dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Tavily search and extract providers for DSH (DeepSeek Harness): runs the built-in web_search and web_fetch through Tavily. Zero dependencies, no build step.
让 DSH 内置的 web_search 和 web_fetch 改走 Tavily,替代随附的 DeepSeek 搜索通道与本地 HTTP 抓取通道。
ctx.web),模型侧仍然是原来的 web_search / web_fetch,参数、结果卡片、引用格式全部不变。fetchProvider 改回 http 即可(见 6)。package.json 声明 dsh.seams: ["web"],离线自测锁定它与 inject 一致。npm test 不需要网络、不需要安装依赖、不需要装 DSH;npm run test:schema 在 npm install 后校验设置 schema。免责声明:这是个人/本地插件,与 DeepSeek 官方、Tavily 官方均无关。
DSH 目前是 developer preview,本插件针对 0.2.1-rc.3 的 seam API 编写;它依赖的ctx.web.registerSearchProvider/registerFetchProvider、设置槽位与客户端 primitives 可能随 DSH 版本变化。
项 · 要求 DSH · 已在 0.2.1-rc.3 上核对接口(peerDependencies 声明为 ^0.2.0-rc.2) Node · >= 20.3.0 —— 用到 AbortSignal.any() 运行依赖 · @deepseek-ai/schemastery ~3.18.5(设置页/schema 用;缺失时插件仍可搜索,但设置页不出现) 安装 · 本地 link: 安装需在插件目录执行 npm install;发布包由包管理器自动安装依赖 构建步骤 · 无(client.js 手写)
DSH 的 web 访问是一个可插拔的 seam(@deepseek-ai/dsh-web,即 ctx.web):
组件 · 角色 @deepseek-ai/dsh-tool-web · 面向模型的 web_search / web_fetch 工具 @deepseek-ai/dsh-web · seam 本身:注册搜索/抓取提供方,并按 id 选择提供方 @deepseek-ai/dsh-web-search-deepseek · 随附的搜索提供方(id:deepseek-official) @deepseek-ai/dsh-web-fetch-http · 随附的抓取提供方(id:http)
DSH 没有内置 Tavily 提供方,所以接入只需要两件事:
tavily 搜索/抓取提供方的插件(本包);web 行的 searchProvider / fetchProvider 改成 tavily。这两件事都在本包的 cordis.patch.yml 里完成(组合包 patch 层在 dsh-base / dsh-web-app 之后应用,同一行最后写入者生效,因此可以覆盖默认值)。
⚠️ 必须显式固定 provider id:deepseek-official 只要存在 key 解析器就报告「可用」,如果两个提供方同时可用且没配置 id,web_search会以WEB_PROVIDER_AMBIGUOUS失败。
本包的 patch 已经替你固定好了。
tvly- 开头的 key;web_search 消耗 1 次搜索额度(includeAnswer 会额外消耗),一次 web_fetch 消耗 1 次 extract 额度(extractDepth: advanced 更多)。
key 有三种放法,推荐设置页或环境变量,避免把密钥写进文件:
方式 · 存储位置 · 说明 Settings → Tavily(推荐) · DSH 凭据库(~/.dsh/.credentials.yaml) · 页面写入 TAVILY_API_KEY;可显示已配置/只读状态;不写进 profile patch 环境变量 · 启动 DSH 的进程环境 · 与凭据库同名引用;页面会显示为只读 字面 apiKey · cordis.patch.yml · 优先级最高,适合临时/overlay;会明文落盘
优先级:字面 `apiKey` > 凭据库 > 环境变量。
# 当前 shell(临时)
$env:TAVILY_API_KEY = 'tvly-...'
# 用户级(需要完全重启 DSH 才继承到)
[Environment]::SetEnvironmentVariable('TAVILY_API_KEY', 'tvly-...', 'User')凭据库的引用名由 apiKeyEnv 控制,默认 TAVILY_API_KEY;一般不需要改。页面检测到 patch 里的字面 apiKey 时会禁用密钥输入并提示优先级,避免“保存了 key 却不生效”。
配置在 cordis.patch.yml 中 web-tavily 行的 config 里;标 是 的字段也可以在 Settings → Tavily 页面里编辑(保存后立即生效,不需要重启)。
字段 · 默认 · 设置页 · 说明 apiKey · 无 · 否 · 字面 key(tvly- 开头),优先级最高;页面检测到它会禁用凭据输入 apiKeyEnv · TAVILY_API_KEY · 否(高级) · 凭据库引用名;页面按它读写密钥 baseURL · https://api.tavily.com · 是 · Tavily 地址;可指向网关/代理,末尾不要斜杠 searchPath · /search · 否 · 搜索端点路径,仅当网关改写了路径才改 extractPath · /extract · 否 · 抓取端点路径,同上 timeoutMs · 15000 · 是 · 单次搜索超时 fetchTimeoutMs · 30000 · 是 · 单次抓取超时 maxResults · 8 · 是 · 本提供方上限(≤ 20);调用方只能往下压,不能往上抬 searchDepth · basic · 是 · basic / advanced / fast / ultra-fast topic · general · 是 · general / news / finance timeRange · 不发送 · 是 · day / week / month / year days · 不发送 · 是 · 仅 topic: news 有意义,最近 N 天 country · 不发送 · 是 · 两位国家代码,例如 us / cn includeAnswer · false · 是 · false / true / basic / advanced;开启后模型会直接拿到一段答案(消耗额外额度) includeDomains · [] · 是 · 只搜这些域名;页面用逗号/空格分隔,patch 里可写数组 excludeDomains · [] · 是 · 排除这些域名;同上 extractDepth · basic · 是 · basic / advanced extractFormat · markdown · 是 · markdown / text maxBodyChars · 100000 · 是 · 抓取正文字符上限,超出截断并标记 truncated userAgent · dsh-tavily/ · 否 · 请求 UA,默认值跟随 package.json 的 version headers · {} · 否 · 额外请求头(网关鉴权用);同名时覆盖默认的 `authorization`
页面保存的 volatile 字段写入当前 profile 的 cordis.patch.yml,Host 的下一次请求就会读到,不需要重启。直接改 patch 文件里的非 volatile 字段(searchPath / extractPath / userAgent / headers)仍需让组合包重新加载:桌面端完全重启 DSH;dsh web / dsh tui / dsh headless 下次启动生效。
Host 半边现在声明 Config(@deepseek-ai/schemastery),换来:
web-tavily namespace 被 dsh-settings 提供给浏览器半边,Settings → Tavily 里出现表单;apply() 里的 options thunk 下次请求就重读,不需要重启;TAVILY_API_KEY。代价与注意事项:
@deepseek-ai/schemastery ~3.18.5(DSH 自身同款版本)。本地 link: 安装需要在插件目录 npm install;发布包由包管理器安装。index.js 会动态 import 失败并降级:搜索/抓取照常,设置页不出现,控制台给出警告。这样不会因为漏装依赖导致整行加载失败。npm run test:schema;DSH 升级客户端 primitives 时设置页可能需要跟着调整。searchPath / extractPath / userAgent / headers 仍是 patch-only(高级字段,页面不渲染)。本包已通过 link: 安装进桌面 profile;下面是通用的安装方式。
npm install(安装设置页/schema 所需的 @deepseek-ai/schemastery);D:\path\to\dsh-tavily;npm install # 先装本包自己的依赖
dsh plugin --profile web add "D:/path/to/dsh-tavily"profile 之间互不相干:装进哪个 profile,就只有那个 surface 生效(桌面端是 desktop,只能由 App 管理器安装)。
--patch overlay 临时覆盖$env:TAVILY_API_KEY = 'tvly-...'
dsh web --patch ./examples/dsh-tavily.overlay.ymloverlay 只重述已存在的 row,前提是该 profile 里已装本包。
npm install(本地 link: 安装不会自动装 link 目标的依赖);TAVILY_API_KEY(或 apiKey,或安装后在 Settings → Tavily 里保存);新装/改动组合包后不重启,运行中的 DSH 仍然在用旧组合——表现就是「插件卡片显示已装,但 web_search 还在走 DeepSeek」。新增 dsh.client 声明也必须完全重启,浏览器半边才会被加载。
把 profile 里 web 行的 searchProvider / fetchProvider 改回 deepseek-official / http(或禁用 web-tavily 行),重启即可。
搜索(POST /search):
Tavily · DSH results[].url / title / content · sources[].url / title / snippet(按 url 去重,无 url 丢弃) results[].published_date · sources[].publishedAt answer · WebSearchResult.content(模型优先读的一段答案)
抓取(POST /extract):
Tavily · DSH results[].raw_content · body { kind: 'text', content }(Tavily 已转成 markdown/text) failed_results[].error · 不抛错,返回 statusCode: 502 的结果,正文写明原因
用 Tavily 接管抓取有三个实际影响,装之前请确认:
extractDepth: advanced 更贵);http://192.168.x.x、http://localhost 之类不可用。如果这三点里任何一条不能接受,就只换搜索:把 cordis.patch.yml 里 web 行的 fetchProvider: tavily 改成 fetchProvider: http,web_fetch 继续走随附的本地 HTTP 提供方(带私网拦截、同源重定向限制等安全策略)。
npm test # smoke + 浏览器半边注册检查,不需要 node_modules
npm run test:schema # 需要先 npm install,校验设置 schema
npm run test:all # 两者一起跑test/smoke.mjs 覆盖:注册 id、可用性判断、环境变量/凭据库解析、字面 key 优先、缺 key 错误、URL/路径规范化、请求体构造与上限夹逼、结果映射/去重/截断、真实 HTTP 往返(内置 mock Tavily)、401/429/432 报错、取消、超时、不可达、抓取截断、failed_results 降级为结果、URL 策略、dsh.seams 与 inject 一致、dsh.client 清单、patch 结构、发布文件无 UTF-8 BOM。
test/client.mjs 用假的 window.__ModuleLoader__ + mini React/primitives/store 桩执行 client.js,覆盖:模块 id、浏览器半边 inject、settings.section 注册参数(id/order/locale)、whileServed('web-tavily')、页面 hook/actions、字面 key 检测。
test/schema.mjs 覆盖:schema 可被 Schemastery 重建、secret/credential-ref/volatile 元数据、默认值与 normalizeConfig 一致、非法值被拒、覆盖值通过 ref 读出。
maxResults 等字段并保存,检查 ~/.dsh/profiles//cordis.patch.yml 出现/更新 web-tavily 行;~/.dsh/.credentials.yaml 出现 TAVILY_API_KEY 条目(不要打印值),页面显示「已配置」;web_search(例如「搜索 deepseek harness」),看来源是否来自 Tavily;web_fetch(给一个公网 URL),看是否返回 markdown 正文;web-tavily 行后重启/刷新,Settings → Tavily 应消失;重新启用后恢复。缺 key 时现在会报 WEB_PROVIDER_CREDENTIAL_MISSING(不再是 WEB_PROVIDER_CONFIGURED_UNAVAILABLE),见 8。
现象 / 错误码 · 原因与处理 WEB_PROVIDER_CONFIGURED_MISSING · 组合包没启用/没装成功,tavily 提供方没注册;确认已重启 DSH WEB_PROVIDER_CONFIGURED_UNAVAILABLE · 已注册但 available() 为 false:baseURL 不合法或超时预算非法。缺 key 现在报 WEB_PROVIDER_CREDENTIAL_MISSING,不再走这个错误 WEB_PROVIDER_CREDENTIAL_MISSING · 已注册但没有可用 key:在 Settings → Tavily 保存、或设 TAVILY_API_KEY、或在 patch 里写 apiKey Settings 里没有 Tavily 一节 · ① 没 npm install(缺 schemastery,控制台有警告);② web-tavily 行被禁用;③ 没完全重启(新 dsh.client 需要重启);④ 该 profile 没装本包 页面显示「未配置」但搜索可用 · key 来自环境变量或 patch 的字面 apiKey;字面 apiKey 优先级最高,页面检测到后会禁用输入 页面提示字面 apiKey 但实际用环境变量 · patch 里有一行空的 apiKey: ''(设置服务把“存在”视为已设置)。删掉这行,或填入非空 key 页面显示只读 · 当前 profile 的设置为只读,或密钥由环境变量提供(describe 报 writable=false) 页面保存失败 · 设置文档 revision 冲突或 Host 拒绝;草稿保留,刷新后重试 凭据服务不可用 · credentials 服务没挂载:key 字段禁用,改用环境变量或字面 apiKey WEB_PROVIDER_AMBIGUOUS · web 行的 provider id 没被钉住(patch 层顺序被更高层覆盖)。在 profile 的 cordis.patch.yml 里显式写 searchProvider: tavily Tavily search returned HTTP 401 · key 无效或过期:核对设置页 / apiKey / TAVILY_API_KEY HTTP 429 · 速率限制:降低请求频率后重试 HTTP 432 / HTTP 433 · 计划额度 / PAYGO 额度用尽:去 Tavily 控制台加额度或升级 HTTP 400 · 参数被拒:检查 searchDepth / topic / timeRange / days / 域名列表 timed out after ...ms · 提高 timeoutMs / fetchTimeoutMs,确认 DSH 主机到 api.tavily.com 的网络与代理 request to ... failed · 端点不可达:检查 baseURL、代理、DNS web_fetch 返回 502 + could not extract ... · Tavily 抓不到该页(404/反爬/PDF 等):换 URL 或用本地 fetchProvider: http web_fetch 报 WEB_INVALID_URL / WEB_BLOCKED_URL · 只接受 http(s) 且 URL 里不能带用户名密码 装了但 web_search 还走 DeepSeek · 没完全重启 DSH;或该 profile 里 web 行仍是 deepseek-official 插件卡片显示「已关闭」 · 运行中的 DSH 是在装插件之前启动的。完全重启
api.tavily.com / docs.tavily.com 解析到198.18.0.0/15(代理 fake-IP 段),DSH 自带的 web_fetch 会以「解析到非公网 IP」拒绝; 插件的 fetch 走 Node 原生实现、通常会经系统代理,但没有真实 key 就没有验证过。 安装后第一次调用请按 7.2 现场确认。
search_depth、include_answer、raw_content、failed_results 等)与 401/429/432/433 语义按公开文档与官方 SDK 行为实现;文档站不可达时 无法二次核对。
TAVILY_API_KEY)后 available() 就为 true,真正的 key 在每次请求时解析;缺 key 时由 WEB_PROVIDER_CREDENTIAL_MISSING 报出,而不是 让 seam 报 WEB_PROVIDER_CONFIGURED_UNAVAILABLE。这是为了支持凭据库/环境变量在运行时变化。
SettingsFormModel / SettingsForm /SettingsValueField / SettingsSecretField 是 0.2.1-rc.3 的基线模块 API;DSH 升级后 可能需要按新版本调整 client.js(与 dsh-cloud-control 的浏览器半边同类风险)。