kezboardpj/dsh-btw1

dsh-btw

Ask a quick side question without interrupting the main conversation - a Claude Code /btw port for DeepSeek Harness (dsh). Type /btw <question> while the agent is working.

包名
dsh-btw
版本
0.1.0
许可证
MIT
最近更新
2026年8月21日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:kezboardpj/dsh-btw

dsh-btw

在智能体干活的时候,用 /btw 快速问个小问题,完全不打断主线任务。

Claude Code /btw 的 dsh 移植版。子代理只能看(继承主对话上下文)、不能用任何工具,单轮回答;你的问题永远不落盘,子代理记录只显示「提问 + 回答」。

安装(给其他用户)

要求:dsh ≥ 0.1.1-rc.2(装了 web UI 的常规安装即可)。

任选一种:

# 方式 A:git 安装(推荐,走 GitHub)
dsh plugin --profile web add https://github.com/kezboardpj/dsh-btw

# 方式 B:本地克隆后链接安装
git clone https://github.com/kezboardpj/dsh-btw
dsh plugin --profile web add /path/to/dsh-btw

# 方式 C:发布到 npm 后按名安装
dsh plugin --profile web add dsh-btw

profile 名按你的实际配置替换(web / tui / 自定义)。 安装后重启 dsh(插件不支持热加载)。

用法

在 web 对话输入框输入:

/btw 刚才那个 config 文件叫什么名字?
  • 主智能体继续干活,旁路用一个一次性 fork 出来的子代理回答
  • 子代理只能看(继承对话历史),不能动任何工具(显式提示"无工具、禁止输出工具调用语法")
  • 单轮回答;卡片展开内容 = 提问 + 清洗后的回答(不显示思维链;幻觉的 tool 调用标记会被截掉;纯工具类问题给兜底说明)
  • 你的问题永远不落盘recordInput:false
  • 旁路子会话以一次性子代理记录保留:子代理面板只读查看完整执行记录,不能继续对话(与 CC「能看到、不能继续」一致)
  • /btw 不带问题 = 显示上一轮旁路问答
  • 旁路线程在进程内存里保留最近 20 条问答,回放给后续的 /btw

与 Claude Code 的差异(已知取舍)

维度Claude Codedsh-btw(本插件)
启动前提需要已完成第一轮对话("Cannot fork before the first conversation turn")——子会话空种子 + 历史走运行时上下文注入,第一轮就能 /btw(比 CC 更早可用)
进行中 turn 的事件能看到"除正在写的回复外的一切"能看到(派生历史含已提交事件,正在流式写的不含)
问题落盘不落盘(内存线程)不落盘(recordInput:false,已验证)
答案显示浮层(Esc/←/x/f)命令卡片(在对话里可见)
子代理记录视图无(fork 不可见,除非 f 转正)一次性子代理记录:只显示提问+回答(历史不进子会话日志)
答案持久化内存线程,退出即没command/done 事件落盘 + 子会话以一次性子代理记录保留(面板只读可看)
线程上下文回放最新 20 条已实现(host 内存)

为什么不删子会话文件(不要改回):dsh 的投影缓存(session_projcache.json)没有删除 API,dispose 时强制写入「live-to-cold」检查点;若删掉子会话文件,缓存行变孤儿 → 子代理面板列表永久卡在「正在加载子代理」。实测踩过并已修复。子会话文件很小,保留是系统一致性正确选择。

为什么不做浮层:dsh 的 client remote/Typert 命名空间是编译器生成的静态结构,第三方插件没有通用的 client↔host 通道(remote.$on 也不存在);要做出 CC 的零落盘浮层需要在 web 客户端自建传输层,超出当前 host 插件的扩展面,列为后续研究。

工作原理(实现要点)

/btw 
  → ctx.commands(不经模型)
  → seedDescriptorTurn(childId, undefined, descriptor) —— 子会话【空种子】,
    只放 subagent/descriptor 身份事件(mode: one-shot,缺它面板报"会话已损坏")
  → ctx.agents.create:一次性子代理
      - childSessionMeta(parent, depth, 0) 继承 cwd/预设/lineage
      - resolveChildAgentOptions(parent) 继承 provider/model
      - applyChildComposition(childCtx, parent, { toolFilter: { allow: [] } })
        → join 父 preset + 滤空全部工具("只能看")
      - systemPrompt.context(btw:parent-history, order 125)
        → 主对话的派生历史(deriveMessages 序列化)作为运行时上下文注入,
          模型可见但【不进子会话日志】→ 记录视图只显示提问+回答
      - systemPrompt.context(btw:no-tools, order 130)
        → 显式"无工具、禁止输出工具调用语法"
  → handle.agent.followup(createUserMessage(...))  单轮唤醒
  → 监听子会话 turn/end:
      - 回答 = 最终 assistant 文本,截掉 / 幻觉标记;
        全为标记则为空 → 兜底说明
      - 卡片输出格式:**提问** + **回答**(用户明确要求不显示思维链)
  → 收尾:handle.dispose()(停循环/退注册/出 store)
    - 子会话文件 + 投影缓存行保持一致地保留(不得删除,否则面板挂起)

开发者(本地迭代)

scratch/dev-patch.yml:用隔离 DSH_HOME + dsh --profile web --patch dev-patch.yml --port 3091 --no-open 跑, 不碰正式服务。lib/index.js 在开发期靠 dsh-btw/node_modules(junction 到本机 dsh 依赖)解析 @deepseek-ai/*;正式安装由 npm/git 正常装依赖,无需 junction。

验证记录(2026-08-21,DeepSeek-V4-Flash-Vision-Exp / pi-ai)

  • ✅ 全程不打断主任务:主 agent 运行中发 /btw,UI 同时显示主任务进行中 + 子代理并发,主任务正常收尾
  • ✅ 子代理单轮、零工具、能只看主对话上下文正确回答
  • ✅ 问题文本未落盘(recordInput:false)
  • ✅ 首轮即可 /btw(空种子 + 上下文注入,比 CC 更早可用)
  • ✅ 子代理单轮、零工具、正确引用历史回答
  • ✅ 子会话文件与投影缓存保持一致(子代理面板可正常加载一次性记录)
  • ✅ 问题文本未落盘