leeyoung1/dsh-web-search-opencode-go

dsh-web-search-opencode-go

Fix DSH web_search through OpenCode Go / Zen: auto-inject x-opencode-session. Drop-in patched fork of @deepseek-ai/dsh-web-search-deepseek.

待分类cross-platformdeepseekdeepseek-harness

dsh-web-search-opencode-go

English | 中文

修复 DSH web_search 走 OpenCode Go / OpenCode Zen 时的 MissingSessionID 报错。 网关会拒绝缺少 x-opencode-session 的 Anthropic Messages 请求:

Error from provider (Console Go): Request is missing x-opencode-session and cannot be routed efficiently.
Please see https://opencode.ai/docs/go/#where-can-i-use-it

本仓库是 @deepseek-ai/dsh-web-search-deepseek 的同名 drop-in 补丁分支,适用于 DeepSeek Harness。 它会自动注入:

  • x-opencode-session —— 当前 DSH agent 会话 id(或配置的 id / 插件级 UUID 兜底);
  • x-opencode-client: dsh。

这样内置 web_search 工具即可恢复正常,且不需要修改官方 DSH 安装目录。

一句话用法: 在 DSH 里存好 OpenCode Go key → 设置 web-search-deepseek.baseURL → 运行安装脚本 → 重启 dsh web → 照常使用 web_search。详细步骤见使用方法。

这个补丁改变了什么

这不是新的 CLI,也不是新的 web_search 命令。安装并重启 dsh web 后:

  • 你现有的 web-search-deepseek 配置保持不变;
  • agent 平时的每一次 web_search 调用都会走补丁后的 provider;
  • 补丁 provider 自动补上 OpenCode Go / Zen 需要的路由头。

不需要改 profile patch,不需要新增工具,也不需要改提示词。

问题原因

DSH 内置搜索提供方请求的是 Anthropic 兼容 Messages 端点:

POST {baseURL}/messages

如果你这样指向 OpenCode Go:

web-search-deepseek:
  baseURL: https://opencode.ai/zen/go/v1

上游提供方只会发送常规请求头(x-api-key、authorization、anthropic-version 等), 而 OpenCode Go 还要求一个会话路由头,缺失就返回 MissingSessionID / HTTP 400。 OpenCode Go 本身支持原生 web_search_20250305,缺的只是这个路由头。

修复内容

本分支保留官方提供方逻辑,新增:

  • 对 opencode.ai 端点自动注入 x-opencode-session / x-opencode-client;
  • 额外的 headers、sessionId 配置,便于兼容其他网关;
  • 安装脚本会把补丁包复制到 DSH web profile 中 bundle 本来就会解析的路径:
~/.dsh/profiles/web/node_modules/@deepseek-ai/dsh-web-search-deepseek

DSH 安装目录(/opt/homebrew/...、npm -g 等)里的官方包不会被改动。

快速开始

需要 Node.js 20+(或可用的 dsh + pnpm),并已存在 DSH web profile。 有两种安装方式;方式 A 就是插件市场使用的路径。

方式 A —— 作为 DSH bundle 安装(推荐)

dsh plugin --profile web add github:leeyoung1/dsh-web-search-opencode-go
# 然后重启 dsh web

本包声明了 dsh.bundle,所以 dsh plugin 会自动把它加入 dsh.profile.bundles。它的 cordis.patch.yml 会禁用官方 web-search-deepseek 行,并在同一位置插入补丁 provider。

npm 包发布后,命令可以更短:

dsh plugin --profile web add dsh-web-search-opencode-go
# 然后重启 dsh web

方式 B —— drop-in 复制(离线 / 不用 pnpm)

把补丁包复制进 profile 的 @deepseek-ai 槽位,遮蔽官方包;不需要包管理器, macOS、Linux、Windows 通用。

macOS / Linux:

git clone https://github.com/leeyoung1/dsh-web-search-opencode-go.git
cd dsh-web-search-opencode-go
./mount.sh
# 然后重启 dsh web

