Skip to content

Releases

v0.6.0

Choose a tag to compare

@DreamRift DreamRift released this 01 Nov 07:41

dsh-web-search-pool 0.6.0

Added

  • 接管 ctx.web.fetch(web_fetch 工具):服务级接管从 web.search 扩展到 web.fetch(2026-11-01 依桌面版 0.2.1-rc.5 app.asar 核对)。启用后 AI 仍调用同一个 web_fetch 工具,抓取走 Tavily Extract(POST /extract),不再消耗 DeepSeek 平台的 Fetch API 额度;结果映射为 seam 同形结构。
  • fetch 调度与门禁:SearchPoolProvider.fetch 复用搜索的 key 池调度、限流、熔断与 Tavily 额度门禁(额度门禁抽为 _quotaGate,search/fetch 共用);抓取只走 Tavily key(Exa 的 /contents 未接),池里没有 Tavily key 时抓取返回不可用。
  • fetch 独立开关与回退:fetchEnabled(默认 true,关闭后 web.fetch 原样走宿主 fetch provider)与 fetchFallbackToOfficial(默认 false);服务级 patch 不可行时按官方 fetch provider id(deepseek-fetch-api → http)降级替换,禁用态委托同搜索模式。
  • Tavily Extract 高级参数:providers.tavily.fetchDepth(默认 basic——advanced 按 2 credits/URL、basic 按 1 credit/5 URL,成本差约 10 倍;JS/反爬站点抓不到正文再改 advanced)与 fetchFormat(默认 markdown)。
  • SearchPoolProvider 构造期 fetchImpl 注入点:与适配器层既有 fetchImpl 设计对齐,测试不再依赖全局 fetch 猴补丁。
  • 回归用例 18 个(tests/search-pool-fetch.test.js),全量 154 用例通过。

完整变更见 CHANGELOG.md。安装与配置见 README 与 docs/。

