🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

Tavily 弹性搜索 frederico-kluser/dsh-tavily-resilient-search

DeepSeek Harness
frederico-kluser37 天前有提交已提供中文文档扫描:未发现敏感能力

多密钥轮换调用 Tavily 实时联网搜索

29.6/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add frederico-kluser/dsh-tavily-resilient-search
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · search
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 37 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🟢 扫描:未发现敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

发起外部网络请求
查看扫描证据(共 2 处,展示前 2 条)
  • 发起网络请求
    client/client.js:35
    const res = await fetch(API + "/health");
  • 发起网络请求
    client/client.js:51
    const res = await fetch(API + path, {
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-invariants@deepseek-ai/dsh-llm@deepseek-ai/dsh-ptc-runtime@deepseek-ai/dsh-sandbox@deepseek-ai/dsh-sandbox-policy@deepseek-ai/dsh-scope@deepseek-ai/dsh-session@deepseek-ai/dsh-system-prompt
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 多密钥轮换调用
  • 实时联网搜索
  • 密钥池弹性轮换

Tavily 网页搜索插件,给 DeepSeek Harness(Cordis 插件)用,支持 API 密钥池原子化弹性轮换——限流、月度配额、密钥吊销都不打断智能体循环。

README

由 DeepSeek 最新模型翻译生成
dsh-tavily-resilient-search 通过 Tavily API 为 DeepSeek Harness(DSH)提供实时网络搜索,具备凭证池的原子化、弹性轮换以及无密钥应急方案——当密钥达到速率限制(429)、月度配额耗尽(432/433)或被撤销(401)时,不会中断 agent loop。 独立的 Cordis 插件:通过清单安装,无需对 DSH 代码进行 fork,并且能在热重载/卸载后存活,不会产生泄漏或孤立的监听器。 它解决的问题 在朴素的实现中,HTTP 429 或 432 会作为 promise 拒绝传播到轮次例程:该轮次会突然终止——或者模型会错误地得出结论,认为“互联网已经不存在了”。在这里,语义意图(搜索)与物理层(当前由哪个凭证来派发)是解耦的: - 饱和/计费错误会改变引发问题的密钥状态,并且该调用会以原封不动的 payload 立即重新发出,由下一个无阻碍的凭证(round-robin)执行; - 当整个池都受阻时,会启用无密钥应急方案(X-Tavily-Access-Mode: keyless); - 只有当所有传输备选方案都耗尽时,该工具才会返回结构化的警告结论——绝不抛出会驱逐宿主进程的异常。
展开完整文档(README 剩余 1 节)
dsh-tavily-resilient-search

通过 Tavily API 为 DeepSeek Harness(DSH)提供实时网络搜索,具备凭证池的原子化、弹性轮换以及无密钥应急方案——当密钥达到速率限制(429)、月度配额耗尽(432/433)或被撤销(401)时,不会中断 agent loop。

独立的 Cordis 插件:通过清单安装,无需对 DSH 代码进行 fork,并且能在热重载/卸载后存活,不会产生泄漏或孤立的监听器。

它解决的问题

在朴素的实现中,HTTP 429 或 432 会作为 promise 拒绝传播到轮次例程:该轮次会突然终止——或者模型会错误地得出结论,认为“互联网已经不存在了”。在这里,语义意图(搜索)与物理层(当前由哪个凭证来派发)是解耦的:

- 饱和/计费错误会改变引发问题的密钥状态,并且该调用会以原封不动的 payload 立即重新发出,由下一个无阻碍的凭证(round-robin)执行;
- 当整个池都受阻时,会启用无密钥应急方案(X-Tavily-Access-Mode: keyless);
- 只有当所有传输备选方案都耗尽时,该工具才会返回结构化的警告结论——绝不抛出会驱逐宿主进程的异常。

安装

dsh plugin --profile web add dsh-tavily-resilient-search

激活是自动的:该包声明了 dsh.bundle.patch(只有 dsh.bundle.patch 才能激活插件——空的 bundle: {} 不会激活任何东西),并且清单 cordis.patch.yml 会进入组合的 Bundle 层。

通过环境变量定义凭证(切勿以明文形式):

export TAVILY_API_KEY_A="tvly-..."
export TAVILY_API_KEY_B="tvly-..." # tantas quantas as contas disponíveis
export TAVILY_API_KEY_C="tvly-..."
export TAVILY_API_KEY_D="tvly-..."

没有任何密钥时,插件不会导致启动崩溃:它会降级为仅无密钥模式(限制要严格得多)并大声警告。已记录的合法状态:“尚未配置”。

通过界面管理密钥

池的所有 CRUD 都集中在一个唯一位置:设置(Settings)中的 “Tavily Keys” 部分——由客户端 bundle(client/client.js,在官方示例中测量的 __ModuleLoader__ 格式)贡献给 settings.section 槽位,并使用 DSH 的设计系统进行样式化。

- 在单一屏幕上完成完整 CRUD:添加(C,使用 Enter)、以卡片形式列出状态(R)、编辑/替换(U,Enter 保存,Esc 取消)、移除(D)以及测试(针对 API 进行验证——1 个信用点)。
- 每个操作都有反馈:请求期间显示 spinner,并立即显示 ✓/⚠ 确认——绝不会有点击后毫无响应的情况。
- 侧边区域的 “🔑 Tavily Keys” 按钮仅在不存在有效密钥时显示(一旦有可用凭证就会消失);它会直接打开定义。没有并行屏幕:旧的独立页面响应 410。
- 面板中的有用链接:app.tavily.com 用于获取密钥、文档以及 token 所在位置。

管理 token(用于打开面板):在首次启动时由 CSPRNG 生成,保存在 ~/.dsh/dsh-tavily-resilient-search/admin-token.txt (0600),并在 DSH 日志(logger 'tavily-pool')中打印一次。丢失了?
用 DSH_TAVILY_ADMIN_RESET=1 重新加载。也可以设置 DSH_TAVILY_ADMIN_TOKEN。
- 边界:来源(socket + Origin)→ Host → 凭据,按此固定顺序;拒绝响应字节级相同(无 oracle)。默认:仅 loopback(admin.trustedRemotes / admin.allowedHosts)。
- 暴力破解:NIST SP 800-63B-4 预算(100 次失败 → 以相同的 401 锁定)。
- 破坏性操作(删除以及替换/编辑)需要一次性确认 nonce。
- 审计:audit.log 可追加(0600,O_NOFOLLOW),记录所有可变决策和拒绝。
- 从环境中移除的密钥会在下次启动时恢复(移除是易失的,面板会提示);通过面板持久化/移除的密钥是永久性的。
- 在公共绑定(0.0.0.0)上,面板拒绝启动(fail-closed,高噪声),直到 admin.allowPublicBind: true —— 搜索工具在任何情况下都继续工作。

配置

在 Profile 层($DSH_HOME/profiles//cordis.patch.yml)、Home ($DSH_HOME/cordis.patch.yml)或 CLI overlay(dsh --patch ./o.yml)中覆盖任何字段。解析是整项替换(whole-entry replace),从不 deep-merge:始终指向插件自身的 id。

| 字段 | 类型 | 默认值 | 作用 |
| apiKeys | string[] | [] | 凭据分组(round-robin)。为空 = keyless-only。 |
| searchDepth | ultra-fast\|fast\|basic\|advanced | basic | 当模型未选择时的默认深度。 |
| maxResults | 1..100(钳制到 10) | 5 | 合格来源的最大数量。 |
| includeAnswer | boolean | true | 注入初步的摘要回答。 |
| timeoutMs | 250..300000 | 15000 | 每次尝试 HTTP 的超时。 |
| callTimeoutMs | ≥ timeoutMs | 120000 | 调用的总协作预算(所有轮换)。 |
| projectId | string | — | 按项目隔离(X-Project-ID)。 |
| admin.enabled | boolean | true | 通过界面管理密钥的面板。 |
| admin.trustedRemotes | string[] | loopback | 面板允许的套接字来源。 |
| admin.allowedHosts | string[] | 127.0.0.1、localhost、::1 | 允许的 Host 名称(防 DNS-rebinding)。 |
| admin.stateDir | string | $DSH_HOME/dsh-tavily-resilient-search | 状态目录(0700)。 |
| admin.allowPublicBind | boolean | false | 显式选择退出对非 loopback 绑定的拒绝。 |
| securityProfile | {sandbox, approval} | 必填 | 安装配置文件的证明(见安全)。 |

示例(Bundle 层,已包含在包中):

- insert:
- id: dsh-tavily-resilient-search
name: 'dsh-tavily-resilient-search'
config:
searchDepth: 'basic'
maxResults: 5
includeAnswer: true
timeoutMs: 15000
callTimeoutMs: 120000
securityProfile:
sandbox: 'workspace-write'
approval: 'ask'
apiKeys: !!js >
(() => { try { return [process.env.TAVILY_API_KEY_A, process.env.TAVILY_API_KEY_B, process.env.TAVILY_API_KEY_C, process.env.TAVILY_API_KEY_D].filter(Boolean) } catch { return [] } })()

清单的实测规则(@deepseek-ai/dsh 0.1.x-rc):行的顺序不承载加载语义(激活由 inject 驱动),并且*一个在加载时抛出异常的 !!js 会阻止所有安装者的 DSH 启动——上面的表达式是防御性的,在失败时返回 []。

暴露的工具:web_search

| 参数 | 类型 | 必填 | 描述 |
| query | string | 是 | 客观关键词(建议 < 1500 个字符;硬性上限 4000)。 |
| search_depth | enum | 否 | ultra-fast/fast(< 800 ms)· basic · advanced(仅限复杂文档)。 |
| max_results | integer | 否 | 1 到 10(默认 5)。 |
| topic | enum | 否 | general \| news。 |

规范结果(完整形式,不适用时显式 null):
ok、query、answer、sources[](title、url、snippet、score)、
responseTime、resultsTruncated、keylessFallbackUsed、error、detail、 suggestion。向模型的投影始终包含一条关于网页内容的不可信警告(间接注入遏制)。

按 HTTP 状态码的行为

| HTTP | 条件 | 插件行为 |
| 200 | 成功 | 解码、规范化、应用 50 KB 上限、返回结果。 |
| 400 | 参数格式错误 | 不轮换——返回错误 + 修正建议。 |
| 401 | 密钥无效/已撤销 | 永久禁用(REVOKED)并立即前进到下一个。 |
| 403 | 域名/路由被禁止 | 不轮换——告知无法访问。 |
| 429 | 速率限制 | 读取 Retry-After(秒或 HTTP 日期),冷却该密钥并轮换。 |
| 432 | 月度配额耗尽 | 暂停至下个月 UTC 午夜并轮换。 |
| 433 | 达到 PAYGO 上限 | 同 432(定时暂停)。 |
| 5xx | 瞬时不稳定 | 使用备选方案重试;密钥状态不变。 |

密钥池状态机

┌──────────────┐ 401 ┌──────────┐
┌────────►│ ACTIVE │───────►│ REVOKED │ (definitivo)
│ └──────┬───────┘ └──────────┘
│ cooldown │ 429
│ expirado ▼
┌─────┴────────┐ ┌──────────────┐
│ (轮询)│◄─│ RATE_LIMITED │ T = Retry-After 或 min(Tmax, T0·2^k) + δ
└──────────────┘ └──────────────┘
▲
│ 每月补充(第 1 天,UTC) ┌─────┴───────────┐ │ QUOTA_EXHAUSTED │ 432/433 → 暂停至下月 UTC 午夜 └─────────────────┘

T₀ = 500 ms,T_max = 60 s,抖动 δ ∈ 0, 500) ms,用于对抗整批重新饱和。恢复是惰性的(无定时器):过期在下次选择时生效,从而保持读取纯净、事件循环干净。

安全

摘要(完整内容见 [docs/seguranca.md):

- sandbox: danger-full-access + approval: never 的组合在加载时被拒绝(fail-loud,故意不可恢复)。securityProfile 是操作员的强制性证明——配置缺失也会高声失败。
- 按值的机密金丝雀:凭据材料会从所有输出文本和日志中被脱敏(一个恶意响应体即使回显了 Authorization 密钥也绝不会将其传播);日志中仅以掩码 …últimos4 标识。
- 每次调用 50 KB 的体积上限:炸弹文档不会撑爆上下文窗口(include_raw_content 从不发送)。
- 网页内容是不可信数据:模型投影携带针对间接指令注入的永久警告。

| Sandbox \ Approval | ask | never |
| workspace-write | 审慎(默认) | 受控自动化 |
| danger-full-access | 受监控的扩展 | 禁止——加载时拒绝 |

经测量验证的 API(绝不靠散文)

所使用的接口是从已发布的 npm tarball 内的 .d.ts 中读取的(sha256 记录于 types/;由 pnpm run check:upstream 重新验证),并由一个契约测试锁定,一旦公共 API 偏离即失败。经测量的事实纠正了流传的文档:

| 已死的说法 | 实测的真实行为 |
| inject: ['tools', 'logger'] | logger 不是 Cordis 的 Service:该 fiber 会永远处于 PENDING。应使用 ctx.logger(nome);inject = ['tools']。 |
| dsh.bundle: {} 激活插件 | 只有 dsh.bundle.patch 才会激活(在 @deepseek-ai/dsh 0.1.0-rc.7+ 中实测)。 |
| 参数中的 required: false | DSL 用 required?: true 标记必填——可选 = 省略该键。 |
| output: { schema: { type: 'object' } } | 对象要求显式的 additionalProperties: boolean。 |
| ctx.httpServer / spawn(cmd, args) | ctx.webServer / ctx.subprocess.spawn(spec)(在 0.1.x-rc 范围内验证)。 |

支持的行:@deepseek-ai/dsh-tools ^0.1.1-rc.1 || ^0.1.7-rc.1(两者之间的
漂移仅为增量)以及 @deepseek-ai/cordis ~4.0.4。注意:dsh- 子包的 dist-tag latest 指向最旧的发布——活跃行是 next。

开发

pnpm install
pnpm run gate # lint + typecheck + build + test + check:tarball
pnpm run check:upstream # 通过网络重新验证 tarballs/sha256(Q-1)
四层测试(node:test + tsx,确定性——注入时钟和 RNG,无 sleep):

| 层 | 证明 |
| test/unit | 纯核心:状态机、字节上限、fail-loud 校验、token/nonce/lockout、0600 持久化 + 防符号链接审计 |
| test/integration | 基于传输替身的原子轮换,以及基于真实 HTTP 服务器(端口 0)的面板路由器 |
| test/adversarial | 尝试突破:机密金丝雀、炸弹文档、间接注入、YOLO 配置、P-09 回归、启动安全、字节级相同的 CSRF/rebinding、无预言机暴力破解、nonce、拒绝公网绑定 |
| test/contract | types/ 镜像与已发布的 .d.ts 逐字一致 |

打包与发布

发布预编译产物(dist/),消费者安装时不运行构建脚本(供应链风险)。files 是允许列表:dist/、cordis.patch.yml、README.md、LICENSE、CHANGELOG.md。发布门禁是
pnpm run gate && publint && attw --pack . && node scripts/check-tarball.mjs
(最后一项检查真实 tarball)。版本说明通过 changesets;在 0.x 中,minor 即为破坏性变更。CI 中的发布使用可信发布(OIDC)——需在 npm 控制台为此仓库配置一次。

许可证

MIT
预览分享卡片长什么样 ↓frederico-kluser/dsh-tavily-resilient-search
分享 · DeepSeek Harness Hub
frederico-kluser/dsh-tavily-resilient-search

多密钥轮换调用 Tavily 实时联网搜索

回到顶部