aooyoo / dsh-web-search-ddg

已收录

Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no model billing

main模型工具技能 查看源代码

安装

pnpm add dsh-web-search-ddg

此命令根据 GitHub 仓库地址生成。运行前请检查上游 README 与源代码;需要可复现安装时,请固定 release 或 commit。

README

维护者编写的文档快照。

在 GitHub 查看 ↗
提交版本 3b9d739同步于 2026年8月18日

dsh-web-search-ddg

中文 | English

Zero-token DuckDuckGo 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 your local browser: it drives Chrome/Edge/Chromium headless against DuckDuckGo's HTML endpoint and parses the result links out of the dumped DOM.

  • Zero model tokens per search — no API key, no auxiliary model request
  • Zero dependencies — Node builtins only; no Playwright/Puppeteer download
  • Keeps the shipped provider registered — switching is a one-line config change, not an uninstall

Requirements

  • A DSH host (≥ 0.1.0-rc) providing the ctx.web seam
  • A local Chromium-family browser. Detected automatically on macOS (Chrome, Edge, Chromium) and Linux (/usr/bin/chromium, /usr/bin/google-chrome); override with chromePath
  • Node.js ≥ 18

Install

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

Then edit the profile's cordis.patch.yml to mount it and make it the default search provider. Note that a patch row replaces the target row's whole config (no deep merge), so the web row must restate every key — the shipped row owns only searchProvider:

# Select this provider for the model-facing web_search tool.
- id: web
  config:
    searchProvider: ddg-browser

# Mount the plugin (registers provider id `ddg-browser`).
- insert:
    - id: web-search-ddg
      name: dsh-web-search-ddg

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).

Configuration

All keys optional; the row config goes to the insert entry above.

KeyDefaultMeaning
chromePathfirst detected browserAbsolute path to a Chromium-family executable.
timeoutMs20000Per-attempt budget. 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).
virtualTimeBudgetMs8000Chrome's --virtual-time-budget — how long the page may settle before the DOM is dumped.

Behavior notes

  • Latency is ~10–20s per search. The DOM dump is usually ready quickly, but the child process frequently fails to exit on its own (background services never quiesce), so results often land at the timeout guard. The guard reads the buffered output, so the search still succeeds — just not fast.
  • DuckDuckGo anomaly pages fail loudly. When the endpoint serves its anti-bot challenge, the plugin surfaces an explicit error naming the cause and the fallback (switch searchProvider back to deepseek-official). It never silently degrades.
  • The headless UA is overridden with a plain desktop Chrome UA — the endpoint keys on the HeadlessChrome marker and blocks it otherwise. If searches start failing everywhere, DuckDuckGo may have tightened detection; bump the UA string in index.js.
  • Every attempt runs in a throwaway --user-data-dir under the OS temp dir, cleaned up best-effort after the process dies (a leaked temp dir never fails a search).

How it works

  1. spawn the browser with --headless --dump-dom --virtual-time-budget and the UA override against https://html.duckduckgo.com/html/?q=<query>
  2. Read the serialized DOM from stdout; a kill guard bounds hung pages, and buffered output at timeout is accepted
  3. Parse <a class="result__a"> (titles) and <a class="result__snippet"> (snippets); both hrefs are //duckduckgo.com/l/?uddg=<encoded> redirects, so decode the real target URL from uddg and pair title/snippet on it
  4. Return { sources: [{ url, title?, snippet? }], truncated: false } through the seam — the model-facing web_search tool and result cards work unchanged

Development

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

License

MIT

项目文件与信号

以下项目是目录快照中检测到的公开仓库信号。

测试已检测

仓库信息

开发语言
JavaScript
许可证
MIT
最后更新
2026年8月16日 14:19

谨慎安装

请检查源代码、权限、生命周期脚本、依赖与网络访问;不受信任的插件应先在隔离环境中测试。