Windows(PowerShell 或 cmd):

git clone https://github.com/leeyoung1/dsh-web-search-opencode-go.git
cd dsh-web-search-opencode-go
node .\bin\dsh-web-search-opencode-go.mjs
# 然后重启 dsh web

mount.sh 只是 POSIX 便捷包装,调用的是同一个 Node 安装脚本。

非默认 profile / DSH home

macOS / Linux:

DSH_PROFILE_DIR=/path/to/profile ./mount.sh
# 或:DSH_HOME=/path/to/dsh-home ./mount.sh

Windows:

$env:DSH_PROFILE_DIR = "C:\path\to\profile"
node .\bin\dsh-web-search-opencode-go.mjs

常用参数(方式 B)

--dry-run     只显示将要进行的修改,不写 profile
--uninstall   把补丁复制件移走,并恢复之前的条目
--help        查看用法与环境变量

最后必须重启 dsh web,因为 DSH 只在启动时加载插件。

使用方法

1. 在 DSH 里存好 OpenCode Go API key

打开 设置 → Models,把 OpenCode Go 的 key 存成以下任一个名字:

  • DEEPSEEK_API_KEY(provider 默认),或
  • OPENCODE_GO_API_KEY(然后在下面的配置里写 apiKeyEnv: OPENCODE_GO_API_KEY)。

每次搜索都会重新解析 key,所以轮换 key 不需要重启。

2. 把内置搜索 provider 指向 OpenCode Go

编辑 ~/.dsh/settings.yaml:

web-search-deepseek:
  baseURL: https://opencode.ai/zen/go/v1
  apiKeyEnv: DEEPSEEK_API_KEY   # 默认值;OPENCODE_GO_API_KEY 也可用
  model: deepseek-v4-flash      # 默认值

3. 安装补丁并重启

按上面的快速开始安装,然后重启 dsh web。

4. 正常使用

没有新命令。直接对 agent 说:

搜索一下 DeepSeek Harness GitHub 的最新信息

或者让 agent 调用:

web_search: DeepSeek Harness GitHub

预期:正常返回结果,不再出现 MissingSessionID。每次搜索会以 web/deepseek-search-llm-request 事件记录在 DSH 会话日志中。

配置

你现有的配置无需改动:

web-search-deepseek:
  baseURL: https://opencode.ai/zen/go/v1
  apiKeyEnv: DEEPSEEK_API_KEY   # 默认值;OPENCODE_GO_API_KEY 也可用
  model: deepseek-v4-flash      # 默认值

可选的新字段:

web-search-deepseek:
  baseURL: https://opencode.ai/zen/go/v1
  headers:
    x-opencode-client: dsh      # 覆盖任意自动生成的标头
  sessionId: my-fixed-session   # 显式指定 OpenCode 路由会话

x-opencode-session 的优先级:

  1. 显式配置的 headers['x-opencode-session']
  2. sessionId 配置
  3. 当前 DSH agent 会话 id
  4. 插件级 UUID 兜底(agent 会话之外的直接调用)

x-opencode-client 默认为 dsh,同样可以被覆盖。

安装方式说明

支持两种安装方式:

  • DSH bundle(方式 A):package.json 声明 dsh.bundle.patch = ./cordis.patch.yml。dsh plugin add 会把包装进 dsh.profile.bundles;patch 禁用官方 web-search-deepseek 行,并插入本 provider,settings 命名空间(web-search-deepseek)与 provider id (deepseek-official)保持不变。
  • drop-in 复制(方式 B):Node 安装脚本把本包复制到 <profile>/node_modules/@deepseek-ai/dsh-web-search-deepseek。Node 会优先 解析这个路径,而不是共享的 profiles/node_modules,于是原有 bundle 行会 加载到补丁 provider。

两种方式都保留你现有的 web-search-deepseek 配置,不需要改 settings。

