dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no model billing
中文 | English
Zero-token web search provider for the DeepSeek Harness (DSH) web capability seam (ctx.web).
DSH's shipped search route (deepseek-official) performs every web_search as a full billed model round trip on deepseek-v4-flash — even when your session model is something else entirely. This plugin replaces that with two zero-cost engines tried in order, first success wins:
0.1.0-rc) providing the ctx.web seam/usr/bin/chromium, /usr/bin/google-chrome); override with chromePath. The Bing engine needs no browser.AbortSignal.any used for fetch timeouts when available)In your DSH profile directory (e.g. ~/.dsh/profiles/web), install the package as an out-of-tree plugin:
pnpm add dsh-web-search-ddg
Declare it as a profile bundle so DSH loads it as a first-class layer (visible in the plugin manager, clean removal):
// profile package.json → dsh.profile.bundles
"bundles": [..., "dsh-web-search-ddg"]
Then select the provider in the profile's cordis.patch.yml:
# Select this provider for the model-facing web_search tool.
- id: web
config:
searchProvider: ddg-browser
Note: a patch row replaces the target row's whole config (no deep merge), so the
webrow must restate every key — the shipped row owns onlysearchProvider. Theinsertofweb-search-ddgitself comes from the package'sdsh.bundlepatch and needs no manual row.
The shipped web-search-deepseek row stays untouched: its provider remains registered and available, so switching back is one line (searchProvider: deepseek-official). DSH's selection is a single explicit id, not a priority chain — there is no silent fallback by design.
Verify the composed tree without starting the host:
dsh --profile web --dump-config | grep -A2 searchProvider
Restart the host to apply (host-side plugin rows do not hot-reload).
All keys optional; the row config goes to the insert entry above.
| Key | Default | Meaning |
|---|---|---|
engines | ["bing", "duckduckgo"] | Engine execution order. Supported: "bing", "duckduckgo". First success answers. |
chromePath | first detected browser | Absolute path to a Chromium-family executable (DuckDuckGo engine only). |
timeoutMs | 20000 | Per-attempt budget for the DuckDuckGo engine. On timeout, buffered DOM output still counts as success (Chrome's --dump-dom process often lingers after printing). Two attempts run per search; keep 2 × timeoutMs under tool-web's searchTimeoutMs (DSH ships 60s). |
virtualTimeBudgetMs | 8000 | Chrome's --virtual-time-budget — how long the page may settle before the DOM is dumped. |
searchProvider back to deepseek-official. It never silently degrades.HeadlessChrome marker and blocks it otherwise.--user-data-dir under the OS temp dir, cleaned up best-effort after the process dies.Bing engine — fetch the SERP with desktop-Chrome headers and bootstrapped cookies; parse <li class="b_algo"> blocks for title + snippet; unwrap result links (/ck/a?…&u=a1<base64url>) into real target URLs.
DuckDuckGo engine — spawn the browser headless (--headless --dump-dom --virtual-time-budget, UA overridden) against https://html.duckduckgo.com/html/?q=<query>; read the serialized DOM with a kill guard (buffered output at timeout still counts); parse <a class="result__a"> titles and <a class="result__snippet"> snippets, decoding the real URL from each redirect's uddg parameter and pairing on it.
Both engines return { sources: [{ url, title?, snippet? }], truncated: false } through the seam — the model-facing web_search tool and result cards work unchanged.
ddg-browser: all search engines failed (…) names every engine's last error:
| Message fragment | Meaning | Remedy |
|---|---|---|
connection reset / rate-limited | Your IP is temporarily flagged by the engine | Switch networks (e.g. phone hotspot) or wait hours; flags decay |
anomaly/challenge page | DuckDuckGo anti-bot challenge served | Same as above; also check the UA string still matches a current Chrome |
no parsable results/links | The engine's markup changed | Update this plugin, or file an issue |
browser did not finish within Nms | Browser hung without producing DOM | Raise timeoutMs; check the browser launches at all |
npm test # end-to-end: registers on a stub ctx.web and runs one real search
CHROME_PATH=/path/to/browser npm test
TEST_QUERY="something else" npm test