shenkonghui/dsh-llm-acp
DeepSeek Harness 的 ACP 客户端 LLM 适配器 + ACP 服务设置界面。通过外部 [Agent Client Protocol](https://agentclientprotocol.com) 服务器作为模型提供方接入 harness 的 LLM 层,并提供一个 Web 设置页面用于浏览 ACP 注册表和管理已配置的服务器。
Project Overview项目介绍
dsh-llm-acp is a dual-sided DeepSeek Harness plugin. The host side is an LLM adapter that launches long-lived ACP server processes via stdin/stdout and registers each as a provider route at acp-<server-id>, streaming agent_message_chunk updates to harness. The client side renders a web settings page for browsing the ACP registry and managing configured servers, including env vars and model selection. Use it to wire ACP agents like Claude, Codex, or OpenCode into harness as model providers. Caveat: harness tools are ignored, ACP servers handle their own tool execution, and no token usage is emitted.
dsh-llm-acp 是 DeepSeek Harness 的双面插件,作为 ACP 客户端 LLM 适配器,通过外部 Agent Client Protocol 服务器接入 harness 的 LLM 层,并为每个已配置服务器注册 acp-<server-id> provider 路由;客户端则提供 Web 设置页面,可浏览 ACP 注册表并管理 ACP 服务。适用于需要将 Claude、Codex、OpenCode 等 ACP agent 作为模型提供方接入 harness 的场景。注意:ACP 服务器自行执行工具,harness 的 tools 会被忽略,且无 token 用量统计。
请帮我了解并安装插件:【dsh-llm-acp】【https://github.com/shenkonghui/dsh-llm-acp】
Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。
Or use CLI install (for developers)或使用命令行安装(适合开发者)
CLI Install命令行安装
dsh plugin --profile my-acp add github:shenkonghui/dsh-llm-acp
把 shenkonghui/dsh-llm-acp 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
@deepseek-ai/dsh-llm-acp
中文 | English
DeepSeek Harness 的 ACP 客户端 LLM 适配器 + ACP 服务设置界面。通过外部 Agent Client Protocol 服务器作为模型提供方接入 harness 的 LLM 层,并提供一个 Web 设置页面用于浏览 ACP 注册表和管理已配置的服务器。
本包是一个双面 dsh 插件:宿主端(lib/index.js)是传输适配器,在 ctx.llm 上注册 provider 路由;客户端(lib/client.js)是浏览器设置页面,让用户从 Web UI 浏览 ACP 注册表并添加/删除 ACP agent 服务器。
界面
ACP注册表添加acp-server
支持acp registry上的所有acp-server[https://agentclientprotocol.com/get-started/registry]
如claude,codex,opencode等

ACP服务管理

使用acp-server进行交互

安装
dsh plugin --profile my-acp add github:shenkonghui/dsh-llm-acp
或从本地目录安装:
dsh plugin --profile my-acp add ./dsh-llm-acp
构建产物(lib/)已提交到仓库,安装时无需运行任何构建脚本。
卸载
dsh plugin --profile my-acp remove @deepseek-ai/dsh-llm-acp
这会从 profile 中移除依赖和 bundle 层。
配置
安装后,在 Web UI 中打开 设置 → ACP 服务。浏览 ACP 注册表,在任意 agent(如 Devin、Codex、Claude Agent)上点击 添加,即可将其配置为 ACP 服务器。每个已配置的服务器会创建一个独立的 provider 路由 acp-<server-id>。
在 我的服务 标签页中,点击任意已配置服务器上的 编辑 按钮,可以:
- 设置环境变量用于认证(如
DEEPSEEK_API_KEY、OPENAI_API_KEY)。每个服务器的环境变量会与插件级env合并,服务级优先。 - 选择要启用的模型。从服务器发现的模型目录中多选要暴露的模型,不选则启用全部已发现的模型。
ACP server 不单独保存权限策略。它复用会话输入框中的权限列表:read-only 和 workspace-write 将敏感操作转发到 harness 审批界面,danger-full-access 自动允许。
也可以直接在 settings.yaml 中配置:
llm-acp:
servers:
devin:
command: devin
args:
- acp
name: Devin
env:
DEEPSEEK_API_KEY: sk-xxx
models:
- deepseek-chat
- deepseek-reasoner
工作原理
整体流程
1. 插件加载阶段(apply(),src/index.ts)
dsh harness 启动
└─ apply(ctx, config)
├─ 读取 llm-acp 设置命名空间 + 内联 config.servers,合并成服务器列表
├─ 对每个服务器 createServer():
│ ├─ resolveNpxShortcut():npx -y <pkg> 若 bin 已在 PATH 则直接用 bin
│ ├─ new AcpConnection():spawn 长生命周期子进程(stdin/stdout JSON-RPC)
│ │ └─ initialize() 握手 → 仅配置了 API key 时才 authenticate()
│ │ (无 key 直接走 env/缓存登录;session/new 失败才惰性补一次 authenticate)
│ ├─ new AcpAdapter():构造时 discoverModels() 探测模型目录
│ └─ ctx.llm.registerAdapter(['acp-<server-id>'], adapter)
└─ reconcileDirectory():向设置页注册可配置 provider 目录
2. 模型调用阶段(每次 stream(),src/adapter.ts)
harness 请求模型
└─ AcpAdapter.stream(options)
├─ await connection.ready(等 ACP initialize 完成)
├─ Session 决策:
│ ├─ agent 支持 loadSession 且有 dsh sessionId
│ │ → session/load 复用,只发增量用户消息(renderPromptDelta)
│ │ 失败/历史变短(compaction)→ 降级新建
│ └─ 否则 session/new 新建,全量历史渲染成一条文本块(renderPrompt)
├─ setSessionModel():best-effort 设置所选模型
├─ session/prompt 流式循环:
│ ├─ agent_message_chunk → text-delta chunk
│ ├─ agent_thought_chunk → reasoning-delta(emitReasoning 开启时)
│ ├─ 扩展进度通知 → reasoning-delta
│ └─ stopReason 终态 → finish chunk(end_turn→stop 等)
└─ 收尾:复用 session 记入 sessionMap 供下轮复用;一次性 session 关闭
权限请求(session/request_permission)按当前会话的权限预设路由:danger-full-access 自动 allow,否则弹 harness 的 approval UI。
3. 设置界面阶段(浏览器端,src/client/)
Web UI「设置 → ACP 服务」
├─ 浏览内置 ACP 注册表(registry.json)→ 点「添加」写入 llm-acp.servers
├─ 宿主端监听 settings 变更 → reconcileServers() 增删/重建连接(指纹比对)
├─ 模型发现:registerModelDiscovery 路由 acp-<id> → 临时 session/new 读 configOptions
├─ acp-info-<id>:只读 initialize 身份(agent 名/版本),不建 session
└─ acp-resolve-<bin>:探测 PATH,把 npx 形式改存本地 bin 路径
核心设计:每个 ACP 服务器 = 一个常驻子进程 = 一个 provider 路由 acp-<id>;工具由 ACP 服务器内部自己执行,适配器只透传文本/推理流,不接 harness 工具生态。
宿主端 — LLM 适配器
apply(ctx, config) 从 llm-acp 设置命名空间读取已配置的服务器列表。对每个服务器,启动一个长生命周期的子进程,通过 stdin/stdout 建立 ACP ClientSideConnection,并在 ctx.llm 上注册路由为 acp-<server-id> 的 AcpAdapter。每次模型调用会创建新的 ACP session,将完整对话作为一条用户消息发送,并将流式 agent_message_chunk 更新转换为 harness 的 StreamChunk。
客户端 — 设置界面
浏览器端注册一个 settings.section slot,渲染 ACP 注册表浏览器和"我的服务"列表。添加服务器时会将其持久化到 llm-acp 设置命名空间;宿主端监听变更并同步更新 provider 目录。
注册表命令推导
ACP 注册表指定了不同的分发类型:
| 类型 | 命令 |
|---|---|
npx |
npx -y <package> ...args |
uvx |
uvx <package> ...args |
binary |
取注册表 cmd 的 basename(如 ./bin/devin → devin) |
binary 类型使用可执行文件的 basename,这样已安装到 PATH 的二进制文件可以直接找到,避免 spawn ./bin/devin ENOENT 错误。
配置项
| 配置 | 默认值 | 说明 |
|---|---|---|
emitReasoning |
true |
是否将 agent_thought_chunk 和扩展进度通知转换为 reasoning-delta chunk。 |
defaultModelId |
devin |
ACP 发现未返回模型时的回退模型 ID。 |
defaultModelName |
Devin (ACP) |
回退模型显示名称。 |
disposeEofGraceMs |
6000 |
stdin EOF 后等待平台终止的宽限时间(毫秒)。 |
disposeGraceMs |
3000 |
SIGTERM 后等待 SIGKILL 的 POSIX 宽限时间(毫秒)。 |
initTimeoutMs |
120000 |
initialize 握手(含 keyed authenticate)的上限(毫秒)。 |
sessionTimeoutMs |
60000 |
session/new、session/load、session/list、session/set_config_option 的上限(毫秒)。 |
authTimeoutMs |
15000 |
单次 authenticate 调用的上限(毫秒)。 |
协议契约
每次 stream() 调用:
- 创建新的 ACP
session/new,使用配置的cwd。 - 将 harness 的
messages和systemprompt 渲染为一条 ACP 文本块。 - 发送
session/prompt,将流式agent_message_chunk更新作为text-deltachunk 传输。 - 当
emitReasoning开启时,agent_thought_chunk更新转换为reasoning-deltachunk。 session/prompt响应的终态stopReason转换为finishchunk。
工具调用增量不会被输出。ACP 服务器内部执行自己的工具。session/request_permission 复用当前会话的权限预设:danger-full-access 自动允许,其他预设通过 harness 一次性审批请求处理;审批不可用、失败或 ACP 未提供 allow_once 时拒绝执行。
停止原因映射
| ACP | Harness finish |
|---|---|
end_turn |
stop |
max_tokens |
max-tokens |
refusal |
error(code REFUSAL) |
cancelled |
aborted |
max_turn_requests / 未知 |
error |
构建
pnpm install
pnpm build # tsc -b && tsdown
构建产物已提交到仓库,用户安装时只需 pnpm install 即可。
已知限制与待办事项
- 不支持 harness 工具生态 — ACP 服务器执行自己的工具;harness 的
GenerateOptions.tools被忽略。 - 无 session 复用 — 每次
stream()调用创建新的 ACP session 并重新发送完整对话。 - 无 token 用量 — ACP v1 不提供 token 计数;适配器不输出
usagechunk。 - 系统提示在消息体内 — ACP
session/new没有 system 槽位,harness 的 system prompt 被拼接到用户消息文本前。 - 全量历史重发 — 适配器将整个
messages数组渲染为一条用户消息。 - ACP v1(SDK 0.25.1) — 适配器使用
@agentclientprotocol/sdk0.25.1,其session/prompt响应携带终态stopReason(v1 契约)。 - 扩展协议处理 — Devin 的
_cognition.ai/*通知被静默消费(进度文本在emitReasoning开启时作为 reasoning 输出);其他非标准 ACP 扩展被吞掉以避免 SDK 错误日志。 - 认证惰性化 — 未配置 API key 时不主动调用
authenticate:依赖 env 凭证或 CLI 缓存登录的 server 直接session/new成功;仅当session/new/session/load失败才执行一次有界(authTimeoutMs)的authenticate并重试。交互式浏览器登录只在确实需要时触发,URL 同时经警告日志与设置页acp-auth-<id>路由暴露。
许可证
MIT
ningbainb/deepseek-harness-desktop
ChisaAlter/Deepseek-Harness-Desktop
rison114514/dsh-endfield-ui
Links2008/DeepSeek-Harness-Desktop
XCNXNXNX/dsh-portable-tavern
WZZNNE/DSH-CyberWorkStation
dhicoc/dsh-theme-mineradio
MrMu666/dsh-LAN