dsh-plugins
Collection of DeepSeek Harness (DSH) plugins — web-search-omp ported from oh-my-pi (23 providers, fallback chain, credential-free)
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 25, 2026
- Updated
- Aug 25, 2026
Introduction
dsh-plugins
Collection of DeepSeek Harness (DSH) plugins — starting with a faithful port of oh-my-pi's web search stack.
Origin: https://github.com/can1357/oh-my-pi (
packages/coding-agent/src/web/search/**)This repository replicates oh-my-pi's search implementation so DSH gets a search provider that works out of the box (credential-free scrapers) and is not limited to DeepSeek (alternative API providers + fallback chain).
Why?
DSH's built-in @deepseek-ai/dsh-web-search-deepseek requires a DEEPSEEK_API_KEY and a single Anthropic-compatible endpoint. oh-my-pi's search:
- supports 23 providers (
perplexity,gemini,anthropic,codex,xai,zai,exa,tinyfish,jina,kagi,tavily,firecrawl,brave,kimi,parallel,synthetic,searxng,startpage,duckduckgo,ecosia,google,mojeek,public) - parses Google-style query directives (
site:,before:/after:,inurl:,intitle:,filetype:, quoted phrases,ORgroups,-exclusions) - applies lenient post-filtering (
applyQueryConstraints) that relaxes constraints rather than returning zero results - has a provider fallback chain with configurable order/exclusions and automatic credential discovery
- is credential-free by default —
duckduckgo,startpage,searxngetc. work without any API key (perfect forweb_searchtool usability)
This repo ports that logic into a DSH ctx.web provider.
Repository layout
dsh-plugins/
├── README.md
├── .gitignore
└── plugins/
└── web-search-omp/ # DSH plugin: web-search-oh-my-pi
├── package.json
├── tsconfig.json
├── README.md
└── src/
├── index.ts # DSH plugin entry (name/inject/apply/Config)
├── types.ts # SearchProviderId, SearchResponse, etc.
├── query.ts # StructuredQuery parsing & formatting
├── utils.ts # clampNumResults, dateToAgeSeconds, etc.
├── provider.ts # Lazy registry + fallback orchestration
├── orchestrator.ts # Composite WebSearchProvider with chain fallback
└── providers/
├── base.ts
├── utils.ts
├── brave.ts
├── tavily.ts
├── exa.ts
├── perplexity.ts
├── duckduckgo.ts
├── searxng.ts
├── jina.ts
├── kagi.ts
├── firecrawl.ts
├── startpage.ts
├── google.ts
├── ecosia.ts
├── mojeek.ts
├── public.ts
├── anthropic.ts
├── gemini.ts
├── xai.ts
└── ...
Quick start
# Install the plugin into a DSH profile (from the dsh-plugins root)
cd plugins/web-search-omp
pnpm install
pnpm run build
# Link into a running DSH profile
dsh plugin --profile web add ./plugins/web-search-omp
See plugins/web-search-omp/README.md for full configuration (provider order, excluded providers, timeouts, API keys).
How it maps to DSH
| oh-my-pi concept | DSH equivalent |
|---|---|
AuthStorage + listAuthCredentials() | ctx.get("credentials") + launchEnvironmentOf(ctx) env fallbacks |
ModelRegistry | optional, only for LLM-mediated providers |
settings.get("providers.*") | installSettingsSection + settingsNamespace("web-search-omp") |
SearchProvider.search(params) | WebSearchProvider.search(request, signal) on ctx.web |
resolveProviderCandidates() + fallback loop | OrchestratedSearchProvider that walks the candidate list internally |
formatForLLM + hasRenderableSearchContent | normalized WebSearchResult (sources[] + optional content) with truncation enforced by ctx.web |
Replicating oh-my-pi
The port is behavior-preserving:
src/query.tsis a direct port ofpackages/coding-agent/src/web/search/query.ts(tokenizer, directive parsing,formatQuery,formatScraperQuery,applyQueryConstraintswith relaxation)src/providers/*mirror their upstream counterparts (same endpoint, sameBRAVE_SEARCH_URL,TAVILY_SEARCH_URL,EXA,PERPLEXITY, etc., sameclampNumResultsdefaults, same recency maps)- The fallback chain respects
SEARCH_PROVIDER_ORDERderived fromSEARCH_PROVIDER_OPTIONS, withpublicexplicit-only (never in auto-chain) - Error classification (
credit exhausted,401/403) and hard timeout (AbortSignal.timeout+AbortSignal.any) match upstream
License
MIT — same as oh-my-pi and deepseek-harness. See each plugin's LICENSE.