@wangchenglai/dsh-acp-session
v0.1.0
Published
为 DeepSeek Harness 的 ACP 补上 session/load、session/delete,并让 session/list 带标题与更新时间
Readme
@wangchenglai/dsh-acp-session
给 DeepSeek Harness 的 ACP 补上三件事,让客户端只用标准 ACP 就能管理会话:
| 能力 | dsh 自带 | 本插件 |
|---|---|---|
| session/list 返回 title / updatedAt | ❌ 只有 id + cwd | ✅ 用 sessionPersistence 补上 |
| session/load(回放历史) | ❌ 未实现 | ✅ session/resume + 按 session/update 回放 |
| session/delete | ❌ 未实现 | ✅ 关闭会话 + 删除会话目录 |
原理
不 fork、不修改 dsh 源码,而是"套"在它外面:
浏览器 ──stdio──▶ [本插件:消息中继] ──进程内 stream──▶ @deepseek-ai/dsh-acp@deepseek-ai/dsh-acp 的配置里有 stream 字段(运行时 transport),本插件用它把
上游 ACP 接到进程内的双工通道上,自己接管真正的 stdio:
- 普通消息:原样双向转发
session/list:转发后补title/updatedAtsession/load:session/resume("already active" 视为成功)+ 回放历史 + 返回{}session/delete:session/close(忽略失败)+ 删会话目录 + 返回{}
会话数据全部通过 dsh 自己的 ctx.sessionPersistence(list / resolveCurrentLog /
readStoredLog)读取,不再自己解压 session.v4.jsonl.zstd。
安装(镜像内)
Dockerfile 里:
COPY --chown=root:root dsh-plugins/acp-session /opt/dsh-plugins/acp-session
RUN cd /opt/dsh-plugins/acp-session \
&& npm install --omit=dev --no-audit --no-fund \
&& chmod +x start-acp.shstart-acp.sh 负责:
- 把插件软链到
$DSH_HOME/profiles/acp/node_modules/@wangchenglai/dsh-acp-session(不动用户的package.json,也不需要联网跑 pnpm) exec dsh --profile acp --patch /opt/dsh-plugins/acp-session/profile-patch.yml(--patch是叠加层,用户已有的 profile 文件不受影响)
jupyter_server_config.py 里把 ACP 的启动命令改成:
'command': ['node', '/usr/local/bin/acp-to-ws', '--port', '{port}', '--',
'bash', '/opt/dsh-plugins/acp-session/start-acp.sh'],本地验证
在容器里(不需要平台后端):
# 1. 确认插件被 dsh 认出来
dsh --profile acp --patch /opt/dsh-plugins/acp-session/profile-patch.yml --dump-config \
| grep -A3 acp-session
# 2. 用 ACP 探针跑一遍
node tools/acp-probe2.js # 依次 initialize / session/new / prompt /
# session/list / session/load / session/delete已知边界
session/delete依赖resolveCurrentLog给出的路径,删除的是整个会话目录 (一个目录里只有该会话的日志)。- 回放只覆盖 user/assistant 文本、推理和工具调用的状态;工具结果目前客户端也不渲染。
session/list为了拿标题会逐个读会话日志(dsh 的持久化层有缓存), 会话数量到几百时会有可感知的延迟;真到那一步再改成只读头部。- 上游
session/resume对"已激活"的会话会报错,本插件按成功处理——这正是load想要的状态,但意味着调用方无法区分"刚恢复"和"本来就在跑"。
