多密钥轮询搜索网页并抓取正文内容
29.6/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ArcaneOrion/dsh-tavily-web该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · search
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 33 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(dependency_conflict · 2026/10/4) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
发起外部网络请求
查看扫描证据(共 2 处,展示前 2 条)
- 发起网络请求src/tavily-web.js:293
return ctx.web.fetch({ url: String(args.url) }, exec.signal); - 发起网络请求src/tavily-web.ts:383
return ctx.web.fetch({ url: String(args.url) }, exec.signal)
扫描于 2026/11/1(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-tools@deepseek-ai/dsh-web@deepseek-ai/dsh-shell@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 多密钥轮询搜索
- 抓取网页正文
DSH Tavily 插件:密钥池化的网页搜索(tavily_search)+ 页面抓取(web_fetch)
README
由 DeepSeek 最新模型翻译生成@arcaneorion/dsh-tavily-web
DSH 的 Tavily 检索 + 网页抓取能力层(host 半,profile bundle)。注册两个模型可见工具,并把自身作为 唯一的 fetch provider 挂进宿主 web 注册表。
- tavily_search —— Tavily 检索,返回 { sources: [{url, title, snippet, publishedAt}], truncated, content? }。
多 key 轮询池:单账号额度耗尽不再等于工具失效。
- web_fetch —— 经 shell seam 的 curl 抓单页,返回 HTTP 状态 + 去标签正文。不依赖 Tavily,无 key 需求。
检索不注册为 web.search() 的 provider:旁边已有出厂的 DeepSeek 检索 provider,再挂一个可用 provider 会让 web.search() 的选择变歧义。检索只以模型可见工具的形式存在。
展开完整文档(README 剩余 1 节)
@arcaneorion/dsh-tavily-web
DSH 的 Tavily 检索 + 网页抓取能力层(host 半,profile bundle)。注册两个模型可见工具,并把自身作为 唯一的 fetch provider 挂进宿主 web 注册表。
- tavily_search —— Tavily 检索,返回 { sources: [{url, title, snippet, publishedAt}], truncated, content? }。
多 key 轮询池:单账号额度耗尽不再等于工具失效。
- web_fetch —— 经 shell seam 的 curl 抓单页,返回 HTTP 状态 + 去标签正文。不依赖 Tavily,无 key 需求。
检索不注册为 web.search() 的 provider:旁边已有出厂的 DeepSeek 检索 provider,再挂一个可用 provider 会让 web.search() 的选择变歧义。检索只以模型可见工具的形式存在。
安装
dsh plugin --profile web add @arcaneorion/dsh-tavily-web
然后重启 dsh --profile web —— host 插件不走热重载
profile 级 bundle:装一次,该 profile 下所有会话都拿到 tavily_search / web_fetch。
发布状态:已发布到 npm,上面的命令可直接用。最新版本号永远现查、别信文档里写死的号:
npm view @arcaneorion/dsh-tavily-web version(404 即尚未发布)。
想在本地改源码即时生效,则走 link: 挂载:~/.dsh/profiles/<profile>/package.json 写 "@arcaneorion/dsh-tavily-web": "link:/home/arcaneorion/AI/AI-DSH/plugin/tavily-web-plugin",并在 dsh.profile.bundles 追加包名。
另外 npm tarball 只含 src/、cordis.patch.yml、README.md(files 白名单),tests/ 不随包发布——要跑下面的离线用例请用仓库副本。
兼容性(DSH 版本)
当前工作树已适配 DSH 0.2.0-rc.1(peer 按 0.2.0-rc.1 声明;版本 0.2.0)。下列 0.1.1-rc.2 记录仅作历史基线。
| 宿主包 | 声明 | 用途 |
| @deepseek-ai/dsh-tools | >=0.2.0-rc.1 | defineTool 注册 tavily_search / web_fetch |
| @deepseek-ai/dsh-web | 0.2.0-rc.1 | 把自身挂成 web 注册表的 fetch provider |
| @deepseek-ai/dsh-shell | 0.2.0-rc.1 | 走 shell seam 调 curl 抓页 |
| @deepseek-ai/cordis | ^4.0.4 | 插件生命周期 |
| @deepseek-ai/schemastery | ^3.18.4 | 配置 schema(keyRefs / apiKeys / cooldownSeconds) |
0.1.1-rc.2 → 0.2.0-rc.1 的唯一变更:shell seam 由 run() 改为 execute().result()
0.2 的 ctx.shell 只有一个执行入口 execute(spec),返回进程句柄;前台结果要再 await handle.result()。
本插件只用了前台执行,因此改动集中在 runCurl 一处:结果对象字段(exitCode / stdout.text / stderr.text / truncated / timedOut / aborted)与 0.1 一致,其余逻辑未动。
无 client 半,故不声明 react。换 DSH 版本必须先重新验证再放宽 peer:web 注册表与 shell seam 的契约跨版本会变,精确钉住的 peer 会在安装时报冲突,好过装上去静默失效。
文件
| 文件 | 说明 |
| src/tavily-web.ts | 源码:配置 schema、key 池、检索、抓取、工具注册(带完整注释) |
| src/tavily-web.js | 发布入口(package.json 的 main):由 .ts 转译而来,随包发布 |
| cordis.patch.yml | bundle 声明(行 id tavily-web),已挂载进 web profile |
| tests/pool.test.cjs | 池行为离线用例(脚本化 shell:桩件实现 0.2 的 execute() → result(),不联网、不消耗额度) |
| tests/live-pool-check.cjs | 真实密钥 + 真实网络的端到端探针 |
| LICENSE | MIT(package.json 同名字段;npm 打包时自动附带,无需写进 files) |
为什么有两个同名文件(改代码前先读这段)
main 必须是普通 JS,入口写成 .ts 会让「线上版本在任何机器上都加载不了」:
- 本地 link: 挂载时能用——pnpm 建的是 symlink,Node ESM 默认解析 realpath,文件真实路径在 plugin/ 下而不在 node_modules 里,所以 Node 的原生类型擦除放行;
- 从 npm 正常安装后,文件真实路径落进 node_modules,Node 直接拒绝: Stripping types is currently unsupported for files under node_modules。
失败形态是静默的:loader 连 fiber 都建不起来(fiberPhase: null),apply() 从不执行, tavily_search 永远不出现,且没有显式报错。所以:
bash
npm run build # 改完 src/tavily-web.ts 后重新生成 src/tavily-web.js
提交时两个文件一起提交(.ts 保留完整注释作源码,.js 是发布产物)。
发布前必须用安装形态验证,不能用 link: 形态验证——那正是这个坑躲过检查的原因: bash
mkdir -p /tmp/probe/node_modules/@arcaneorion
cp -r . /tmp/probe/node_modules/@arcaneorion/dsh-tavily-web
cd /tmp/probe && node -e "import('@arcaneorion/dsh-tavily-web').then(m=>console.log(Object.keys(m)))"
打印 [ 'Config', 'apply', 'inject', 'name' ] 才算通过
key 池
Tavily 的额度是按 key 计的,一个账号用尽不该把整个工具带走。池按引用名轮询,并按 key 的健康状况退避:
| 情况 | 处理 |
| HTTP 200 | 该 key 解除退避;游标前移,下次调用从下一把开始(轮询铺开) |
| 401 | 判为常驻失效(密钥本身被拒),本轮及后续跳过 |
| 403 / 429 / 432 | 退避 cooldownSeconds,到期自动回池 |
| 400 / 5xx / 传输失败 | 立即抛出,不烧池——这类失败换 key 也救不回来,试下去只会掩盖真问题 |
三个设计要点:
1. 按引用名寻址,缓存 key 值。 credentials 服务要求「每次操作重新 resolve」(改过的凭据必须在下一次调用生效,无需重启),所以池只保存引用名;每次调用现取现用。
2. 指纹而非密钥。 池为每个条目存一个 FNV-1a 指纹,用来识别同一个引用名下换了一把新密钥——指纹变了就立刻解除退避。因此「把 TAVILY_API_KEY 的值改成一个新账号」会即时生效,而不会被旧的退避状态挡住。
3. 最后一轮兜底重试。 所有健康 key 都失败后,被退避的 key 会再试一次。配额重置后无需重启即可自动恢复,且失败时报的是 API 原话,而不是含糊的「所有 key 都在退避中」。
全池失败时错误里逐把列出原因,便于直接定位:
tavily search: all 8 key(s) in the pool failed
- TAVILY_API_KEY: HTTP 432 — This request exceeds your plan's set usage limit. (retry after 2026-09-14T04:59:52Z)
- TAVILY_API_KEY_2: not configured
...
为什么默认池是 8 个名字
credentials 服务故意不提供引用枚举("the reference half, which has no enumeration")——配置面是从 schema 得知存在哪些引用的,而不是从服务。所以池成员必须预先声明。于是默认值直接写成 TAVILY_API_KEY、TAVILY_API_KEY_2 … TAVILY_API_KEY_8 整个家族:未配置的名字 resolve 回来是 undefined,被池直接跳过、零成本、零报错。
因此加第二把 key 不需要改任何 composition,只要: yaml
~/.dsh/.credentials.yaml
refs:
TAVILY_API_KEY: tvly-dev-...
TAVILY_API_KEY_2: tvly-dev-...
配置
全部可选,默认值即上文的家族。要覆盖时改用户层 ~/.dsh/profiles/<profile>/cordis.patch.yml(在所有 bundle 层之后应用),而不是改本包自带的 patch: yaml
- id: tavily-web
config:
keyRefs: [TAVILY_API_KEY, TAVILY_WORK_KEY] # 整体替换默认家族
apiKeys: [] # 字面量 key,排在 keyRefs 之后;密钥更该放 seam
cooldownSeconds: 900 # 403/429/432 后的退避秒数
keyRefs 与代码共用一个 DEFAULT_KEY_REFS 常量,避免「schema 声明的默认」与「运行时实际生效的默认」漂移。
加载/验证 bash
node tests/pool.test.cjs # 离线用例;VERIFY_TAVILY_KEY=<key> 时额外跑一项真实网络用例
node tests/live-pool-check.cjs # 真实凭据 + 真实网络,打印每次调用实际用了哪把 key
改了包源后:host 插件不走热重载,必须重启 dsh --profile web
启动日志出现 (key pool: N ref(s), cooldown 900s) 即表示新代码已加载
踩坑:curl 的错误体是合法 JSON
Tavily 的报错体(如 432 的 {"detail":{"error":"..."}})是合法 JSON,而 curl 遇到 HTTP 错误退出码仍是 0。于是「不检查状态码」的写法会一路顺利走完:退出码 0 → JSON.parse 成功 → data.results 为 undefined → 返回 {sources: [], truncated: false}。
任何 API 错误(401/429/432)都长得像「搜到 0 条结果」,无法自证。因此检索的 curl 必须带 -w '%{http_code}' 取回状态码并在解析前判定;这也是本插件唯一处对 curl 的硬性要求。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
ArcaneOrion/dsh-tavily-web
多密钥轮询搜索网页并抓取正文内容
相关插件 · 搜索 / 抓取
LLM 知识平台Tencent/WeKnora
概览 ·快速开始 ·新特性 ·功能 ·客户端 ·文档 ·开发
★ 36,161已汉化DSH
72.1
智能体记忆系统MemTensor/MemOS
MemOS 2.0 Stardust星尘
★ 12,195已汉化DSH
71.2
跨代理记忆库zilliztech/memsearch
跨平台语义记忆,专为 AI 编程智能体打造。
★ 2,799已汉化DSH
70.9
技能语料库EverMind-AI/SkillCorpus
SkillCorpus 能给你什么
★ 694已汉化DSH
69.7
代码图谱记忆syncable-dev/memtrace-public
你的智能体值得拥有结构化记忆。
★ 509已汉化MCP
67.9
AnySearch 搜索插件anysearch-team/anysearch-dsh
AnySearch 网页搜索服务商,为 DeepSeek Harness(DSH)提供高级搜索工具
★ 457已汉化DSH
66.6