OpenCode V2的深度搜索
DeepSeek Search & Fetch作为一个OpenCode V2插件: 内置的 websearch 工具路由到DeepSeek,加上一个干净的。
降价取货工具,本地使用/成本统计,a 坚持 后端开关,以及 TUI +桌面边栏 显示
状态和数字,一键翻转接管。
回到原生搜索:侧边栏开关, mode 选择,一个 deepseek_mode 电话,或
tools/switch-mode.ps1 从回购中。
中文说明见 文档/ README.zh-CN.md。
不同于现有的同名V1包:这个包的目标是 V2插件API切换后端 在 运行时,以及报告 当地使用情况和估计费用.
验证对
opencode 2.2.5与@opencode/[email protected]在Windows上。搜索/获取API事实来自 https://api-docs.deepseek.com/zh-cn/guides/search.
要求
opencode >= 2.2.5(V2插件API)- node . js
>= 22.18(该插件附带TypeScript源代码) - 具有Search/Fetch访问权限的DeepSeek API密钥
- 对于侧边栏:没有额外的- TUI和桌面应用程序提供渲染器(
@opentui/*,solid-js), 从同一个包中加载插件的两个部分
安装
设置键一次(Windows,用户范围):
[Environment]::SetEnvironmentVariable("DEEPSEEK_API_KEY", "sk-...", "User")
opencode service restart # User-scope variables only reach new processes
然后将插件添加到 opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"plugins": ["@qthinker/opencode-deepseek-search"]
}
哪个文件加载哪一半。 读取服务器插件和桌面面板
opencode.json(c)-桌面应用程序只读取该文件,a 全球~/.config/opencode/opencode.jsonc入口使面板出现在每个窗口中。读取TUI的一半cli.json("plugins": [...]). 所以一个插件每一半都是启用的:在你想要的那一半的文件中列出它,无论它来自npm(按包名)还是来自本地目录(按路径)。
与选项(推荐-这是哪里 mode 和朋友一起生活):
{
"plugins": [
{
"package": "@qthinker/opencode-deepseek-search",
"options": {
"mode": "deepseek",
"count": 5,
"apiKey": "{env:DEEPSEEK_API_KEY}"
}
}
]
}
存储库目录中的本地开发点(配置项必须是 目录,而不是文件):
{
"plugins": [
{ "package": "D:/repos/opencode-deepseek-search", "options": { "mode": "deepseek" } }
]
}
opencode plugin add <package-or-directory> 同样的编辑为您(它写 全球 配置),
opencode plugin list 然后应该显示 deepseek-search 与源 local 或者包名。
重载规则: 服务器一半 保存源文件时在适当位置重新运行-否 /reload,没有重启服务。
另外两半是客户端:重新启动 途易,并重新加载 桌面窗口,去捡个零钱来
tui.ts / gui-experimental.cjs (和运行 npm run build:gui 首先是克隆)。
选项
| 选项 | 类型 | 默认的 | 意义 |
|---|---|---|---|
mode | "deepseek" | "native" | deepseek | 的默认后端 websearch;一个坚持 deepseek_mode Switch覆盖它 |
apiKey | 字符串 | DEEPSEEK_API_KEY | 通常 "{env:DEEPSEEK_API_KEY}";未设置的嫉妒变成 "" |
count | 1-50 | 5 | 每次搜索结果(不改变价格) |
fetchMaxChars | 500 - 200000 | 30000 | 截断极限 deepseek_fetch,并附有明确通知 |
pricePerThousand | 0 - 10000 | 5 | 每1000个请求人民币(整数),仅用于本地成本估算 |
工具
| 工具 | 它是做什么的 |
|---|---|
websearch (内置) | 相同的名称和输入;在 deepseek 模式这个插件提供结果 |
deepseek_fetch | 输入一个URL,清除Markdown,删除 fetchMaxChars 有通知 |
deepseek_usage | 本地搜索/获取计数和估计成本; reset: true 清除它 |
deepseek_mode | 报告或切换搜索后端;交换机被持久化 |
路由 保留内置权限检查和声明的 output 形状,所以审批提示和呈现
是不变的。结果把 summary (600-800字,为模型编写)或 snippet -从来没有整页的文本,
和 need_content 从未被要求过。
切换后端
切换方式
| 道路 | 如何 | 坚持 | 用它来 |
|---|---|---|---|
| 侧边栏 | 点击途易卡上的动作([停用] / [启用]),或面板按钮 | 是(插件存储) mode/v1) | 当你工作的时候 |
| 配置 | 编辑 options.mode;保存时适用 | 是(在配置文件中) | 长期违约 |
| 工具 | 让模特打电话 deepseek_mode,或者你自己叫它 | 是(插件存储) mode/v1) | 在不接触文件的情况下切换会话 |
| 脚本 | .\tools\switch-mode.ps1 native | 是(脚本编辑配置) | 从终端快速切换,不需要编辑器 |
deepseek_mode 行动:
| 呼叫 | 效果 |
|---|---|
deepseek_mode (或 {"mode": "status"}) | 报告当前后端 以及它的来源 (配置文件/持久化开关) |
deepseek_mode({"mode": "deepseek"}) | 路由内置 websearch 深度搜索工具 |
deepseek_mode({"mode": "native"}) | 让内置后端保持原样 |
deepseek_mode({"mode": "config"}) | 清除持久化开关 options.mode 再决定 |
优先级
deepseek_mode switch (storage: mode/v1) > options.mode > built-in default
- 开关存在于OpenCode的本地插件存储(
mode/v1) - - - 对于安装是全局的,并在整个过程中持久化 重新启动 -它永远不会修改你的配置文件。 - 因为它胜过了配置文件,所以“什么都不做”的编辑意味着存在一个存储开关:ask
deepseek_mode(它命名源),然后使用mode: "config". - 提供者在两种模式下都注册了,所以在任何步骤中最坏的情况都是“保留以前的后端”——永远不会 “无法搜索”。
原生模式还能给你什么
websearch 完全独立,并服务于您现有的后端。 deepseek_fetch, deepseek_usage 和
deepseek_mode 保持注册(它们是附加的),并且提供者仍然是注册的,因此您可以选择它
明确与 providerID: "deepseek" 或配置 "websearch": { "provider": "deepseek" }.
为什么工具被重新路由,而不是依赖于一个默认的提供商:在2.2.5中,一个插件
websearch.default.set()是 被后来注册的内置配置插件覆盖,因此该工具继续使用内置提供程序。插件 因此修补内置工具本身;保留内置的权限检查,而“选择搜索”则保留 “提供者”表单在深度搜索模式中不会出现。如果某个版本没有公开该工具,deepseek_mode说它不能 在运行时切换-使用websearch.provider在配置中。
TUI和桌面侧栏
该插件还显示您工作的地方,并且可以在没有模型或配置文件的情况下切换:
| 表面 | 你得到了什么 | 如何切换 |
|---|---|---|
| 途易 | 一个DeepSeek块被附加到会话侧栏:state,然后是:Search · Fetch · ¥ 估计);它会退化为缩写,然后随着侧边栏的缩小而退化为更少的列 | 单击标题右侧的操作,或运行 /deepseek 菜单的斜杠命令 |
| 桌面 | 一、 DeepSeek 选项卡,在会话的侧区域中列出 新标签页 页面及其 + 菜单,并可使用 DeepSeek: 打开统计面板 命令 | 面板的按钮,加上刷新控件 |
- 两个表面读取相同的分类账和相同的存储开关
deepseek_usage/deepseek_mode:单身 服务器端源,通过插件自己的RPC到达,所以数字不会在TUI和桌面之间出现分歧。 - “停止”意味着手内建
websearch回到您配置的后端 (完全deepseek_mode({"mode": "native"}))。 这不是卸载:deepseek_fetch,deepseek_usage和deepseek_mode保持注册,国家就会 坚持mode/v1和其他开关一样。 - 动作行总是说点击做什么。如果没有配置API密钥,则不需要采取任何操作,如下所示
而解决方法是(
DEEPSEEK_API_KEY); 当内建工具无法修补时,它会报告,而不是 假装被启用。 - 的状态刷新
changed事件在每次计数和每次切换后触发,并在10秒内重新读取 两面后退。
桌面部分作为预构建的CommonJS包发布(gui-experimental.cjs). 发布的软件包包括它;如果你
从克隆中运行插件,构建一次——TUI部分不需要构建,像服务器部分一样从TypeScript加载:
npm install && npm run build:gui
使用和成本
| 计数器 | 计算时 | 宣传 |
|---|---|---|
search | HTTP 200和 results 非空 | 每次请求0.005元 |
fetch | HTTP 200和正文非空 | 每次请求0.005元 |
empty | HTTP 200的空结果/正文 | 不收费 |
failed | 网络错误,或者重试一次后非200 | 不收费 |
成本以整数元为单位累积,所以重复的加法永远不会漂移。 count 不影响价格。
deepseek_usage({ "reset": true }) 报告后清理分类账。
- 储存在
ctx.storage关键usage/v1,保存最近60天,日键为当地时间。 - 存储对于OpenCode安装是全局的,并且在重新启动后仍然有效。
- 本地统计数据≠你的DeepSeek账单:只有这台机器,这个插件。其他工具和机器不计算在内, 并发的OpenCode服务器可能会丢失计数(最后一次写入获胜)。
费率限制和成本
搜索100 QPS /获取每个帐户25 QPS(获取也限制每个目标域)。单个请求的成本
¥0.005。仅在408/429/5xx上重试一次,荣誉 Retry-After (上限为5分钟),并可取消。
隐私
查询和url被发送到 https://api.deepseek.com. 没有其他东西离开你的机器;使用分类帐和
模式切换留在本地OpenCode存储。API密钥永远不会被记录。
搜索结果和获取的页面是 第三方文本将它们视为数据,而不是指令——页面可以这样做 包含试图引导模型的文本。
故障排除
| 症状 | 原因/修复 |
|---|---|
| 不确定使用哪个后端搜索 | 呼叫 deepseek_mode -报告后端 和 其来源 |
| 配置编辑似乎被忽略了 | 存在一个持久化开关(源文件是这么说的);清除它 deepseek_mode({"mode": "config"}) |
未配置 DeepSeek API Key (缺少键) | 集 DEEPSEEK_API_KEY,重新启动OpenCode服务一次,以便新进程继承它 |
401 无效的关键 | 检查一下钥匙和那个 apiKey/env指向它 |
402 余额不足 | 充值;失败的请求不会被计费 |
429 速度有限 | 已经后退过一次了;重试后 |
403 / 404 在获取 | 网站阻止提取或页面没有可读的文本;试试内置的 webfetch |
| 搜索仍然会访问本地后端 | mode 或者持久化开关是 native;如果两者都是 deepseek,内置的 websearch 没有找到工具-使用配置 "websearch": { "provider": "deepseek" } |
| TUI侧边栏没有DeepSeek卡 | TUI一半已启用 cli.json ("plugins": [...]),不在 opencode.jsonc;添加路径/包并重新启动TUI |
| 中没有DeepSeek条目 新标签页 列表 | 程序中读取插件 全球 opencode.jsonc,并且它的bundle必须存在- run npm run build:gui 当从克隆中工作时,请重新加载窗口 |
侧边栏表示 读取失败 | 一半无法到达RPC: check opencode plugin list 报告 deepseek-search 作为主动,然后寻找 /api/rpc/deepseek-search/status 在 ~/.local/share/opencode/log/opencode.log. 一个 400 rpc.invalid_input 意味着一半和服务器不同意合同-重新加载该客户端 |
地方发展
cd D:\repos\opencode-deepseek-search
npm install
npm run typecheck # tsc --noEmit, both the server/TUI config and the GUI config
npm test # node --test, pure functions, zero cost
npm run build:gui # src/gui -> gui-experimental.cjs (the desktop half's bundle)
node --experimental-strip-types scripts/check-gui-bundle.ts # bundle shape check, run in CI
npm run smoke # real API smoke; skipped without DEEPSEEK_API_KEY
npm pack --dry-run # audit the publish artifacts — run build:gui first, `pack` does not build the bundle
一命令开关(仅支持repo的助手)编辑 options.mode 在 opencode.jsonc把它备份到 opencode.jsonc.bak-switch):
.\tools\switch-mode.ps1 status
.\tools\switch-mode.ps1 native
.\tools\switch-mode.ps1 deepseek
如果ExecutionPolicy阻止它:
powershell -NoProfile -ExecutionPolicy Bypass -File .\tools\switch-mode.ps1 native
更短,通过别名 $PROFILE:
function dsmode { & "D:\repos\opencode-deepseek-search\tools\switch-mode.ps1" @args }
布局:
index.ts # directory-plugin entry, re-exports src/index.ts
tui.ts # TUI entry, re-exports src/tui/main.ts
src/index.ts # plugin: options, registration, websearch patch, three tools
src/deepseek.ts # HTTP core: timeout/cancel, single backoff retry, Chinese errors, mapping
src/usage.ts # pure ledger: micro-CNY pricing, 60-day prune, defensive parse, formatting
src/rpc.ts # RPC contract shared by the server, TUI and desktop halves
src/status-view.ts # pure view model both sidebars derive their copy from
src/tui/ # TUI half: card element tree + plugin wiring
src/gui/ # desktop half: side panel component + plugin wiring
vite.config.ts # builds src/gui into the root gui-experimental.cjs bundle
test/*.test.ts # pure-function tests
scripts/smoke.ts # real-API smoke (5 steps)
scripts/check-gui-bundle.ts # bundle shape check, run in CI after build:gui
tools/switch-mode.ps1 # terminal backend switch
.github/workflows/ # ci (build + typecheck + test + bundle check) / release
两个包装陷阱(已经避免-不要再引入它们):
- 配置的本地插件路径必须为 目录;单个文件被删除。
- 做。 不 添加
exports来package.json:name+exports, OpenCode按包解析目录 名称,当解析的入口点位于目录之外时,它就是 默默的下降 (没有计程仪, 它就这样从plugin list)。
两者都适用于插件的每一半: index.ts, tui.ts 和 gui-experimental.cjs 位于存储库根,
这就是目录和安装包解析路径所查找的内容。 test/packaging.test.ts 失败,如果
exports 返回或根条目停止解析。
源代码编辑在保存时热重新加载;验证与 opencode plugin list 加上一次真正的搜索。
许可证
麻省理工学院。与DeepSeek无关。