v0.5.1 — 修复 5xx/超时下 failover 不推进(issue #1)

Choose a tag to compare

@DreamRift DreamRift released this 21 Oct 14:30

修复:单次搜索内不重复重试同一个失败的 key(#1)

第一个被选中的 key 若返回 HTTP 5xx / 401 / 网络错或单次超时(不是 429),同一次搜索的下一轮又会选中它;maxAttempts = keyPool.totalKeys 很快用尽,同供应商的健康 key 和下一个供应商都不会被尝试。最常见的「1 个 Tavily key + Exa 兜底」配置在 5xx/超时时不切换,上游挂起时每次搜索耗满宿主预算(默认 30s)后失败。

根因

  • _search 每轮重新 scheduler.acquire(),不排除本次搜索已试过的 entry;
  • acquire() 无排除参数,smooth WRR 按 max(1, rpm) 加权,高权重 key 连续胜出(单 key 供应商时它就是唯一候选);
  • 非 429 失败只累加 failCount,要连续 allowedFails(默认 3)次才冷却,所以下一轮仍是候选;
  • 原超时换 key 用例两个 key rpm 都是 60,WRR 恰好交替,测试假绿。

修复

  • Scheduler.acquire(exclude?) 新增调用级排除参数:候选在冷却过滤之外再排除已试 entry,不写冷却、不改失败计数、不影响权重累加;
  • SearchPoolProvider._search 维护 tried 集合,选中 entry 后先登记再走凭据/闸门 —— 一次搜索内每个 entry 至多尝试一次,失败立即换 key / 换供应商;
  • 冷却、失败计数、权重轮转、错误中性化与 ctx.web.search 接管契约均未改动。

验证

项 结果
node scripts/run-tests.mjs 136 用例全绿(原 131,新增 5)
反证:临时移除修复 132/136,4 个新用例必红
内联复现 A/B/C 全部成功:A [bad,good]、B [tavily,exa]、C [hang,exa]
node --check / scripts/check-docs.mjs 通过,0 errors

已知边界

  • 「所有 key 同时挂起」时仍会逐个等到 requestTimeoutMs(默认 20s);宿主 web_search 的截止时间不向 provider 暴露,因此不引入总预算猜测。
  • 未跑真实宿主 e2e(scripts/e2e-boot.mjs 需要 app.asar 提取目录)。

升级

dsh-web-search-pool: https://gh-proxy.com/https://github.com/DreamRift/dsh-web-search-pool/archive/refs/tags/v0.5.1.tar.gz

或使用本 Release 附带的 dsh-web-search-pool-0.5.1.tgz(sha256 9BD00666C530AE2EE3F592538CC65059ED901E82277EEC90DFC0BB3E3129D268)。

完整变更:v0.5.0...v0.5.1

v0.5.0: 运行时接管官方搜索

Choose a tag to compare

@DreamRift DreamRift released this 19 Oct 04:36

修复

  • 「启用搜索 Key 池」未真正生效:0.4.0 只在 apply 时把 web 行的 searchProvider 改成 search-pool。官方 WebRuntime.search 是调用时才按该字段选 provider,而用户 profile 的 cordis.patch.yml 在 bundle 层之后应用、官方 Web search 设置页也写同一行;覆盖后请求仍走 deepseek-search-api / deepseek-official,消耗 DeepSeek 官方 API key。

变更

  • 接管点改为 ctx.web.search 服务方法:apply 时在 web 服务实例上安装可逆 wrapper,启用态直接走 key 池;不依赖 provider id、provider 注册顺序、web.searchProvider 或行 id,因此不会被 profile patch / 官方设置页覆盖。关闭时委托回原 web.search,卸载时按 descriptor 恢复。
  • cordis.patch.yml 不再改写官方 web 行,只插入 web-search-pool 行。
  • 模型无感:wrapper 返回与官方 seam 同形的 { content?, sources, truncated },去掉池内部 query / provider 字段,并按 maxResults 截断;池不可用/失败时默认不回退官方,抛中性的 WEB_PROVIDER_UNAVAILABLE(不含 Tavily / Exa / key / 官方端点字样),详细原因只写 ctx.logger 与 error.cause。
  • 降级路径:若宿主把 web.search 冻结/设为不可配置,退回替换 deepseek-search-api / deepseek-official provider 对象的 search / available;若 searchProviders 也不可检查,再退回配置同步。
  • 清理注册到 ctx.effect:cordis 4.0.4 的 Loader 不把 apply 的返回值当 disposer,原写法在卸载时不会恢复官方方法。

新增

  • fallbackToOfficial(默认 false):池不可用/全部 key 失败时是否回退官方搜索;可在 profile patch 中打开。
  • scripts/privacy-scan.mjs 用户名改为运行时获取(PRIVACY_USERNAME 可覆盖),不再把账户名写进源码。

验证

  • 单元/契约测试 131 例全绿(node scripts/run-tests.mjs):服务级接管、未知 provider id、maxResults 截断、中性错误、关闭委托、fallbackToOfficial 回退、web.search 不可 patch 的降级、dispose 恢复。
  • 桌面版 0.2.1-rc.2(resources/app.asar 提取)真实启动全绿:web 行保持 deepseek-official、ctx.web.search 有 own wrapper、无 key 时真实宿主调用抛中性错误、settings.update 不改写 web 行。
  • 复现失效场景(profile 显式写 searchProvider: deepseek-search-api)下 --live-search 真机搜索仍走 Tavily:约 3.9s 返回 5 条来源 + answer 摘要。

安装方式:DSH 桌面版 → 设置 → 插件 → 安装 → 选择本 Release 附带的 dsh-web-search-pool-0.5.0.tgz,按提示重启。升级后 web 行仍显示官方 provider 属正常现象——接管发生在 ctx.web.search 方法上;日志可见 search-pool: takeover installed at web.search。安装后验证与配置说明见仓库 docs/安装与升级.md。

v0.4.0: 适配 DSH 0.2.0

Choose a tag to compare

@DreamRift DreamRift released this 29 Sep 00:31

新增

  • 支持 DSH 0.2.0 线:peer 范围从 ^0.1.7-rc.1 扩为 ^0.1.7-rc.1 || ^0.2.0-rc.1(0.1.7 与 0.2.0 双线并存),桌面版 0.2.0-rc.1 的启动兼容门放行本 bundle 层。
  • scripts/privacy-scan.mjs:扫描 git 全部历史的个人用户名、绝对路径、真实长度 API key、邮箱、Bearer token;接入发布流程必跑步骤。
  • scripts/e2e-boot.mjs 新增 --user-patch(真实用户 patch 层组合验证)与 --live-search(真机搜索冒烟)两个能力。

变更

  • 0.2.0 适配核对(无行为改动):0.2.0 把 loader 拆为独立包 @deepseek-ai/cordis-plugin-loader(cordis 4.0.4 的 peer),逐项核对宿主 app.asar 源码确认本插件依赖的契约无破坏性变化——ctx.web.registerSearchProvider 与 provider 面、loader/volatile-update、Config schema 的 volatile 投影、plugins.row.config keyed slot、ctx.configForms、ctx.remote.credentials 与 credentials/reference-updated 事件、dsh.client.inject 三包到达顺序、dsh-base 根组 web 行的 restate 语义。因此 0.2.0 线只放宽 peer 范围,src/ 无功能改动。

验证

  • 桌面版 0.2.0-rc.1(resources/app.asar 提取)源码核对 + scripts/e2e-boot.mjs 真实启动全绿:skippedBundles 为空、web 行 patch 生效(searchProvider=search-pool 且 fetchProvider 保留)、web-search-pool 行 ACTIVE、settings.describe 投影全部字段、settings.update 端到端(不重挂 + volatile 就地提交 + web 行双向同步 + patch 落盘)、client-modules 图谱下发浏览器 bundle。
  • 本地测试 122 个用例全绿;发布前隐私扫描(全历史 + 待提交改动)通过。

安装方式:DSH 桌面版 → 设置 → 插件 → 安装 → 选择本 Release 附带的 dsh-web-search-pool-0.4.0.tgz,按提示重启。安装后重启验证与配置说明见仓库 docs/安装与升级.md。

v0.3.0 — 适配 DSH 0.1.7

Choose a tag to compare

@DreamRift DreamRift released this 25 Sep 02:22

v0.3.0 — 适配 DSH 0.1.7(官方桌面版 0.1.7-rc.2 实测)

🔧 修复

  • 「安装后无插件页面 + 重启 dsh 报错」:0.2.1 的 client half 在 exports.inject
    里等服务 settingsScope——0.1.7 已随设置体系重写移除该服务,浏览器 loader entry
    永久 pending,web boot fail-loud(桌面版崩溃日志实证
    dsh-web-search-pool: pending (waiting for service: settingsScope))。

⚠️ Breaking

  • 仅支持 DSH 0.1.7+(peer 收紧为 ^0.1.7-rc.1,DSH 启动兼容门 satisfies 判定)。

✨ 变化

Host half

  • 设置面改为 loader 行 Config schema 自动投影(namespace = 行 id);全部可编辑字段
    .volatile()——运行期是 Ref,编辑经 settings.mutate 写 profile patch 后就地提交
    (loader/volatile-update,不重挂插件)。
  • 运行时 usage/tick/diagnostic 移出 schema(0.1.7 的 settings 写入即落盘进用户 patch),
    Tavily 额度快照改 ctx.logger 观测;额度门禁 / 长冷却 / 自动恢复逻辑不变。
  • web 行 id 运行时探测(web / include:web)。

Client half(按官方 companion 包同构重写)

  • settings.plugin.item slot → plugins.row.config(key = dsh-web-search-pool#web-search-pool)。
  • ctx.settingsScope → ctx.configForms(get(ns) + whileServed 门控)。
  • 写入走 form.mutate(ops, revision);凭据走 remote.credentials describe/set。

✅ 验证

  • 122 个 node:test 用例全绿(含真实 cordis + Loader + schemastery 驱动 host half 的集成测试)。
  • scripts/e2e-boot.mjs:用桌面版 app.asar 内真实运行时 + 隔离 profile 端到端启动整棵
    宿主树——bundle 加载 / patch 生效 / 插件 ACTIVE / settings 投影 / 写入落盘就地提交 /
    client-modules 图谱下发,全绿。

📦 安装

npm pack
# 桌面版:设置 → 插件 → 安装 → 选择 tgz;在 dsh-web-search-pool 的 web-search-pool 行点「配置」

详见 docs/安装与升级.md 与 CHANGELOG.md。