把 OpenCode 接成 DSH 子代理后端:yhuan416/dsh-opencode-client

前言

如果你的 dsh 需要把活派给一个常驻的 OpenCode 服务,又不想在终端、网页和 dsh 之间来回手工搬运上下文,dsh-opencode-client 就是为这种情况写的。插件直接连到远程的 opencode serve 实例,把它的 project、session、message 暴露成 dsh 里的工具,再把 OpenCode 注册成 dsh 的原生 subagent 后端。

已有的做法一般是在 dsh 里开一个外部命令 subagent,或者自己写脚本调 OpenCode 的 HTTP API。前者上下文只能跑一次,后者要自己维护鉴权、轮询、权限回调。这个插件把这层补齐了:多服务器配置、SSE 事件、权限审批卡、会话续跑和 workspace 操作都内置。

这是什么

yhuan416/dsh-opencode-client 是 DeepSeek Harness(DSH)插件,由 yhuan416 维护。它充当 OpenCode 的 client:连接一台或多台远程 opencode serve,把远端的 projects / sessions / messages 带到 dsh 里,支持把任务委派进去,并提供把 OpenCode 作为原生 dsh subagent 后端的能力。

OpenCode 自身架构里,opencode serve 暴露一个 OpenAPI HTTP 服务,TUI、Web UI、SDK 都是它的 client。这个插件是其中一个 client,宿主是 dsh。插件自身的定位写得也很清楚:主要角色是注册 OpenCode 为原生 subagent 后端(opencode_subagent_<server>),并把远端会话、workspace 暴露为工具;内嵌 OpenCode Web UI 是可选便利,不是替代。

仓库信息:MIT License,stargazers_count 为 0(截至 2026-11-08,来自 GitHub API),未发布到 npm,需要从 git 或本地路径安装。README 明确已验证 dsh 0.2.1-rc.2 与 OpenCode 1.18.10 / 1.18.31 / 1.18.33。

核心能力

服务器配置与发现

通过 servers 数组配置多台实例,每台可以是 id / label? / url / password? / directory?。发现能力由 GET /api/opencode-client/list 提供,返回服务器健康状态、projects 以及按 directory 分组的 sessions。会话列表走工具 opencode_sessions 或 GET /api/opencode-client/sessions,消息走 opencode_messages 或 GET /api/opencode-client/messages。

会话读取与逐轮续跑

opencode_session_info 拿 title / summary / todos / diff;opencode_share 生成或取消分享链接。opencode_prompt 向一个已存在的远端会话发一条消息,默认 fire-and-forget,加 wait=true 可阻塞;再用 opencode_messages 或 opencode_progress 读结果,然后发下一条。这是让远端 worker 会话跨 dsh turn 存活的关键。

委派与原生子代理

opencode_subagent 新建会话,或用 session= 继续;可选 agent、model 和 prompt-enforced schema。实现上用的是 prompt_async 加消息轮询,失败时回退到阻塞式 prompt。提交时支持 files JSON 数组(text/base64 → data URL file parts)。

原生子代理通过在 profile 里加一行 tool-subagent 注册,provider 名是 opencode-<serverId>,生成 opencode_subagent_<server> 工具,接入 dsh 的 ctx.subagents provider seam。它和 opencode_subagent 共用同一个 session-run 生命周期(lib/session-run.js),包括会话创建、交互追踪、async prompt + SSE idle 等待、abort 处理。README 说原生子代理会话标题为 dsh subagent: <label>,便于在插件页面识别。

实时进度与中止

opencode_progress 读当前 tool/step、耗时和输出尾部,数据来自 SSE tool event,委派在 SSE idle 事件上判定完成。每台服务器还有独立的 SSE 订阅(/global/event,带重连),用于快速处理 permission / question、刷新 live state,以及 GET /api/opencode-client/events 和 /status。

opencode_abort 停掉运行中的远端会话,等待中的委派会返回 abort error 而不是悬挂。注意 README 明确:同 turn 内 tool call 是串行的,所以必须从另一个 dsh session 或 agent 调用它,才能中止本 turn 里阻塞的 opencode_subagent。

工作区与权限

workspace 操作工具有 opencode_shell、opencode_git_status、opencode_git_diff、opencode_read_file、opencode_find。opencode_init 会写 AGENTS.md,需要 confirm=true;opencode_fork、opencode_children、opencode_summarize(mutating)用于会话管理。opencode_command 在会话里执行远端命令,例如 init。另外还有目录类工具:opencode_models(providers/models,credentials 已剥离)、opencode_commands、opencode_skills、opencode_tools、opencode_references、opencode_agents(区分 primary/subagent、native/custom),以及诊断用的 opencode_search(v2 session search)和 opencode_mcp(MCP server 状态)。

权限方面,permission: ask(默认)把远端权限请求变成 dsh 的 approval card,allow / reject 是确定性回答。question: reject(默认)拒绝交互式提问,也可设为 "ignore" 它们。README 在 Notes 里说明:交互式问题只有在 run 由 opencode_subagent 启动(agent 在 scope 内)时才会转发到 dsh 的 user-question UI,否则会被拒绝。

内嵌 OpenCode UI

