dsh-search-ledger
Routes web search and fetch, records estimated costs, and provides local budgets, circuit breakers, and diagnostics. Requires Node.js >=22.19 and DSH 0.2.1-rc.2 or 0.2.1-rc.3.
Install
dsh plugin --profile web add dsh-search-ledger
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
DSH Search Ledger
简体中文 · [English](./README.en.md)
DSH 原生 web_search / web_fetch 的渠道管理和费用统计插件。
在 DSH 里同时用 DeepSeek 官方 API、中转和其他搜索服务时,搜索该走哪个渠道、失败后换谁、用了多少次,都需要分开配置和查看。这个插件把这些事放到一个页面里:按模型 Provider 绑定搜索渠道,管理每个渠道的 Key,再用本地账本记录实际请求。
当前版本为 0.6.2,清单只声明 DSH 版本下限 >=0.2.0-rc.2、不设上限,升级 DSH 不会因版本声明被拒。它统计的是经过插件的搜索和抓取请求,不是模型 Token 用量;显示的费用是本地估算,不能代替服务商账单。
功能
- Search 和 Fetch 可以选不同渠道,也可以按 Provider、全局或会话单独覆盖。
- 官方 API 和中转分别设置价格、币种及计费方式,不把它们混在一起算。
- 一个渠道可以保存多个 Key,每行一个。正常请求轮换起点,遇到失败先尝试同渠道的其他 Key。
- 可以开启有序切换。缺 Key 的引擎直接跳过,失败、限流或超时后按配置顺序尝试下一个渠道;成功或合法的空搜索结果会停止切换。
- 每次实际尝试都会单独记账。同一轮切换通过
operationId关联,历史记录使用请求当时的价格,不会随当前配置重新计算。 - 用量可以按日期、渠道、来源 Provider、会话和币种筛选。界面支持深色、窄面板、键盘操作和长下拉列表。
- 诊断页可只读检查后端接管、Provider 路由与候选凭据状态,并按操作关联最近的账本尝试。它不会测试 Key 或发送搜索请求。
- 用量页支持导出 CSV / JSON;开发版本还包含可选的预算与渠道熔断状态,默认不启用。
Key 可以直接在界面填写,也可以逐个测试。测试需要先确认费用风险,不会自动保存输入或切换到别的渠道。
和只接入搜索 API 的插件有什么区别
这里多做的一层,是把请求路由和费用记录连起来。
例如,官方 DeepSeek Provider 的 Search 走官方 API,中转 Provider 的 Search 走中转,Fetch 则统一走本地 HTTP。三者可以各用各的价格和凭据,不必为了换一个操作而更换整套搜索配置。
失败后的账目也会保留。第一个渠道超时,第二个成功,不意味着只发生过一次请求。插件会留下前一次尝试,并把无法确认的结果单独标出来。价格没填时显示未知,不会因为金额暂时算不出来就显示成免费。
如果需要在多个 Provider 和搜索服务之间分配请求,或者想查清一次调用走了哪里、费用为什么增加,这些记录会比较有用。它不做全账户账单同步,也不会自动挑选最便宜的服务、搜集公共搜索实例或悄悄启用收费接力。这里介绍的是本插件的做法,不是对某个第三方插件的测试结论。
支持的渠道
渠道 · Search · Fetch · 备注
DeepSeek 官方 API · ✓ · ✓ · Search、Fetch 分别计价
DeepSeek 兼容中转 · ✓ · ✓ · 需要兼容工具 API,只支持聊天接口不够
TinyFish · ✓ · ✓ · 使用对应操作的官方 API 地址
百度千帆 · ✓ · — · 只支持 Search
Tavily · ✓ · ✓ · basic Search / Extract;credits 在本地保守预留
SearXNG · ✓ · — · 自建或获准使用的实例,需要启用 JSON 输出
本地 HTTP · — · ✓ · 复用 DSH 抓取后端,没有本插件按次收取的 API 费用
是否免费、能用多少次,要看服务商的账户计划。SearXNG 和本地抓取也有部署、网络及目标站点访问成本,不代表无限免费。
安装
本版本需要 Node.js ≥22.19 和 DSH ≥0.2.0-rc.2(只有下限,没有上限),DSH 升级后不会被判定为不兼容;开发与测试基线是 DSH 0.2.1-rc.2,其他版本未逐一验证。
从 npm 安装
安装前先退出共享 DSH_HOME 的 DSH 进程,备份目标 Profile 和插件数据:
dsh plugin --profile web add "dsh-search-ledger@0.6.2" --ignore-scripts
把 web 换成实际 Profile。普通 npm install 只会把包加入当前 Node 项目,不会替 DSH 注册插件或应用 patch。遇到 minimumReleaseAge 拒绝时,先检查依赖或等待版本满足时间要求,不要删除锁文件或全局关闭保护。
从 0.6.0 或更早版本升级
此版本不会自动迁移旧配置、凭据和账本。旧渠道配置与 Key 池不会自动迁移;升级后可能需要恢复配置并重新填写 Key。旧池 Key 不会在界面回显,如没有留存,请在服务商处重新生成;不要把 Key 写入配置文件。
1. 完全退出共享该 DSH_HOME 的所有 DSH 进程,先备份整个 Profile、宿主凭据存储以及 $DSH_HOME/web-search-billing/。备份须包含数据库及相关文件和 installation-salt,不要只复制正在写入的数据库。
2. 检查 $DSH_HOME/dsh-search-ledger/:目标目录已存在时停止,不要覆盖、删除或合并;其中可能已有新账本。保留两份数据并先确认迁移方案。
3. 目标目录不存在且确认全部进程已停止时,可将旧目录完整复制到新目录,保留原目录作为备份。数据库及 installation-salt 必须一起保留;这一步只处理账本,不会迁移配置和 Key。
4. 在 Profile 配置中检查旧的 web-search-billing 配置入口;备份后将相关渠道、Provider 绑定、覆盖和故障转移配置迁移到 dsh-search-ledger 对应入口。不要盲目替换其他插件的配置。
5. 确认当前安装的包名:0.5.1 的包名已是 dsh-search-ledger,早期包可能是 dsh-web-search-billing。按实际情况升级或先移除旧包;不要在同一 Profile 中同时安装两个包。
6. 重启后检查历史账本、渠道配置、路由与 Key 状态。旧池 Key 需要在新渠道中重新输入并保存;确认无误后再发起请求。原始备份应保留到验证完成。
此手动流程尚未覆盖所有宿主配置和冲突场景;迁移前如不确定配置来源或目标目录状态,先停止并保留备份,不要强制继续。
配置
重启 DSH 后,在设置侧边栏打开 DSH 搜索账本,按下面的顺序配置:
1. 在 渠道管理 添加渠道,填写名称、地址和费率,保存渠道配置。新建渠道默认停用,不会自动发送请求。
2. 展开渠道,在 API Key 区域每行输入一个 Key,保存 Key 池。之后再次保存会替换整个池,不是追加。已经保存的 Key 不会显示出来。
3. 在 渠道地址、费率与高级配置 勾选“启用”,再保存渠道配置。保存 Key 和启用渠道是两件事。
4. 到 Provider 与覆盖,为实际的模型 Provider ID 分别选择 Search、Fetch 渠道并保存。覆盖顺序是:会话覆盖 → 全局覆盖 → Provider 绑定。
5. 确认宿主 Web 工具使用 web-search-metered / web-fetch-metered 后端,发起一次原生调用,再去 用量与费用 看最近记录。
安装 patch 会选择这两个后端,但其他更高优先级的配置可能覆盖它。插件不默认绑定模型 Provider,也不会在没有绑定时自行选择收费渠道。
需要自动切换时,在对应操作下打开“有序切换”,调整渠道顺序和超时预算。配置示例在 [provider-routing.patch.yml](./examples/provider-routing.patch.yml),其中的 Provider ID、地址和价格都需要按实际情况修改。
测试 Key
选择 Search 或 Fetch,再点击“测试 Key”。输入框有内容时测本次输入,为空时测已保存池或兼容凭证引用。测试后输入会保留,需要自己点保存。
每个 Key 只试一次,单 Key 最多 10 秒,整批最多 60 秒。测试不切换渠道,但可能收费,也会写入账本。Fetch 的测试目标固定为 https://example.com/。超时、限流和网络错误不一定是 Key 无效,也不能说明服务商没有扣费。
Key 池最多支持 32 个 Key。正常请求的轮换游标在当前进程内共享,重启后重置。
诊断与导出
在“诊断”页选择 Provider 和 Search / Fetch,查看后端接管证据、默认路由及候选凭据状态。凭据可读取不等于认证有效;默认路由不包含会话覆盖。时间线最多读取最近 200 条尝试,达到上限时同一次操作可能显示不完整;没有记录的跳过或安装前调用不能推断。
诊断 JSON 导出需要确认,包含插件版本、自检状态、结果统计及最近尝试的操作、状态、时间和 HTTP 状态码,不包含渠道名、Provider ID、Key、查询词或网页正文。时间仍可能敏感,分享前请检查。用量页的 CSV / JSON 是另一个导出,包含渠道和来源 Provider 等元数据,每次最多 20,000 条。
预算与熔断设置目前通过宿主配置文件设置,界面提供状态查看和熔断复位。预算仅依据当前 Profile 的本地账本,金额只统计已确认费用;超时、其他客户端的用量及并发请求可能导致实际费用超过上限,不能代替服务商的账户限额。熔断或预算开启后可能改变派发行为,请先了解配置再启用。
费用怎么算
统计单位是实际 API 尝试,不是聊天轮数。一次工具调用里有多个查询时,可能发送多次底层请求。
DeepSeek 官方渠道默认给 Search 和 Fetch 各设置 5 CNY/千次,按 HTTP 200 且结果非空确认计费。这是插件的默认配置,不会实时同步服务商价格。中转可以独立填写单价,选择非空成功或所有 HTTP 200 计费,具体口径要自己与服务商核对。
例如,单价 5 元/千次,10 次计费成功就是 0.05 元。金额在内部用整数微单位累加,CNY 和 USD 分开显示,不自动换汇。
账本会分别显示计费成功、空结果、明确失败、未确认和未知价格。请求发出后超时、断连或响应无法解析时,可能无法确认服务端是否计费,因此不会直接按免费处理。后续切换成功,也不会删掉前面的尝试。
插件只能记录经过自己后端的请求。其他插件、设备、模型服务端内部搜索,以及安装前没有被观测到的调用,都不在统计范围内。
Tavily 的 credits 也只是本地保护。同一 DSH_HOME 下,相同 Key 在不同渠道和 Profile 间共享本地额度;其他工具、设备或 DSH_HOME 的消耗无法统计,不能据此保证整个账户不超支。
数据和备份
Key 池保存在宿主凭据存储中,按 DSH_HOME、Profile 和渠道隔离,不写进插件配置或账本,也不覆盖模型的同名凭证。宿主默认的本地存储不是加密保险箱,仍然需要保护本机账户和文件。
账本不保存 Key、Authorization、查询词或网页正文,只保留渠道身份、请求归属、时间、状态和价格等计量信息。数据目录是 $DSH_HOME/dsh-search-ledger/。
备份前停掉共享该目录的进程,把数据库及其相关文件和 installation-salt 一起保留。不要只复制正在写入的主数据库。旧账本升级前会先做一致性备份;失败不会自动删除账本。也不要在同一目录混跑新旧版本,或只修改数据库版本号来回退。
有历史账目的渠道仍能正常使用,只是不能删除或更换地址归属。要换服务就新建渠道,不再用的可以停用。修改名称或价格不会重算历史账目。
常见问题
渠道已经保存,为什么还是不能选?
先到渠道高级配置里勾选“启用”并保存。停用渠道会列出原因,但不能选择。千帆只支持 Search,不会出现在 Fetch 下拉框里。
搜索过了,为什么用量是空的?
检查宿主后端、Provider 绑定、Key 和渠道启用状态,再看看日期与币种筛选。配置看起来正确,不代表请求已经成功;没有经过插件的调用也不会入账。
“已有请求记录”是不是说渠道不能用了?
不是。这个提示是在保护历史账目,不是在停用渠道,也不是连通性检测。只要渠道启用、凭据和路由有效,就能继续使用。
卸载会删除账本吗?
不会。退出 DSH 后运行下面的命令,把 web 换成实际 Profile:
dsh plugin --profile web remove dsh-search-ledger
卸载不会自动擦除历史数据。
开发
node scripts/check.mjs # 类型检查、测试、构建和发布契约 node scripts/test.mjs # 只跑行为测试 node scripts/typecheck.mjs # 只检查 Host / Client 类型
0.5.1 功能基线通过了 235 项行为测试,仓库也包含打包、真实 Renderer Loader 和桌面安装入口的契约检查。浏览器检查覆盖保存后展开、窄面板、深色、缩放和 2000 项菜单。
这些验证使用合成 Key 和模拟响应,不代表所有服务商真实账户或所有 Electron 环境都已经测过。固定宿主开发依赖仍有已记
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::4,最后更新 2026-11-03