在 Agent Client Protocol 客户端里使用 DeepSeek Harness,例如 Zed 和…
53.4/100
综合分
61
GitHub 星标
2,774
npm 周下载
—/5
用户评分
数据截至 2026/11/4 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @openma/deepseek-harness-acpnpm 源 · @openma/deepseek-harness-acp 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · security
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包@openma/deepseek-harness-acp @ 0.4.40
✓Node 引擎要求 >=22.15 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/2 17:39:54
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 82 处,展示前 48 条)
- 读取本地文件dist/index.js:79
if (existsSync(join(candidate, "package.json"))) { - 读取本地文件dist/index.js:88
const installed = JSON.parse(readFileSync(join(source, "package.json"), "utf8")); - 读取本地文件dist/index.js:105
const parsed = JSON.parse(readFileSync(join(packageRoot, "vendor/runtime.json"), "utf8")); - 读取本地文件dist/index.js:117
if (!existsSync(archive)) return void 0; - 读取本地文件dist/index.js:120
if (existsSync(marker)) return target; - 写入本地文件dist/index.js:121
mkdirSync(dirname(target), { recursive: true }); - 读取本地文件dist/index.js:122
const actual = createHash("sha256").update(readFileSync(archive)).digest("hex"); - 删除本地文件递归dist/index.js:124
if (existsSync(target)) rmSync(target, { recursive: true, force: true }); - 写入本地文件dist/index.js:129
writeFileSync(join(temporary, ".dsh-acp-runtime"), `${metadata.dsh} - 写入本地文件dist/index.js:132
renameSync(temporary, target); - 删除本地文件递归dist/index.js:137
if (existsSync(temporary)) rmSync(temporary, { recursive: true, force: true }); - 写入本地文件dist/index.js:280
await mkdir(home, { recursive: true }); - 写入本地文件dist/index.js:281
await writeFile(temporary, JSON.stringify(value) + "\n", { mode: 384 }); - 写入本地文件dist/index.js:282
await rename(temporary, path); - 删除本地文件dist/index.js:284
await rm(temporary, { force: true }).catch(() => { - 执行外部命令固定命令dist/index.js:839
const result = spawnSync("npm", ["install", "-g", `${NAME}@latest`], { stdio: ["ignore", 2, 2] }); - 执行外部命令固定命令dist/bridge.js:335
execFile("open", [url], () => void 0); - 执行外部命令固定命令dist/bridge.js:339
execFile("cmd", ["/c", "start", "", url], () => void 0); - 执行外部命令固定命令dist/bridge.js:342
execFile("xdg-open", [url], () => void 0); - 发起网络请求dist/bridge.js:3623
createElicitation: (request) => conn.request("elicitation/create", request), - 发起网络请求dist/bridge.js:3898
return conn.request("session/request_permission", { - 发起网络请求dist/bridge.js:4551
create: (request, options) => conn.request( - 执行外部命令固定命令dist/server.js:331
execFile("open", [url], () => void 0); - 执行外部命令固定命令dist/server.js:335
execFile("cmd", ["/c", "start", "", url], () => void 0); - 执行外部命令固定命令dist/server.js:338
execFile("xdg-open", [url], () => void 0); - 发起网络请求dist/server.js:3619
createElicitation: (request) => conn.request("elicitation/create", request), - 发起网络请求dist/server.js:3894
return conn.request("session/request_permission", { - 发起网络请求dist/server.js:4547
create: (request, options) => conn.request( - 读取本地文件dist/plugin.js:92
const manifest = JSON.parse(readFileSync(manifestPath, "utf8")); - 执行外部命令固定命令dist/plugin.js:389
execFile("open", [url], () => void 0); - 执行外部命令固定命令dist/plugin.js:393
execFile("cmd", ["/c", "start", "", url], () => void 0); - 执行外部命令固定命令dist/plugin.js:396
execFile("xdg-open", [url], () => void 0); - 发起网络请求dist/plugin.js:3666
createElicitation: (request) => conn.request("elicitation/create", request), - 发起网络请求dist/plugin.js:3941
return conn.request("session/request_permission", { - 发起网络请求dist/plugin.js:4594
create: (request, options) => conn.request( - 读取本地文件dist/plugin.js:4706
if (existsSync(root)) return [{ path: root, trust: "system" }]; - 读取本地文件dist/plugin.js:4713
if (existsSync(join(dirname2(manifest), "presets"))) return []; - 读取本地文件dist/bin.js:72
if (existsSync(join(candidate, "package.json"))) { - 读取本地文件dist/bin.js:81
const installed = JSON.parse(readFileSync(join(source, "package.json"), "utf8")); - 读取本地文件dist/bin.js:98
const parsed = JSON.parse(readFileSync(join(packageRoot, "vendor/runtime.json"), "utf8")); - 读取本地文件dist/bin.js:110
if (!existsSync(archive)) return void 0; - 读取本地文件dist/bin.js:113
if (existsSync(marker)) return target; - 写入本地文件dist/bin.js:114
mkdirSync(dirname(target), { recursive: true }); - 读取本地文件dist/bin.js:115
const actual = createHash("sha256").update(readFileSync(archive)).digest("hex"); - 删除本地文件递归dist/bin.js:117
if (existsSync(target)) rmSync(target, { recursive: true, force: true }); - 写入本地文件dist/bin.js:122
writeFileSync(join(temporary, ".dsh-acp-runtime"), `${metadata.dsh} - 写入本地文件dist/bin.js:125
renameSync(temporary, target); - 删除本地文件递归dist/bin.js:130
if (existsSync(temporary)) rmSync(temporary, { recursive: true, force: true });
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-timer@deepseek-ai/dsh@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-instructions@deepseek-ai/dsh-agent-loop@deepseek-ai/dsh-anonymous-user-id@deepseek-ai/dsh-attachment@deepseek-ai/dsh-bash-sandbox@deepseek-ai/dsh-brand@deepseek-ai/dsh-commands@deepseek-ai/dsh-compaction给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- ACP服务端实现
- 接入ACP客户端
DeepSeek Harness 的 ACP 服务端实现,dsh-acp
最近更新
在 GitHub 查看全部 →v0.4.402026-10-26
· 变更内容
· docs(release):通过 issue 和 release PR 发布,绝不直接推送到 main
· feat:新增可选的 RFD 子代理会话和 SDK 2 支持
· chore:将内置 dsh 升级到 0.2.1-rc.2,由 @github-actions[bot] 提交于
· fix:让 ask_user_question 的 elicitation 适配通用 ACP 表单客户端,由 @devin-ai-integration[bot] 提交于
· release:v0.4.40
· 新贡献者
· @devin-ai-integration[bot] 在以下提交中完成首次贡献
完整变更日志:
v0.4.392026-10-17
· 变更内容
· 修复:dsh 兼容性只设最低版本门槛;通过特性检测支持 dsh 0.2.1
· 修复:只在 engines.dsh 里声明 dsh 最低版本(peer 版本门槛会拒绝预发布版)
完整变更日志:
v0.4.39-beta.22026-10-17预发布
· 变更内容
· 修复:只在 engines.dsh 里声明 dsh 最低版本(peer 依赖的最低版本会拒绝预发布版)
完整变更日志:
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成deepseek-harness-acp
在 Agent Client Protocol 客户端里使用 DeepSeek Harness,例如 Zed 和 Backchat。
= 22.15" />
适配器在进程内组装 harness,把会话事件日志映射成完整的 ACP 词汇:流式文本与推理、带 diff 和显示终端的工具调用、计划、权限请求、会话模式、配置项、斜杠命令、技能和 MCP 服务器。凭据不会写进你的编辑器配置——它复用你在 dsh Web UI 里保存的密钥,或者由 dsh-acp login 把密钥存进同一个存储。
一个包,两种用法:独立运行或作为插件
| | A · dsh 配置档插件(推荐) | B · 独立服务器 |
| 适合 | 常规安装与升级 | 连接 ACP 客户端,但不想管理 dsh 配置档 |
| 安装 | dsh plugin --profile acp add @openma/deepseek-harness-acp@latest | npm i -g @openma/deepseek-harness-acp |
| Zed 运行 | dsh --profile acp | dsh-acp |
| Harness | 拥有该配置档的 dsh | 你安装的 dsh,然后是包内锁定的私有运行时 |
展开完整文档(README 剩余 1 节)
deepseek-harness-acp
在 Agent Client Protocol 客户端里使用 DeepSeek Harness,例如 Zed 和 Backchat。
= 22.15" />
适配器在进程内组装 harness,把会话事件日志映射成完整的 ACP 词汇:流式文本与推理、带 diff 和显示终端的工具调用、计划、权限请求、会话模式、配置项、斜杠命令、技能和 MCP 服务器。凭据不会写进你的编辑器配置——它复用你在 dsh Web UI 里保存的密钥,或者由 dsh-acp login 把密钥存进同一个存储。
一个包,两种用法:独立运行或作为插件
| | A · dsh 配置档插件(推荐) | B · 独立服务器 |
| 适合 | 常规安装与升级 | 连接 ACP 客户端,但不想管理 dsh 配置档 |
| 安装 | dsh plugin --profile acp add @openma/deepseek-harness-acp@latest | npm i -g @openma/deepseek-harness-acp |
| Zed 运行 | dsh --profile acp | dsh-acp |
| Harness | 拥有该配置档的 dsh | 你安装的 dsh,然后是包内锁定的私有运行时 |
| 组合方式 | dsh-base + 本 bundle + 配置档自带的补丁 | dsh-base + 本 bundle(配置档机制在进程内启动) |
两种形态共用 $DSH_HOME:同一份凭据存储、设置、预设和会话日志,与 dsh web 一致——在 Web UI 里开始的对话,可以在编辑器里列出并加载。
dsh 的其他界面可以把与传输无关的 @openma/deepseek-harness-acp/plugin 挂到自己的 Base Host 树上,自行接管传输适配器。TUI 配置档就走这条路:它启动单独的 TUI Client 进程,通过该进程的标准 stdin/stdout 连接 ACP;它
不启动 dsh-acp,也不使用进程内 Client 流。
因此这个包不只是命令行封装。它还是其他 dsh 应用使用的 ACP 界面插件:同一份 Host 组合,可以按界面选定的传输方式,对外暴露相同的会话、工具、预设、技能和持久化。
DSH 兼容性
本版本支持 @deepseek-ai/dsh >=0.1.7-rc.2 —— 这是 engines.dsh 中声明的最低版本下限(dsh 自己的插件加载器会检查该字段,且包含预发布版),绝不是精确版本列表。它刻意不作为 @deepseek-ai/dsh 的 peer 依赖:npm 和 pnpm 匹配 peer 范围时不包含预发布版,所以 peer 下限会拒绝所有 dsh 预发布版。更新的 dsh 总会尝试加载:dsh 各代之间的 API 差异在使用处做特性检测(例如 dsh 0.2.1 的 subagents.drainDescendants 对比 0.2.0 的 drainContinuableDescendants),比最新测试版本(0.2.1-rc.2)更新的 dsh 只记录一条警告。只有低于下限的 dsh 会被拒绝。CI 会跑测试过的配置档矩阵(runtime/compatibility.json)以及 next dist-tag。内置运行时是 DSH 0.2.0-rc.2,包含上游的跨进程会话写锁。
运行时选择只有两条规则(Martty issue #157):
- 独立模式(dsh-acp bin):始终使用打包的运行时 —— 绝不查询调用目录、PATH 或全局 npm 中的环境安装。显式指定 --dsh-path/DSH_PATH/DSH_ACP_HOST(或字面值 bundled)会改为选择某个安装,若该安装超出支持范围,则拒绝并给出消息,说明发现的版本、来源和支持范围。
- 插件模式(dsh plugin add,Martty 作为 dsh 插件启动):宿主 dsh 就是运行时,挂载时按同一范围检查;宿主超出范围会以同样的拒绝消息失败。
解析出的运行时总会报告:启动器把 harness host: @deepseek-ai/dsh <version> via 记录到 stderr,initialize 响应携带 agentCapabilities._meta.dsh.runtime({base, version, source})供客户端显示。
竞争的加载/恢复会返回标准 JSON-RPC 错误。关闭会话或退出所属进程后,其他进程才能恢复该会话。每个写入共享会话的进程都必须使用固定后端;旧宿主不参与此锁。
恢复历史会话使用宿主的 V3 迁移,会保留原始日志。升级后的会话无法被旧宿主读取。多根工作区通过内置的多根插件支持(见 Features 下的 Sessions)。
A · dsh 配置档插件(推荐)
npm install -g @deepseek-ai/dsh
dsh web # save your API key once
dsh plugin --profile acp add @openma/deepseek-harness-acp@latest
// Zed settings.json
{
"agent_servers": {json
"DeepSeek Harness": { "command": "dsh", "args": ["--profile", "acp"] }
}
}
插件命令会创建 $DSH_HOME/profiles/acp,安装或升级适配器,并注册它的 dsh.bundle 补丁。桥接层挂载在 @deepseek-ai/dsh-base 之上——与 dsh web 相同的产品基线,只是关掉了模块重载监听器。你可以像扩展其他 dsh 配置档一样,在 $DSH_HOME/profiles/acp/cordis.patch.yml 里扩展这个配置档。走这条路径不需要全局安装 dsh-acp。
B · 独立服务器 bash
npm install -g @openma/deepseek-harness-acp
dsh-acp login # interactive; or save the key in the dsh Web UI
jsonc
// Zed settings.json
{
"agent_servers": {
"DeepSeek Harness": { "command": "dsh-acp" }
}
}
独立二进制默认使用打包在本包内的运行时,除非你通过 --dsh-path / DSH_PATH / DSH_ACP_HOST 显式指定某个 harness。DSH 以 engines.dsh 下限的形式声明(见 DSH 兼容性),从不作为 npm 安装的依赖:插件模式使用 Host 的依赖树,独立模式则把同样的导入映射到私有运行时。如果真实的 $DSH_HOME/profiles/acp 存在,就由该配置档负责组合。
插件与扩展模型
扩展 ACP 支撑的界面有两条互不依赖的路径。
想通过 ACP 客户端使用可移植的 Agent Plugins、Codex 插件、Claude Code 插件或 Pi 包,就把 Agent Plugins Bridge 加到同一个配置档: sh
dsh plugin --profile acp add @openma/dsh-agents-plugins-bridge@latest
Bridge 贡献的是普通的 Host 行。因此,导入的命令、技能、工具、钩子、MCP 连接、智能体和 Pi 扩展,都经由本适配器已有的投影到达 ACP;不存在 ACP 专用的插件导入运行时。Bridge 的 Web 管理面板和 MCP Apps HTML 渲染器仍属于 Web 界面,不会通过 ACP 发送。
如果扩展需要会话自有的后台生命周期,又不想开终端 UI,就用 Martty owner。它是通用的 ACP rpc 客户端:本包仍是服务器/传输层,Martty 负责长期存活的会话,以及显式的启动/关闭斜杠命令。
扩展 Host 组合
ACP 适配器跑在配置档已有的 Cordis 树上。要改变智能体组合,就往该配置档里加 dsh 插件,而不是分叉 ACP 服务器:服务商和模型加入实时目录,命令和技能加入对外公布的会话界面,工具和子代理通过标准的 session/update 出现,同一套会话持久化对所有界面都仍然可用。
对于嵌入 ACP 的应用,公开的包入口如下:
| 导出 | 作用 |
| @openma/deepseek-harness-acp/plugin | 完整的 Host 侧 surface 插件。它补齐 ACP 要求的 Host 服务,这些服务 Base 留给 surface 提供,同时提供 ctx.acpServer。它不占用传输层。 |
| @openma/deepseek-harness-acp/server | 更底层的 acpServer 服务商,与传输无关,面向已经提供注入式组合服务的 Host 树。 |
| @openma/deepseek-harness-acp/stdio | 标准配置档适配器:把 ctx.acpServer 接到进程的 stdin/stdout。 |
| @openma/deepseek-harness-acp/bridge | Node 流适配器,也是旧配置档补丁的兼容入口。 |
ctx.acpServer.connect(stream) 在现有 Host 组合之上创建一个连接自有的 bridge fiber。传输层持有者保留进程、流和 TTY 的生命周期;ACP 插件保留会话和智能体语义。这正是 @openma/deepseek-harness-tui 采用的形态:ACP 留在 Base Host 树上,而独立的 TUI Client 进程持有自己的 Cordis 树。
新增 Cordis 服务不会自动凭空造出一个线上方法。只要标准 ACP 能力或事件投影存在,就优先用它;只有必须跨客户端边界的行为,才加适配器。
扩展 ACP 而不破坏普通客户端
可选的线上行为遵循 ACP 的扩展约定:
1. 在 initialize 元数据里声明支持,能力名带命名空间和版本,例如 _meta.dsh.cordis.protocol。
2. 不需要新请求时,把注解放在标准消息的命名空间 _meta 字段里。
3. 自定义 JSON-RPC 请求和通知以下划线开头命名,并且只在双方协商出匹配能力之后才发送。
4. 保持标准 ACP 路径完整。没有声明扩展的客户端,仍然要能拿到正常的会话、提示词、更新、取消、认证和配置选项。
DSH 工具结果值
[ACP 元数据注册表][metadata-registry] 是本适配器读取或发出的每个 _meta 字段的权威清单。它记录方向、载体、形状、协商要求和重放行为,包括位于 _meta.dsh.toolResult.value 的原生 DSH 工具值。
[metadata-registry]: https://github.com/openma-ai/deepseek-harness-acp/blob/main/docs/metadata.md
当前包把这一模式用在内置的 _dsh/cordis/ 家族上,TUI 用它做 Client 能力发现、动态 Package 生命周期,以及包私有的 Host/Client RPC。这是一套显式、带版本的扩展,而不是跨进程同步 Cordis 插件 id、fiber 或 inject。bridge 内部的方法注册表目前不是公开的任意扩展 API;新的扩展家族应先定义稳定的能力、归属、生命周期和回退契约。
认证
编辑器配置里不放密钥,聊天里不粘贴机密。ACP 客户端遵循协议:initialize 会声明客户端表示可用的 Agent Auth 方法。
1. API key — api-key,或按实时路由使用 api-key:<provider>。客户端可以传入 _meta["api-key"].apiKey。
2. Terminal — terminal-login,前提是客户端声明了 clientCapabilities.auth.terminal(或 _meta["terminal-auth"])。客户端自己运行声明的 dsh-acp login 命令——适配器从不提供命令路径——保存的密钥会在下一次 authenticate 或 session/new 时被读取。
3. Browser — browser,仅当客户端声明 clientCapabilities.elicitation.url 时可用。适配器启动一个 localhost 登录页,并通过 url elicitation 把 URL 交给客户端——headless、SSH 和 WSL 会话都能看到这个 URL。密钥从不经 ACP 传输;等待时间受页面自身的超时限制,拒绝或取消会以 auth_required 结束流程,而不是一直挂起。
4. Custom gateway — gateway,仅当客户端用 clientCapabilities.auth._meta.gateway === true 主动启用时可用。客户端发送 _meta.gateway { baseUrl, headers, providerName? }。
适配器把凭据写入 harness 存储。凭据缺失会让 session/new 和 session/prompt 失败,返回 auth_required(-32000),并携带 data.authMethods——即同一份声明列表——这样客户端可以从任何失败处打开自己的认证 UI。输入原生认证命令(/login、/logout)会得到一句「isn't available in this environment」的回复,指向客户端的登录/登出,并结束本轮——它从不被声明,从不到达模型,从不更改凭据,也从不返回 auth_required。
logout 的作用域是单个服务商路由——由 _meta.provider 指定,省略时用当前服务商——只清除该服务商存储的密钥和 gateway base-URL。重新认证会覆盖同一服务商的凭据;认证第二个服务商会与第一个并存;dsh-acp login --provider <route> 会在带外替换它。当前方法、服务商和凭据名称一旦变化,就会以 _auth/status_update 推送给客户端。
1. Harness credential store — $DSH_HOME/.credentials.yaml(权限 600),dsh Web UI 写入的文件;支持热重载。用 dsh-acp login [--provider <route>] 或 Web UI(Settings → Models)保存密钥。
2. Process environment — 启动智能体的环境中的 DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL(以及对应路由的 ANTHROPIC_API_KEY / OPENAI_API_KEY)。
凭据校验针对的是当前服务商路由。只有 Anthropic 的存储足以支撑 Anthropic 会话;DeepSeek 密钥无法解锁其他服务商。
Features
- Streaming — 助手文本与推理增量;组装消息回退。
- 图片 — 当组合挂载 ctx.attachments 时(dsh-base 会挂载),就会声明 promptCapabilities.image。ACP 的 image 块会经过校验,用 saveImage 存储,并与周围的文本保持原有的传输顺序。resource_link 仍然是文本形式的文件指针。
- 工具调用 — ACP 类型、人类可读标题、文件位置、来自 fs-tool hunk 的真实补丁、原始输入/输出;客户端支持时,命令输出显示在显示终端上,否则以围栏代码块输出。
- 权限预设作为会话模式 — read-only / workspace-write / danger-full-access,每个都是命名的 {sandbox, approval} 对,记录为持久的会话事实(也作为配置选项暴露给只渲染这些选项的客户端)。
- 智能体组合 — 当配置档挂载 agentPresets 时,一个未分类的配置选项 id: "agent" 会列出名单(standard / code / minimal / cordis,加上用户副本)。切换会实时重建智能体,并保留历史。编写(复制/删除)仍在 Web 设置页面进行;没有 /preset 斜杠命令。
- 实时模型目录 — 来自运行中组合的服务商 × 模型(在 Web UI 中添加的第三方服务商会立即出现),以及跟随产品默认值的推理强度选择。模型选项 id 是稳定的:注册一个服务商时使用裸模型 id,有多个服务商时使用 provider::model — 绝不基于当前默认*服务商(每次切换都会重写它),因此客户端缓存的 id 仍然有效。输入时仍接受裸 id,并解析到提供它们的服务商。
- 斜杠命令 — 适配器内置命令(/status、/model)加上 harness 命令注册表(/compact、/goal、/permission、/plan 等),执行时不消耗模型轮次,再加上技能(/skill-name — harness 自己的调用手势)。登录和登出是 ACP 方法,不是聊天命令。
- 计划与用量 — todo_write 快照作为 ACP 计划;token 统计作为 usage_update 和每轮用量。
- 会话 — session/resume 恢复持久会话,不重放会话记录;session/load 仍是完整历史路径。还支持 session/list、客户端在智能体重启后提示旧会话时静默恢复,以及以 session_info_update 形式提供标题。多根会话通过内置多根插件支持:initialize 声明 sessionCapabilities.additionalDirectories: {},session/new、session/load、session/resume 和 session/fork 接受绝对目录路径(cwd 仍是相对路径的基准)。附加根在每种模式下都可读,在 workspace-write 下可写(read-only 下不可写);session/new 省略输入或传空输入,走的正是单根路径。该列表以会话插件记录的形式持久化:客户端省略 additionalDirectories 时,load/resume/fork 会恢复它;请求非空则替换它。插件用树内薄子类替换核心 fs-sandbox/sandbox 行,并放宽 bwrap/Landlock/Seatbelt 配置档;无法放宽的配置档形状会失败关闭,而不是静默丢弃根。残余限制:Windows ACL 后端无法放宽其单一的 workspace 授权(那里不支持附加根写入,读取仍可用),Windows UNC/设备路径会被拒绝,放宽能力与 @deepseek-ai/dsh-sandbox-local 发出的配置档形状耦合。
- Fork — initialize 声明 sessionCapabilities.fork: {} 和 agentCapabilities._meta.jetbrains.air.fork = { version: 1, inclusive: true }(与 dsh.cordis 深度合并)。session/fork 创建新会话 id,源会话保持不变。没有 _meta.jetbrains.air.fork 时,新会话复制源会话已提交的日志。有该块时,复制保留选中的 assistant 消息及其之前的一切,丢弃之后的所有消息。messageId 是 ACP id <turn>:<step>(<id>:segment:<n> 形式的 id 也会按 <id> 匹配)。可选的 messageFingerprint(sha256: + assistant 文本的 SHA-256)和从 1 开始的 messageOccurrence 用于消歧。版本错误、指纹错误、id 缺失,或指定点不在日志中,都返回 JSON-RPC -32602 —— 适配器不会静默复制整个会话。未知会话 id 和子代理子会话也返回 -32602。只有已持久化的 assistant 消息才是 fork 点;运行中轮次的实时流会被忽略。如果选中的消息本身包含工具调用,这些调用会从复制的消息中移除(其结果存储在消息之后,保留调用会留下非法会话记录,并让 session/load 重放越过该消息)。更早消息中的工具调用和结果保留。对新会话执行 session/load 会重放到该 assistant 消息为止,不再继续;session/prompt 从那里继续。fork 响应携带与 session/new 相同的 modes 和 configOptions 形状。
- MCP 服务器 — 每个会话的 mcpServers 会挂载 @deepseek-ai/dsh-mcp-client 实例(stdio + 可流式 HTTP);工具以 mcp__<server>__<tool> 的形式加入;某个服务器出故障,也不会让会话崩溃。
- 引导注入(Steering) — initialize 响应会声明 _meta.steering.supported: true。发送 _session/steering,带上 { sessionId, prompt, _meta: { steering: { idleBehavior: "promptRequired" } } },即可注入到正在进行的回合;返回 { outcome: "injected" } 表示仍由该回合原本的 prompt 请求和输出流负责。如果该回合在注入前结束,响应为 { outcome: "promptRequired", reason: "noRunningTurn" },客户端再发送普通的 session/prompt。省略 idleBehavior 时行为相同。并发 session/prompt 的引导注入仍然支持。
- 真正的取消 — session/cancel 通过 harness 智能体中断正在进行的回合。
配置
命令行参数优先于环境变量,环境变量优先于默认值。全部可选 —— 不带任何参数时,会话遵循你的产品默认配置(settings.yaml)。
| 参数 | 环境变量 | 默认值 | 用途 |
| --dsh-path | DSH_PATH | 自动探测 | DeepSeek Harness 安装位置 |
| --provider | DSH_PROVIDER | 产品默认 | 覆盖服务商路由 |
| --model | DSH_MODEL | 产品默认 | 覆盖模型 |
| --max-tokens | DSH_MAX_TOKENS | 服务商默认 | 单次请求的输出 token 上限 |
| --permission-mode | DSH_PERMISSION_MODE | workspace-write | 初始权限预设 |
| --reasoning-effort | DSH_REASONING_EFFORT | 产品默认 | off / high / max |
| — | DEEPSEEK_API_KEY | — | API 凭据(回退到凭据存储) |
| — | DEEPSEEK_BASE_URL | DeepSeek 端点 | 覆盖 OpenAI 兼容端点 |
| — | DSH_ACP_DEBUG | 关闭 | 输出详细 stderr 诊断信息 |
子命令:dsh-acp login [api-key](省略参数时进入交互模式;输入内容不会回显)、dsh-acp update(通过 npm 自更新)。
权限与沙箱
会话以 workspace-write 启动:bash 和文件修改都限制在会话的 cwd 内(外加共享临时根目录),模型重试时请求更大权限会触发 ACP 权限请求。始终允许(本会话) 会把该会话的审批策略切换为 never。danger-full-access 会同时关闭沙箱和提示 —— 只在一次性检出目录或容器里使用。每个级别都是一个持久预设(沙箱 + 审批一起),与 Web UI 提供的三个级别相同。
架构
ACP client (Zed, …)
│ ACP JSON-RPC over stdio
▼
dsh-acp
├─ src/bin.ts selects one DSH tree before Host imports evaluate
├─ src/profile-boot.ts boots the harness's own profile machinery
│ (dsh-base + this bundle + $DSH_HOME layers)
├─ src/harness.ts host discovery (DSH_PATH → cwd → PATH → npm -g → bundled runtime)
└─ src/bridge/ the ACP bridge (a cordis plugin)
├─ index.ts 会话、提示词、取消、模式、选项、 │ 命令、凭据、MCP 挂载 ├─ translate.ts 会话事件 → ACP 更新投影(纯函数) ├─ history.ts 为 session/load 重放已存日志(纯函数) ├─ fork.ts session/fork 元信息、消息查找、含端点截断(纯函数) └─ prompt.ts ACP 提示词块 → harness 内容块(纯函数) ▼ 外部或随包分发的 dsh (智能体主干、llm、持久化、沙箱、工具、预设、技能、压缩……)
被其他界面嵌入时,只有传输边界会变:
dsh Base Host Cordis tree
├─ product plugins (agents, tools, skills, persistence, …)
└─ @openma/deepseek-harness-acp/plugin
└─ acpServer.connect(Stream)
│ standard ACP + negotiated extensions
▼
surface-owned Client process
桥接层消费 harness 的 session/event 事件流——持久化存储写入的也是同一份只追加日志——所以实时流式输出、历史重放和 session/list 天然一致。所有 harness 模块(包括 cordis 本身)都从同一棵宿主树加载:插件与服务标识绝不会分散到多份副本里。
开发
npm install # dev deps include the harness packages (types + tests)
npm run typecheck # tsc --noEmit
npm test # vitest: unit + e2e smoke (boots the real composition; no model calls)
npm run build # esbuild → dist/
想额外对独立安装的宿主跑 e2e 套件:
npm install --prefix /tmp/dsh-host @deepseek-ai/dsh
DSH_ACP_TEST_HOST=/tmp/dsh-host npm test
实时迭代:成对配置档
让编辑器用的配置档继续指向已发布包,再用 pnpm 软链接把第二个配置档指到这个工作树:
dsh plugin --profile acp add -w @openma/deepseek-harness-acp # stable
dsh plugin --profile acp-test add -w "link:$PWD" # dev (symlink)
开发循环就是 npm run build 加重启——dist/ 和 cordis.patch.yml 都通过软链接读取。(pnpm 会把 file: 当成复制安装,还会缓存同版本 tarball;link: 两者都能避开。)
{
"agent_servers": {
"DeepSeek Harness": { "command": "dsh", "args": ["--profile", "acp"] },
"DeepSeek Harness (dev)": { "command": "dsh", "args": ["--profile", "acp-test"] }
}
}
自动化兼容性审查
.github/workflows/dsh-update.yml 开出新的 bundled-dsh 升级 PR 时,会自动派一个 Cursor 云端智能体,审查 ACP 与新 dsh 版本的兼容性。这个智能体会:
- 阅读 dsh 各版本之间的发布说明与 API 变更
- 用新 dsh 版本测试 ACP 适配器
- 需要时直接把修复推到 PR 分支
- 在 PR 上留一条结论评论(可安全合并 / 修复后可安全合并 / 不安全)这需要 CURSOR_API_KEY 组织或仓库密钥(从 Cursor Dashboard 获取的 Cursor API key)。如果没有配置这个密钥,工作流会跳过智能体派发并给出警告,同时让 PR 保持打开状态,等待人工审查。
智能体使用 Cursor Cloud Agents API v1,并设置 workOnCurrentBranch: true,直接推送到 PR 的 head 分支,不新建分支或 PR。
要在已有 PR 上手动测试审查工作流,请通过 Actions → Update bundled dsh → Run workflow 触发工作流,并提供 PR 编号。派发逻辑位于 scripts/dispatch-cursor-review.sh。
License
Apache-2.0.预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
openma-ai/deepseek-harness-acp
在 Agent Client Protocol 客户端里使用 DeepSeek Harness,例如 Zed 和…
相关插件 · 安全 / 权限
智能体逆向工程morluto/rea
用智能体逆向工程任何东西,从应用行为到原生二进制。
★ 422,036已汉化DSH
73.3
智能体集群框架ruvnet/ruflo
面向 Claude Code 与 Codex 的智能体元基座meta-harness。
★ 80,619已汉化MCP
71.8
WorkBuddy 模型接入corrinehu/dsh-workbuddy-connect
2026 年 10 月 20 日起,WorkBuddy…
★ 1,604已汉化DSH
71.7
主动编码智能体deepseek-ai/dsh-superagent-prototype
研究原型,仅供参考,不是 DeepSeek 官方产品。…
★ 15,535已汉化DSH
71.6
破甲一键通z91772524-ai/pojia-next
十五个 AI…
★ 1,004已汉化DSH
71.6
Agent 操作层agentic-os-org/ANOLISA
ANOLISA(Agentic Nexus Operating Layer & Interface System Architecture)|智能体操作系统,带运行时、安全、可观测性,以及 Tokenless 响应压缩,降低 token 用量与成本。
★ 653已汉化DSH
70.7
这是你的仓库?认领条目