插件支持注册一个右侧栏 tab(kind: opencode),内容是 server picker 加上真实 OpenCode Web UI 的 iframe,显示在当前会话页面里。可以从服务器列表的「侧边栏打开」按钮打开,也可以走右侧栏 add-tab 引导;「全屏」overlay 和「新标签」仍作为兜底。README 强调没有重新实现,内嵌页面保留 streaming、tool cards、diffs 和 permissions。插件页面本身还有单独的 “OpenCode Client” 区块,展示 servers / workspaces / sessions、session ids、active tool、messages,并可创建会话。

安装与启用

从本地路径安装并加入 web profile:

dsh plugin --profile web add /path/to/dsh-opencode-client

或者手动写入 profile 的 dependencies,并把它选为 bundle:

{
  "dependencies": { "dsh-opencode-client": "file:/path/to/dsh-opencode-client" },
  "dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-opencode-client"] } }
}

安装前需要先看源码和 LICENSE(仓库标注 MIT)。注意它目前没有 npm 包,README 说从 git 或本地路径安装。

配置

配置写在插件条目的 config 下,多台服务器并列:

- id: opencode-client
  name: dsh-opencode-client
  config:
    servers:
      - id: n100
        label: n100 opencode
        url: http://192.168.4.50:4096
        # password: xxx          # OPENCODE_SERVER_PASSWORD (basic auth, user "opencode")
        # directory: /home/yhuan/workspace   # default remote dir when the caller does not give one
        # agent: plan            # default OpenCode agent for delegation
        # model: deepseek/deepseek-chat      # default model "provider/model"
      - id: m65
        label: 4.65 opencode
        url: http://192.168.4.65:4096
    permission: ask              # ask (default, dsh approval card) | allow | reject
    question: reject             # reject (default) interactive questions or "ignore" them
    pathMap:                     # only when local and remote path layouts differ
      - { from: /home/yhuan, to: /home/yhuan }

要把它当成原生 dsh subagent,加一行 tool:

- insert:
    - id: tool-opencode-n100
      name: "@deepseek-ai/dsh-tool-subagent"
      config:
        provider: opencode-n100   # "opencode-" + server id
        maxDepth: provider-managed
        toolName: opencode_subagent_n100

典型用法

先用发现接口确认服务器可达、projects 和 sessions 能列出:

curl http://192.168.4.50:4096/api/opencode-client/list

在 dsh 里把一个任务派给远端新会话:

opencode_subagent 还有一堆 CSV 需要清洗,在 /home/yhuan/workspace 下新建会话处理,agent 用 plan,模型用 deepseek/deepseek-chat

需要跨 dsh turn 保留同一个远端会话时,用 opencode_prompt 逐条发消息,回复后 opencode_messages 取结果,再发下一条。想盯着执行过程就用 opencode_progress 看当前 tool 和输出尾部;发现状态不对,从另一个 dsh session 调 opencode_abort 停掉。

远端要临时跑点东西,用 workspace 工具而不是另开 shell:opencode_shell、opencode_git_diff、opencode_read_file 都可以直接作用到远端目录。pathMap 只在本地和远端路径布局不一致时才需要配。

适用场景与注意

适合这几类人:已经在用 opencode serve 做常驻代码服务、想把 dsh 和它打通的人;想统一委派入口,而不是手写 HTTP 调用脚本的人;想让 OpenCode 作为 dsh subagent 后端之一参与多后端编排的人。

注意事项摘自 README:

  • 远端 OpenCode 服务必须能被 dsh 宿主访问。opencode serve 默认绑 127.0.0.1,需要绑 0.0.0.0 或放在 SSH 隧道后面。
  • 会话续跑走 OpenCode HTTP API;原生外部 subagent 仍然是执行一次,行为与 Codex / Claude Code backend 一致。
  • 结构化输出是通过 prompt 约束,不是 format= 约束。opencode 1.18.x 存在上游 bug:prompt 带 format: {type:"json_schema"} 后,服务会持久化一个 retryCount 字段,导致 GET /session/{id}/message 返回 400,会话被污染。插件因此在 prompt 末尾追加一段约束输出的说明来绕开。
  • 插件以当前 dsh 进程的权限运行。装之前检查源码,确认 servers 里配置的 url、password 和你暴露的 directory 范围符合预期;opencode_init、opencode_summarize、opencode_shell 都属于会改远端状态或执行命令的工具。
  • permission 默认是 ask,会把远端权限请求转成 dsh 审批卡;如果你希望全自动跑,改成 allow 之前先想清楚后果。

文档在仓库里:ARCHITECTURE.md(模块图、数据流、设计决策)、COMPATIBILITY.md(dsh / OpenCode 兼容性与版本策略)、docs/subagent-seam.md(subagent provider contract)、docs/chat-ui-proposal.md(页面内远程会话聊天提案),另有中文版 README.zh.md、TODO.md、CHANGELOG.md。

结尾

这个插件解决的是一个具体的接头问题:让 dsh 能用工具和原生 subagent 两种方式驱动一个已经在线运行的 OpenCode 服务,同时保留远端的实时进度、权限审批与会话续跑能力。它并非 OpenCode 的全功能克隆,远端 UI 而已;真正的计算和上下文仍在 opencode serve 那一侧。

目录页:https://www.skillhub.cn/plugins/yhuan416/dsh-opencode-client
源码:https://github.com/yhuan416/dsh-opencode-client

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