dsh-external-bridge:让外部进程通过本机 HTTP 驱动桌面 DSH 真会话

前言

DeepSeek Harness(DSH)桌面版的主界面适合人手点选建会话、看侧栏滚动。想在终端里跑的 Claude Code、自建脚本或 CI 助手去「遥控」同一套宿主时,常见做法是 dsh headless 或碰宿主自带的 Web 口。前者建的会话只落在 ~/.dsh/sessions/,不进 workspace.json,GUI 侧栏看不到;后者对没有 GUI 凭据的请求一律 401,外部进程接不上。

dsh-external-bridge 是社区维护的 DSH 客户端侧 Host 插件(维护者 Jason25417,MIT 许可)。它在 loopback 上单独起一个 HTTP 服务,用 Bearer token 鉴权,调用宿主 sessionController.create 等能力,建出来的是和工作区侧栏里手动新建无区别的真会话。下文按定位、能力、安装、调用顺序说明。

这是什么

插件全名 dsh-external-bridge(npm 包名同称,当前版本 0.2.1)。运行时不改 DSH 本体、不改 @yunmiao/studymate,仅在 ~/.dsh/profiles/desktop/plugins/dsh-external-bridge/ 增加插件目录。

监听地址固定为 127.0.0.1:39217。端口被占用则启动失败并在日志说明,不会静默换端口。依赖 Node >= 22,宿主 DSH 0.2.x(package.json 要求 dsh >= 0.2.1-rc.0 < 0.3.0)。

与宿主自带 HTTP 口的区别

桌面宿主另有 Web 口(例如 127.0.0.1:50186、*:3081),外部进程没有 GUI 客户端凭据时会一直收到 401 unauthorized。本插件不挂 connection.fetch,用 node:http 自建 loopback 监听,启动时生成 32 字节随机 token(base64url),写入 ~/.dsh/secrets/external-bridge.token(目录 0700、文件 0600)。每个请求须带 Authorization: Bearer <token>,否则 401。插件 dispose 时关闭监听。

核心功能

会话与可见性

  • POST /sessions:创建会话;可选 agentPreset、provider / model / reasoningEffort、firstPrompt。workspaceId 与 cwd 二选一(推荐已注册的 workspaceId,保证侧栏可见)。
  • POST /sessions/:id/prompt:投递用户消息;mode 为 queue(默认)或 steer。
  • GET /sessions/:id:读 state(running | idle | error)、lastAssistantText、turnCount、必要时 error。
  • **GET /sessions/:id/wait?timeoutMs=:长轮询等回复;默认 30 秒,timeoutMs` 上限 240 秒。
  • GET /sessions:按工作区列出会话 id。
  • GET /health:返回 version、presets、models(拿不到则为 null)。

建会话走宿主 sessionController.create;指定模型时插件在 create 之后调用 selectModel,并在成功后恢复用户原先的全局默认模型,避免悄悄改掉 GUI 里的默认选项。

若 cwd 不属于任何已注册工作区,仍会建会话,但响应可能带 warning:会话存在,侧栏可能不显示。模型不可用时可能返回错误,但仍可能携带 sessionId 供调用方接续处理。

所有成功/失败响应均为 JSON;失败形如 { "ok": false, "error": { "code", "message" } }。请求体上限 1 MiB。

安装与启用

插件已打包为 DSH bundle(package.json 的 dsh.bundle)。推荐用官方插件命令安装,然后完全退出并重开 DSH Desktop(Host 插件只在启动时挂载):

dsh plugin --profile desktop add dsh-external-bridge

安装来源可以是 npm 包、tarball 或本地路径。源码 checkout 场景可在 ~/.dsh/profiles/desktop/cordis.patch.yml 末尾追加 external-bridge 的 file:// Host 条目;回滚时删除对应段落并重开桌面宿主。细节见仓库 README「挂载」一节。

验证服务是否起来

桥启动后,可用 token 文件探活:

test -f ~/.dsh/secrets/external-bridge.token && ls -l ~/.dsh/secrets/external-bridge.token
TOKEN=$(cat ~/.dsh/secrets/external-bridge.token)
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:39217/health | jq

若返回 "ok": true 且带有 version、presets、models 等字段,说明监听正常。排错可在宿主日志中搜索 [dsh-external-bridge] 或 external bridge;端口冲突可用 lsof -nP -iTCP:39217 -sTCP:LISTEN 检查。

典型调用流程

下面是一条可复现的最小链路:先健康检查,再建会话并带首条 prompt,最后长轮询取助手正文。

1、确认 token 与 health(见上一节)。

2、创建会话(示例 JSON 字段以你环境 /health 返回的 preset、model 为准):

curl -s -X POST http://127.0.0.1:39217/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "ws_xxx",
    "agentPreset": "learning",
    "provider": "opencode-go-4",
    "model": "deepseek-v4-pro",
    "reasoningEffort": "max",
    "firstPrompt": "只回复两个字:收到"
  }' | jq

成功时得到 sessionId 等字段。

3、若需追加消息:

curl -s -X POST "http://127.0.0.1:39217/sessions/<sessionId>/prompt" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "继续", "mode": "queue"}' | jq

4、等待或轮询状态:

curl -s -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:39217/sessions/<sessionId>/wait?timeoutMs=30000" | jq

lastAssistantText 为最后一条带正文的助手回复(工具调用行不计入)。空闲或出错会立即返回;超时则 state 仍为 running 且 timedOut: true。

适用场景与注意

适合谁:需要在同一台机器上用脚本或外部 Agent 编排 DSH,又希望会话出现在桌面工作区侧栏、消息与 GUI 手动操作一致可见的开发者。

安全与权限:服务只绑定 loopback,token 存于本机 ~/.dsh/secrets/。插件以当前 DSH 桌面进程权限运行;安装前应自行审阅 GitHub 源码 与 MIT 许可证。

生态说明:DSH 奉行「一切皆插件」;SkillHub 目录页 为社区收录,与 DeepSeek / 幻方无官方从属关系。

结尾

dsh-external-bridge 补上的是「外部自动化 + 桌面真会话」之间的缺口:本机 HTTP、独立 token、标准 REST 式会话生命周期。需要细节、错误码表与模型/状态读取实现说明时,以仓库 README 为准。

  • 目录页:https://www.skillhub.cn/plugins/Jason25417/dsh-external-bridge
  • GitHub:https://github.com/Jason25417/dsh-external-bridge
羽毛球分组比赛记分
小程序二维码

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

小夜