dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH 的 ctx.web 搜索提供方(id: deepseek-search-api):主用 DeepSeek 官方专用检索端点 POST /v1/tools/search(按次计费),失败或空结果时回退到原生(模型)搜索;在「插件」面板提供免重启的配置卡片。
DSH(DeepSeek Harness)ctx.web 的搜索提供方,id = deepseek-search-api,设置页命名空间 = web-search-api。
主路径:DeepSeek 官方专用检索端点 POST {baseURL}/v1/tools/search —— 一次 HTTP,按成功请求计费(5 元 / 1000 次,失败与空结果不计费,无峰谷价)。
兜底路径:Search API 失败或返回空结果时,自动回退到原生(模型)搜索(Anthropic 兼容 Messages + 服务端 web_search 工具)——与官方 @deepseek-ai/dsh-web-search-deepseek 同一请求形状与解析方式,只在主路径不行时才用。
它替换的默认后端 deepseek-official 每次搜索都要跑一个完整模型轮次(官方那个包的 README「开发备注」把"专用检索端点"列为未来工作——现在端点有了,这个包就是补上那一环)。
社区已有若干"搜索后端切换/路由"插件(dsh-search-router、dsh-search-hub、dsh-web-search-* 等),但它们的 DeepSeek 选项走的都是同一个原生链路(api.deepseek.com/anthropic/v1 + web_search_20250305),没有一个打新上线的 /v1/tools/search。要"用上这个按次计费的新端点",本插件是那条路。
| 主路径(Search API) | 兜底(原生搜索) | |
|---|---|---|
| 请求 | 一次 HTTP POST /v1/tools/search | 一次 Anthropic Messages 调用 + 服务端 web_search |
| 计费 | 0.005 元 / 次成功请求 | 无请求费,费用 = 该辅助轮次的输入 + 输出 token |
| 延迟 | 一次 HTTP | 一个完整模型轮次 |
| 可控性 | count(1–50)、need_content、site:/lang:/after: 等检索语法 | 服务端决定条数,只能在返回后截断 |
| 结果字段 | snippet + summary + date + rerank_score + authority | url/title/page_age,snippet 来自 cited_text 引用 |
| 鉴权 | API Key(Authorization: Bearer) | 账号 token(x-dsh-auth-token)或 API Key |
一次估算(deepseek-flash 价格,空闲时段):主路径 ≈ 0.005 元 + 回填 token;兜底 ≈ 0.012 元(未命中缓存)~0.024 元(高峰)。所以高峰时段主路径便宜约 4~5 倍,真正的收益是延迟低一个数量级。
主侧边栏的「插件」面板 → 标题「网页搜索(Search API)」的卡片 → 点进去是配置表单。
⚠️ 它不在「设置」里。这个 build 的设置侧栏(账号与余额 / 通用设置 / 模型 / 内置插件 / 技能与 MCP / Agent 预设 / 插件市场 / 侧边卡片)没有插件配置页——官方那张「网页搜索」卡片同样挂在「插件」面板里(官方 README 写的 "Settings → Plugins → Plugin configuration" 对应的是这个面板)。本插件用与官方卡片相同的机制注册自己的卡片:客户端半身 lib/client.js 往 plugins.item 槽位注册一条,宿主服务其命名空间时才出现。
卡片可编辑 4 个字段(其余字段只在 composition 里改):
| 卡片字段 | 我的键 | 默认 | 说明 |
|---|---|---|---|
| API Key | apiKey | 未设置 | 走凭据服务按 apiKeyEnv 的引用名存储,不写进设置文件 |
| 检索端点 | baseURL | https://api.deepseek.com | 自动追加 /v1/tools/search |
| 单次返回条数 | count | 8 | 1–50;不影响单次价格,宁多别少 |
| 回退时最多搜索次数 | maxUses | 5 | 主路径失败回退到原生搜索时,一次请求最多搜几次 |
| 字段 | 默认 | 说明 |
|---|---|---|
apiKey | 未设置 | 字面值密钥(role=secret,不会随远端响应回传)。优先用 apiKeyEnv |
apiKeyEnv | DEEPSEEK_API_KEY | 凭据引用名(role=credential-ref):先查凭据服务,再查进程环境 |
baseURL | https://api.deepseek.com | Search API 基址,自动追加 /v1/tools/search |
count | 8 | 返回条数 1–50。不影响单次价格,宁多别少 |
needContent | false | 让 Search API 顺带返回正文(不加钱,但回填上下文变贵) |
timeoutMs | 30000 | 单次请求超时 |
fallback | true | 主路径失败(或空结果)时是否回退原生搜索 |
fallbackOnEmpty | true | 空结果是否也算失败 |
fallbackBaseURL | https://api.deepseek.com/anthropic/v1 | 回退用的 Anthropic 兼容基址(缺省时回退读 $DEEPSEEK_SEARCH_BASE_URL) |
fallbackModel | deepseek-v4-flash | 回退用的模型名 |
maxUses | 5 | 回退时一次请求最多触发几次服务端搜索(卡片也编辑它) |
fallbackMaxTokens | 4096 | 回退请求的 max_tokens |
也可以直接写 composition(profile 的 cordis.patch.yml),注意一行的 config 是整体替换,写全:
- id: web-search-api
config:
count: 5
fallback: true
apiKeyEnv: DEEPSEEK_API_KEY
本机(桌面版)已接好:软链进 profile、bundles 已登记、pnpm-lock.yaml 已同形补条目。重启 DSH 生效。
换机/重装时三步:
~/.dsh/plugin-src/dsh-web-search-api,建软链到 ~/.dsh/profiles/<profile>/node_modules/(形状与既有 dsh-kb 一致);或者用 CLI:dsh plugin --profile <profile> add link:/path/to/dsh-web-search-api。node scripts/link-deps.mjs。
link: 装的包不会被 pnpm 安装它自己的依赖,而 Node 从导入文件的真实路径往上找 —— 源码在 plugin-src/ 下,天然找不到 harness 侧的 @deepseek-ai/*。本脚本把 @deepseek-ai/schemastery 链进来;缺了它插件照常工作,只是设置页没有表单(Config 不导出)。cordis.patch.yml 负责(dsh.bundle.patch 声明),不需要动 profile 的 patch。为什么不用手改 profile 的
cordis.patch.yml:bundle 层按dsh.profile.bundles顺序在 profile 层之前应用,本插件排在@deepseek-ai/dsh-base之后,所以它自带的 patch 能覆盖 base 的web条目(config整体替换)。这样卸载插件即自动还原成 base 默认的deepseek-official。
node scripts/cordis-load.mjs # 用 DSH 本体那份真 cordis 加载 + 替身 fetch 跑 20 项断言
node scripts/verify-profile-wiring.mjs
cordis-load.mjs 覆盖:主路径成功 / HTTP 500 回退 / 空结果回退 / 两边皆空 / fallback=false / 无 Key 时直接走原生 / 账号路由鉴权 / 双失败聚合错误 / 请求形状 / 设置表单 schema。
verify-profile-wiring.mjs 覆盖:依赖解析、profile 链接、package.json(依赖 + bundles + 顺序安全)、lock 形状、composition patch 结构、残留覆盖、备份。
运行期怎么判断走的哪条路:
web/deepseek-search-llm-request 会话事件 = 主路径在跑(那是原生链路的标记事件)。[dsh-web-search-api] Search API ... 已回退原生搜索 的 warn 日志。web-search-api 表单 = bundle 已加载、schema 已投影。cordis.patch.yml 里的 - id: web 段,重启;或在 profile 的 patch 里写一段 - id: web 覆盖成 searchProvider: deepseek-official(覆盖是整体替换,两个键都要写)。dsh plugin --profile <profile> remove dsh-web-search-api;手工装的话删 bundles 那行、删 lock 条目、删软链。{package.json,pnpm-lock.yaml,cordis.patch.yml}.bak-before-web-search-api 覆盖回去。@deepseek-ai/*,所以错误用带 code 的普通 Error(WEB_PROVIDER_ERROR / WEB_PROVIDER_CREDENTIAL_MISSING / WEB_ABORTED)而不是 harness 的 WebError;node scripts/link-deps.mjs 只补 schemastery 这一条解析路径,不为错误类型引入依赖。needContent=true 时 Search API 返回的正文会被丢弃:seam 的来源形状只有 url/title/snippet/publishedAt,装不下正文。想让模型读正文,用 web_fetch。MIT。