drop-in 方式下,如果目标路径已存在,脚本会先把它移到 dsh-web-search-deepseek.unpatched-<timestamp>,而不是直接删除。 DSH 升级或 pnpm/npm 重装恢复了官方包之后,重新运行安装脚本并重启 dsh web 即可。

卸载 / 回滚

任意系统都可以用跨平台卸载命令:

npx dsh-web-search-opencode-go --uninstall
# 或在克隆目录中:
node ./bin/dsh-web-search-opencode-go.mjs --uninstall
# 重启 dsh web

它会把补丁复制件移到 dsh-web-search-deepseek.uninstalled-<timestamp>, 并在存在 .unpatched-* 备份时恢复最近的备份;没有备份时 Node 会重新解析 到官方包。

手动等价操作:

  • macOS / Linux:

    rm -rf ~/.dsh/profiles/web/node_modules/@deepseek-ai/dsh-web-search-deepseek
    # 重启 dsh web
    
  • Windows PowerShell:

    Remove-Item -Recurse -Force "$env:USERPROFILE\.dsh\profiles\web\node_modules\@deepseek-ai\dsh-web-search-deepseek"
    # 重启 dsh web
    

兼容性

  • DSH 0.1.x 系列(已在 0.1.1-rc.2 验证)。
  • 与 @deepseek-ai/dsh-web-search-deepseek@0.1.1-rc.2 API 兼容。
  • OpenCode Go / OpenCode Zen 的 Anthropic 兼容端点。
  • Node.js 20+。
  • macOS、Linux、Windows。安装脚本只做文件复制,不使用符号链接或管理员专属 API;CI 会在三种系统上运行安装测试。

常见问题

现象原因处理
安装后仍报 MissingSessionID没有重启 dsh web重启 dsh web。
WEB_PROVIDER_CREDENTIAL_MISSINGDEEPSEEK_API_KEY 没有存密钥在 DSH 设置 → Models 里存密钥,或设 apiKeyEnv: OPENCODE_GO_API_KEY。
DeepSeek search request failed / HTTP 401/403密钥与端点不匹配用 OpenCode Go 密钥配 opencode.ai,或把 baseURL 改回 DeepSeek 官方端点并配 DeepSeek 密钥。
提供方不可用baseURL 无法解析使用带 /v1 的完整基址,例如 https://opencode.ai/zen/go/v1。
DSH 升级后搜索又坏了profile 恢复了官方包重新运行安装脚本(./mount.sh、npx dsh-web-search-opencode-go)并重启。
Windows 安装时报 EPERM / EBUSYdsh web 正在运行,profile 文件被锁定先停止 dsh web,重新运行安装脚本,再启动。

开发

npm test                 # 标头 + 跨平台安装脚本测试(无外部依赖)
npm run link-deps        # 可选:链接官方包,便于在克隆目录直接导入完整 provider
node ./bin/dsh-web-search-opencode-go.mjs --dry-run

测试只导入无依赖的 lib/headers.js。只有需要在克隆目录中导入完整 lib/index.js 时才需要 link-deps;安装后的副本会通过 profile 的 node_modules 父目录解析官方包。

仓库元信息(便于搜索)

建议的 GitHub 仓库名、描述与 topics:

  • 仓库名: dsh-web-search-opencode-go
  • 描述: Fix DSH web_search through OpenCode Go / Zen: auto-inject x-opencode-session. Drop-in patched fork of @deepseek-ai/dsh-web-search-deepseek.
  • Topics: dsh, deepseek-harness, deepseek, opencode, opencode-go, opencode-zen, web-search, websearch, dsh-plugin, x-opencode-session, MissingSessionID, cross-platform, windows, macos, linux

可直接执行的 gh 与 npm 命令见 docs/publishing.md。

许可证与归属

MIT。提供方实现派生自 DeepSeek 的 @deepseek-ai/dsh-web-search-deepseek(同样为 MIT), 原始许可证保留在 LICENSE。

本仓库是非官方社区补丁,与 DeepSeek、OpenCode 无隶属关系。