dsh-web-service
让任何会说 HTTP 的东西驱动 DSH:47 条路由(REST + SSE),覆盖工作区、会话(创建/提示、SSE 实时生成、历史、统计、任务清单、中止、问答)、模型与全局默认模型、提供方、Agent Preset、设置命名空间、技能与工作区文件(含分片续传上传),另有 OpenAI 兼容的 /chat/completions、内置 OpenAPI 3.0 规范与在线调试页。它只 inject 宿主的 webServer 与 tools,挂在宿主 webserver(默认前缀 /api/v1)或独立端口,可选 API Key 鉴权,并自带一份教会 DSH 里 Agent 调用本 API 的
安装
dsh plugin --profile web add dsh-web-service
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-webapi (dsh-web-service)
[English](README.md) | 中文
第一次用?先看图文版 [使用教程](docs/TUTORIAL.zh.md)。
把 DeepSeek Harness 通过 HTTP 开放出来:DSH 里的工作区、会话、模型、设置、技能与文件直接变成
REST 接口与 SSE 流,再加一个 OpenAI 兼容的 /chat/completions,现成的 OpenAI 客户端不用改就能接到 DSH。
典型用法:给 DSH 做一个自托管控制台、桌面或移动端客户端、驱动 Agent 的 CI/自动化流程、
把 DSH 当成工具调用的其它 Agent,或在 DSH 前面再包一层自己的 API 网关。
- 零新增依赖:插件只
injectwebServer与tools,路由挂在 DSH 宿主的 webserver 上,并可另开一个可随时启停的独立固定端口服务。 - 80+ 条路由(REST + SSE),内置 OpenAPI 3.0 规范、在线调试页,以及可启停独立 API 服务的设置页。
- 自带 SKILL:
skills/dsh-web-service/SKILL.md教会 DSH 里的 Agent 调用本 API(流式、中止、
回答挂起问题、上传文件等)。
安装
兼容 DSH 0.1.0–0.2.x(peer 范围见 package.json;已在 0.1.7-rc.2 上运行验证,并在 0.2.0-rc.2 上通过类型检查与运行时装配验证)。
方式一:预构建 tarball(推荐,免构建、免 allowBuilds 授权)
dsh plugin --profile web add \ https://github.com/toddpan/dsh-webapi/releases/latest/download/dsh-web-service.tgz
dsh plugin 会把该包写进 profile 的 package.json(依赖 + dsh.profile.bundles);
带 HMR 的 profile 会立即装配,否则重启 DSH 生效。探活:
curl -s http://127.0.0.1:3080/api/v1/system/status # {"ok":true,...}
curl -sI http://127.0.0.1:3080/api/v1/docs # HTTP/1.1 200 OK
升级提示。 资产名不带版本号,latest/download/dsh-web-service.tgz 对全新安装永远指向最新构建;
但包管理器可能复用该 URL 的旧解析结果。要把已有安装切到确定版本,用带版本号的资产:
dsh plugin --profile web add https://github.com/toddpan/dsh-webapi/releases/download/v0.1.11/dsh-web-service-0.1.11.tgz
方式二:直接从 git 仓库安装(插件管理器的「GitHub 仓库地址」安装方式)
dsh plugin --profile web add github:toddpan/dsh-webapi
lib/ 已入库,所以从 git 装的包可直接运行。lib/ 与 src/ 保持同步——改动 src/ 后,
请在同一次改动里重新构建并提交 lib/。
方式三:从源码构建(需要一份 DSH 源码 checkout)
git clone https://github.com/toddpan/dsh-webapi && cd dsh-webapi DSH_CHECKOUT=/path/to/deepseek-harness bash scripts/build.sh # src/ → lib/ dsh plugin --profile web add "$PWD"
scripts/build.sh 会从 checkout 软链 cordis / schemastery / @deepseek-ai/* 等 peer,无需 npm install。
配置
全部可选,装好后写在 profile patch 的插件行 config 里(默认值见 src/index.ts):
字段 · 默认 · 说明
pathPrefix · /api/v1 · 路由前缀
apiKey · '' · 非空则开启鉴权,请求需带该 key
standalonePort · 0 · 首次安装时的初始端口;0 = 自动分配(31800-31899)。分配后以设置页为准,配置不再覆盖
standaloneBindIp · 127.0.0.1 · 首次安装时的初始监听范围:127.0.0.1(仅本机)或 0.0.0.0(局域网可达);之后以设置页为准
cors · true · 是否允许跨域
defaultCwd · '' · 默认工作目录,留空取 process.cwd()
maxUploadBytes · 2 GiB · 上传大小上限,大文件建议走分片接口
adminRemoteAccess · false · 是否允许非回环地址访问 API Key 管理接口;默认仅本机可管理密钥
apiKey 只是「遗留单 Key」,向后兼容用。日常管理请到设置页生成/吊销多条 Key,详见
[API Key 管理](#api-key-管理设置页)。
API 服务(独立固定端口)
插件自带一个独立的 HTTP 服务,与 DSH 主 webserver 解耦——主端口每次启动都会变,
独立服务端口固定,适合写进三方客户端、脚本或反向代理。
- 首次安装自动分配端口:从 31800 起找空闲端口,分配后固定不变。
- 在设置页启停:
GET /api/v1/settings/api-keys→ 「API 服务」卡片;端口与监听范围
(127.0.0.1 仅本机 / 0.0.0.0 局域网)随时可改,即时生效、无需重启 DSH。
- API 地址实时显示:改端口或监听范围时,地址区随表单实时预览;运行中显示真实地址,可一键复制。
- 状态持久化:运行中的服务在 DSH 重启后自动恢复同一端口;停止后重启 DSH 仍保持停止。
设置文件:<DSH_HOME>/dsh-web-service/service-settings.json(0600)。旧版 fixedPort
格式会在读取时自动迁移。
操作 · 接口(管理令牌鉴权)
读取状态 · GET /api/v1/api-keys/service
启动 / 换端口 / 换监听范围 · POST /api/v1/api-keys/service/start { "port": 31800, "bindIp": "127.0.0.1" }
停止 · POST /api/v1/api-keys/service/stop
建议空闲端口 · GET /api/v1/api-keys/service/free-port
旧版兼容 · GET / PUT /api/v1/api-keys/port(fixedPort: 0 表示停止)
启动绑定失败(端口被占用等)返回 409,原监听回滚,现状不变。
API Key 管理(设置页)
打开 GET /api/v1/settings/api-keys 即可在一个页面里管理独立 API 服务与三方调用鉴权的密钥:
查看(脱敏)、新建、轮换、吊销、开启/关闭鉴权。/docs 页头部也有「管理 API Key」入口。
三个入口
入口 · 说明
DSH Web GUI 侧边栏「API 服务」 · 插件自带浏览器半边(client half),装好并重启 DSH 后出现在侧边栏,内嵌本页
GET /api/v1/settings/api-keys · 独立页面,可直接收藏
/docs 页头「管理 API Key」按钮 · 从 API 文档一键跳转
页面按管理令牌闸门设计:密钥管理与普通 API 调用是两套凭证。首次打开会要求输入管理令牌,
页面会直接给出取令牌的命令(在运行 DSH 的机器上执行):
cat <DSH 配置根>/dsh-web-service/admin-token,粘贴一次后保存在浏览器 localStorage。
未通过闸门时,页头的「新建 API Key」等管理按钮一律收起——不会出现「点了按钮才报 401」的死胡同。
页面主题与离线可用
/docs、/docs/reference、/settings/api-keys 三个页面统一使用 HARNESS 设计令牌
(--dsw-alias-*,取值镜像 packages/client/ui-theme/src/styles/design-platform.css),
因此配色、圆角、字号与 DSH Web GUI 一致,并同时支持浅色 / 深色:
- 内嵌在 GUI 侧边栏时(同源 iframe)直接读取父页面的令牌计算值并实时跟随其明暗切换,
用户自定义主题同样生效;
- 独立打开时按系统
prefers-color-scheme,也可用?theme=light/?theme=dark强制。
Swagger UI 资产随包自托管在 vendor/swagger-ui/,由 /api/v1/docs/assets/* 提供,
不依赖任何公共 CDN,内网或离线环境同样可以打开 /docs/reference。
内嵌在 GUI 侧边栏时,页内的「SWAGGER / 查看 OpenAPI JSON / 交互式文档」等按钮会在面板内跳转
(目标页给出「← 返回」按钮)。原因:DSH Desktop 主窗口显式拒绝一切新窗口
(webContents.setWindowOpenHandler(() => ({ action: 'deny' }))),target="_blank" 在应用内是
静默失败;外部链接(GitHub / 问题反馈)仍会尝试新窗口,被拒时提示复制链接。
新建时有两种 Key 值来源,对应 POST /api-keys 的 plaintext 字段:
方式 · 行为
随机生成(默认) · 服务端生成 dsk_ + 32 字节 CSPRNG(256 位熵)
使用自定义 Key · 粘贴你已有的 Key(16-256 位可见 ASCII),用于接入既有客户端或迁移
自定义 Key 的强度由你负责,因此它连前缀都不展示(列表里标记「自定义」)——否则一个
my-secret-api-key-xxx 露出前 12 位就泄露了大半价值。服务端同样只保存哈希。
同值的有效记录会被拒绝(400);已吊销 / 已过期的值可以重新登记。
两套凭证,互不通用
用途 · 凭证 · 头部写法
调用业务接口(数据面) · API Key · Authorization: Bearer <key> 或 X-API-Key: <key>
管理密钥(管理面) · Admin Token · Authorization: Bearer <admin-token> 或 X-Admin-Token: <admin-token>
这样持有 API Key 的三方客户端无法给自己增发密钥。Admin Token 由插件首次启动时自动生成,
存放在 DSH 配置根下的 dsh-web-service/admin-token(权限 0600):
cat "${DSH_HOME:-$HOME/.dsh}/dsh-web-service/admin-token"
安全约定
- 落盘只存两项:
sha256(明文)(鉴权用)和一份可逆密文sealed(列表页「复制」用)。
sealed 是用管理令牌经 HKDF 派生的密钥做的 AES-256-GCM;因此 api-keys.json 单独泄露
(备份、截图、贴到 issue)还原不出 Key,还需要同目录下 0600 的 admin-token。
- 列表页每条 Key 都有「复制」按钮,明文通过管理令牌鉴权的接口现取现用,只写进剪贴板,
不进 DOM、不写 localStorage、不打日志。
- 加密存储上线之前创建的 Key 只有哈希,明文不可恢复 —— 点「复制」会直接引导到「轮换」生成新 Key;
管理令牌被删除重建后,旧密文的解密封装也随之失效,同样表现为「不可复制,请轮换」(不会静默给错值)。
- 管理接口默认只允许本机(回环)访问;远程管理需显式设置
adminRemoteAccess: true。
浏览器请求一律做同源校验(防 CSRF / DNS rebinding),跨源返回 `403 FORBIDDE
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:8,最后更新 2026-10-27