ctx.web 接缝的零配置 Exa 网页搜索提供方:无 API key 时走匿名 MCP 兜底,配 key 时走 REST 搜索。
安装
# npm 包(预构建)
dsh plugin --profile web add @tonydua/dsh-web-search-exa
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:TonyDua/dsh-web-search-exa
GitHub 来源的插件在安装时会在你的机器上执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 简体中文
为 DeepSeek Harness(dsh)提供零配置的 Exa 网页搜索: 无需 API key —— 一个
ctx.webseam 的WebSearchProvider,内置匿名 MCP 兜底 + 带 key 的 REST 路径。
使用 deepseek-v4-flash 在 DeepSeek Harness(dsh)内开发。
特性
- 🆓 零配置、默认免 key —— 搜索经由 Exa 官方托管的 MCP 服务器(
mcp.exa.ai/mcp),完全不携带凭据(Exa 官方提供的免认证公共 MCP,有限流)。 - 🔑 配 key 自动升级 REST —— 设置
EXA_API_KEY后自动切换到 ExaPOST /searchREST API(额度更高,行为不变)。 - 🔌 即插即用 —— 注册进 dsh
ctx.webseam;模型侧的web_search/web_fetch工具、提示词区段与结果卡片无需任何改动。 - 🎛️
providerId开关 —— 可与官方@deepseek-ai/dsh-web-search-exa在同一 profile 共存(不撞 id、无黑箱覆盖)。 - 📦 可直接发布 —— MIT、ESM、内置类型声明、
files仅含lib/。
为什么有这个包(与官方包的差异)
DeepSeek Harness 自带官方 Exa 提供方 @deepseek-ai/dsh-web-search-exa。本包是它的零配置变体:补上了官方没有的匿名 MCP 兜底,同时保留配置 key 后的相同 REST 行为。
官方 @deepseek-ai/dsh-web-search-exa |
本包 @tonydua/dsh-web-search-exa |
|
|---|---|---|
REST 路径(POST /search) |
✅ 唯一路径 | ✅ 配置 key 时使用 |
| 必须有 API key | ✅ 是——key 为空则不可用 | ❌ 不需要——无 key 走匿名 MCP 兜底 |
匿名 MCP(mcp.exa.ai/mcp) |
❌ 未实现 | ✅ 无 key 时默认路径 |
| 零配置安装 | ❌ | ✅ |
| Provider id | exa(固定) |
默认 exa,可用 providerId 配置 |
| Cordis 插件名 | web-search-exa |
web-search-exa |
| 配置键 | apiKey、baseURL、searchType、numResults、highlightsPerResult |
apiKey、apiKeyEnv、apiURL、mcpURL、searchType、numResults、highlightsPerResult、providerId |
我该用哪个?
- 你有
EXA_API_KEY,且想要官方维护的包 → 用@deepseek-ai/dsh-web-search-exa,它是官方标准实现。 - 想零配置、免 key、无成本负担地试用 Exa 搜索 → 用本包。优雅降级:默认匿名 MCP,出现 key 自动走 REST。
- 两个都想要 → 一起装,用
providerId开关(见与官方包共存)。
工作原理
| 条件 | 路径 | 端点 |
|---|---|---|
配置了 apiKey / EXA_API_KEY |
REST POST /search,Authorization: Bearer |
https://api.exa.ai/search(可配置) |
| 未配置任何 key | 匿名 MCP tools/call web_search_exa(JSON-RPC 2.0,无凭据) |
https://mcp.exa.ai/mcp(可配置) |
匿名 MCP 路径不发送任何凭据,来源标识通过 x-exa-source: dsh-anything 头携带。结果按 seam 的 WebSearchSource 形状规范化(url、title、snippet、publishedAt),maxResults 由 seam 在返回路径上强制执行。匿名使用受 Exa 限流:HTTP 429 会以 WEB_PROVIDER_ERROR 呈现,并提示配置 API key(配置后自动切换到 REST 路径)。
安装(装入 dsh profile)
一条命令从 npm 安装(v0.1.3+ 自带 dsh.bundle manifest——bundle patch 会自动插入 provider 行,无需手动改 patch):
dsh plugin --profile web add @tonydua/dsh-web-search-exa
重启 dsh web 生效。无 API key 时官方 DeepSeek 搜索提供方不可用,seam 会自动选中本插件——完全零配置。配了 key 时,需在你的 $DSH_HOME/profiles/web/cordis.patch.yml(在 bundle patch 之后应用)里显式选中 Exa:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: exa
…或用环境变量 $DSH_WEB_SEARCH_PROVIDER=exa 在运行时选中。
本地开发目录:
dsh plugin --profile web add ../plugins/dsh-web-search-exa
然后启用并选中该提供方。合并进 $DSH_HOME/profiles/web/cordis.patch.yml(持久生效):
- id: web-search-exa
name: '@tonydua/dsh-web-search-exa'
config:
apiKeyEnv: EXA_API_KEY
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: exa
也可以不修改配置,直接用环境变量 $DSH_WEB_SEARCH_PROVIDER=exa 在运行时选中该提供方。
重启 dsh web 生效。模型侧的 web_search 工具随即走该提供方,无需改任何工具配置。
运行时单例兼容性
@deepseek-ai/dsh-tools 是 dsh 的运行时单例包,一个 profile 中必须解析到同一份物理包实例。本插件本身不依赖它;这是宿主 profile 的依赖约束。如果 profile 中的其他第三方插件把 @deepseek-ai/dsh-tools 错误声明成普通嵌套依赖,而不是 peer dependency,应先修正该插件的依赖声明,或让 profile 的包管理器统一解析到共享实例,再排查搜索错误。否则 dsh agent loop 可能在 provider 被调用前就因 Cannot read properties of undefined (reading 'prepare') 失败。
配置
| 配置键 | 默认值 | 含义 |
|---|---|---|
providerId |
exa |
注册进 ctx.web 的提供方 id。仅当本包与官方包同时安装时才需要改(见下一节)。 |
apiKey |
未设置 | Exa API 密钥字面值。为空/缺失时启用匿名 MCP 路径。 |
apiKeyEnv |
EXA_API_KEY |
未设置字面 apiKey 时读取的环境变量名。 |
apiURL |
https://api.exa.ai/search |
REST 搜索端点(仅带 key 的路径使用)。 |
mcpURL |
https://mcp.exa.ai/mcp |
Exa 托管 MCP 端点(匿名路径使用)。 |
searchType |
auto |
REST 检索模式:auto / keyword / neural。 |
numResults |
未设置 | 请求未携带 maxResults 时的默认结果数。 |
highlightsPerResult |
1 |
REST 路径每个结果请求的 highlight 句子数。 |
与官方包共存
两个包默认在 ctx.web 下注册相同的 provider id(exa),cordis 插件名也都是 web-search-exa。seam 会拒绝重复 id(WEB_DUPLICATE_PROVIDER),所以不改配置就把两个包装进同一个 profile 会在启动时报错。
没有黑箱覆盖——共存必须显式配置,通过 providerId 开关完成:
- 官方包保持
exa(它的 id 固定)。 - 给本包一个不同 id——在本插件
config里设providerId: exa-anon(任意唯一字符串)。 - 在
webseam 上显式选中匿名变体:searchProvider: exa-anon(或用环境变量$DSH_WEB_SEARCH_PROVIDER=exa-anon);若还想用官方包,再配searchProvider: exa切换。
- insert:
- id: web-search-exa
name: '@tonydua/dsh-web-search-exa'
config:
providerId: exa-anon
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: exa-anon
最简单的替代方案:每个 profile 只装其中一个包,默认配置即可直接使用。
在 Web 面板中的呈现
状态:本版本的配置入口在 profile 补丁层,不在 Web UI —— 没有可编辑的界面入口。 Settings UI 只渲染客户端插件为固定命名空间(shell、agent-loop、web-search-deepseek)手工注册的卡片,对任意插件命名空间没有通用表单。当前实际情况:
- 插件清单(Settings → Plugins):启用后自动出现
web-search-exa(@tonydua/dsh-web-search-exa)条目 —— 清单直接读取 Cordis loader 的实时条目,无需额外代码。 - 设置命名空间(服务端):插件通过
installSettingsSection注册了web-search-exa段,数据层可写——但没有任何客户端卡片绑定它,所以界面上不显示。内置的 "Web search" 卡片编辑的是官方web-search-deepseek命名空间,与本插件无关。 - 现在怎么改配置:编辑
$DSH_HOME/profiles/web/cordis.patch.yml里本插件的config(字段与默认值见上方配置表),重启dsh web;或用环境变量EXA_API_KEY/$DSH_WEB_SEARCH_PROVIDER。apiKey标记了role('secret'),任何describe()响应都不会暴露其值。 - 搜索结果卡片:
web_search调用经dsh-tool-web照常渲染web结果卡片(来源、摘要、日期),与提供方无关 —— 匿名 Exa 的结果与 DeepSeek 搜索显示完全一致。
路线图(下一版本):新增注册到 settings.plugin.item slot 的客户端卡片,绑定 web-search-exa 命名空间,让上表所有字段可以在 Settings → Plugins 里实时编辑(与官方卡片同机制)。
常见问题(FAQ)
Q: 需要 Exa API key 吗? 不需要。无 key 时走 Exa 免费匿名托管 MCP;配 key 后走 REST API 获得更高额度。
Q: 遇到 HTTP 429 / 限流怎么办?
这是 Exa 匿名 MCP 的限流。配置 EXA_API_KEY(或 apiKey 字段),提供方会自动切到 REST 路径。
Q: 能和官方 Exa 提供方一起装吗?
可以——给本包一个不同的 providerId 并显式选中即可(见与官方包共存)。
Q: 为什么 Web UI 里没有设置入口?
本版本只在服务端注册了 web-search-exa 设置命名空间;UI 卡片计划在下一版本提供。现阶段通过 cordis.patch.yml 或环境变量配置(见在 Web 面板中的呈现)。
致谢(Acknowledgements)
匿名 MCP 接入方式参考了 can1357/oh-my-pi 的 web_search 实现(packages/coding-agent/src/web/search/providers/exa.ts 与 src/exa/mcp-client.ts)以及 @oh-my-pi/exa 插件:同样的"有 key 走 REST、无 key 走免凭据 mcp.exa.ai/mcp"策略、同样的 x-exa-source 来源头、同样的 Title: 分节响应解析。感谢 oh-my-pi(omp)项目率先打通了零配置的 Exa 接入。
同时感谢 Exa 提供并运营这个免费、免认证的托管 MCP 服务器(mcp.exa.ai/mcp)——正是它让本包的零配置默认路径成为可能。Exa 托管 MCP 是 Exa 的官方产品;匿名使用有限流(见 FAQ)。
更新日志(Changelog)
所有变更见 CHANGELOG.md。
许可证
MIT —— 见 LICENSE。
链接
同类插件
liustack/modlens★ 1199
为纯文本模型架起视觉桥梁:粘贴图片,输出结构化 JSON 证据(OCR、版面、语义)。
Anionex/dsh-vision-toolkit★ 308
让纯文本模型更好地做视觉任务:带意图的图片问答、长截图 OCR、UI 还原等。
zhaoolee/notes★ 138
将 DSH 对话导出为锤子便签风格 PNG,或在配置的账号工作区中新建和更新 Markdown 便签。
liustack/modsearch★ 85
纯文本 agent 的联网搜索桥:搜索网页与 X,返回结构化 JSON 证据(search/fetch/引用)。
Lum1104/dsh-browser★ 80
Chrome 侧边栏扩展,让 DSH 直接操控你的浏览器,无需视觉能力。
taxueseek/argo★ 69
专为 agent 打造的搜索工具:多语言,覆盖中文/英文/学术/代码/购物/金融/新闻/百科。