前言¶
DeepSeek Harness(DSH)裏,智能體通過 web_search 做聯網檢索。若 profile 沒有可用的搜索 provider,會回退到 @deepseek-ai/dsh-web-search-deepseek,經 DeepSeek 對話 API 完成搜索。DeepSeek API Key 缺失或無效時,每次搜索都會失敗,例如:
DeepSeek API error (HTTP 401): Authentication Fails, your api key: ****d09c is invalid
社區裏也有直接讀 DuckDuckGo HTML、Bing 等公開端點的無 Key 插件,往往只能拿到較薄的摘要、缺少第一方元數據。下面介紹維護者 lovehin 的 dsh-websearch-keyless:對齊 OpenCode WebSearch 服務裏三種可無 Key 調用的後端,註冊爲 ctx.web 的搜索 provider,無需註冊、無需配置即可接管 web_search(web_fetch 仍走內置 HTTP provider)。
這是什麼¶
- 名稱:dsh-websearch-keyless(npm 包名同目錄)
- 分類:聯網工具(SkillHub 社區目錄:lovehin/dsh-websearch-keyless)
- 源碼:GitHub - lovehin/dsh-websearch-keyless
- 許可證:MIT;當前 package 版本 0.1.0;要求 Node >= 20.3.0
插件以 bundle 形式發佈,自帶 cordis.patch.yml,安裝後自動把 web 服務的 searchProvider 指到 opencode-keyless。
核心功能¶
三路後端與降級¶
按優先級依次嘗試,某一端失敗、超時或無結果時落到下一個:
| 順序 | 後端 | 端點 | 無 Key 信號 |
|---|---|---|---|
| 1 | Tavily | POST https://api.tavily.com/search |
X-Tavily-Access-Mode: keyless |
| 2 | TinyFish | POST https://agent.tinyfish.ai/mcp |
X-TinyFish-Access-Mode: keyless |
| 3 | Exa | POST https://mcp.exa.ai/mcp |
無 key 參數 |
實現集中在 lib/providers.js(純 CJS、零依賴)與 lib/index.js(Cordis 插件,向 ctx.web 註冊 WebSearchProvider)。available() 恆爲 true;全部後端均失敗時映射爲 seam 錯誤碼 WEB_PROVIDER_ERROR。
與同類無 Key 插件的差異(README 自述)¶
- 調用與 OpenCode 相同的第一方搜索 API 的 keyless 模式,標題與正文片段更完整,而非 scraped 結果頁 markup。
- 三個獨立 provider,單點限流不會拖垮整條搜索鏈。
- 兩個源文件、零依賴、無構建步驟、不聲明 DSH peer dependencies。
兼容性說明¶
README 寫明在 DSH 0.2.1-rc.3 上做過測試;manifest deliberately 不聲明 @deepseek-ai/* peer 與 engines.dsh,避免版本範圍不匹配導致啓動時被跳過。
安裝與啓用¶
將 <profile> 換成你實際啓動的 profile:desktop 對應桌面應用,web 對應 dsh web。
npx -y @deepseek-ai/dsh plugin --profile <profile> add github:lovehin/dsh-websearch-keyless
插件管理器會同時寫入 dependencies 與 dsh.profile.bundles;作爲 bundle,其 cordis.patch.yml 會自動生效,不必手改 profile 的 patch 層。重啓 DSH 或 reload profile 後 web_search 即可使用。
確認配置是否生效:
npx -y @deepseek-ai/dsh --profile <profile> --dump-config | grep -A3 "^- id: web"
期望看到類似:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: opencode-keyless
fetchProvider: http
手動安裝(CLI 被應用託管拒絕時)¶
若 profile 由 Electron 獨佔管理(例如提示 profile "desktop" is managed exclusively by the Electron application),需將插件放到 ~/.dsh/local-plugins/dsh-websearch-keyless、在 profile 的 node_modules 做 symlink,並在 package.json 的 dependencies 與 cordis.patch.yml 中手工寫入 bundle 條目;patch 中必須同時設置 searchProvider: opencode-keyless 與 fetchProvider: http(見下文 Gotchas)。逐步命令見 GitHub README 的 Manual install 小節。
典型用法與驗證¶
DSH 側無需額外配置項:安裝 bundle 並 reload 後,Harness 內對 web_search 的調用會走 opencode-keyless provider。
倉庫自帶無依賴測試(在插件源碼根目錄執行):
npm test # 離線:解析、降級與插件契約(14 個測試)
npm run test:live # live:探測三個真實端點
npm test 不需要網絡,CI 在 Node 20、22、24 上運行。test:live 會訪問第三方共享端點,適合作爲人工冒煙而非 CI 門禁。
適用場景與注意¶
適合誰:希望在 DSH 裏用原生 web_search,但不想維護 Tavily / Exa 等 API Key,且能接受 keyless 共享配額、偶發零結果或限流的用戶。
運行權限:插件以當前 DSH 進程權限出站訪問上述 HTTPS 端點;安裝前請自行審閱 源碼 與 MIT 許可證。
三個常見坑(Gotchas)¶
-
fetchProvider必須寫全。 對id: web的 patch 替換整個config對象,不會 deep-merge。只改searchProvider會丟掉默認的fetchProvider: http,web_fetch可能報:multiple usable web providers are registered (deepseek-fetch-api, http); configure one explicitly。 -
空的
cordis.patch.yml可能是字面量[]。 直接 append 會變成第二份 YAML 文檔,解析失敗。需先刪掉[]再追加塊。 -
不要給插件加
@deepseek-ai/*peer。 範圍不覆蓋當前 DSH 版本時,啓動會 skip bundle 並提示 incompatible。
故障對照(節選)¶
| 現象 | 可能原因 |
|---|---|
WEB_PROVIDER_CONFIGURED_MISSING |
配置了 searchProvider: opencode-keyless 但插件未加載 — 檢查 dependencies、bundles 與 node_modules 解析 |
all keyless search backends failed |
三路均失敗 — 無外網、代理或共享配額;可試 npm run test:live |
| 搜索無結果 | keyless 配額共享,生僻 query 可能 legitimately 爲零 — 可改寫 query |
卸載:
npx -y @deepseek-ai/dsh plugin --profile <profile> remove dsh-websearch-keyless
結尾¶
dsh-websearch-keyless 把 OpenCode 同款的 Tavily、TinyFish、Exa keyless 鏈路搬進 DSH,用 bundle 一鍵切換 searchProvider,在零 Key、零構建的前提下恢復 web_search。社區索引見 SkillHub 插件頁,實現與安裝細節以 GitHub 倉庫 README 爲準。