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. 오후 2:19

신중하게 설치하기

소스 코드, 권한, 수명 주기 스크립트, 의존성 및 네트워크 접근을 검토하고 신뢰하지 않는 플러그인은 격리 환경에서 테스트하세요.