UI Enhancements

dsh-btw

iyllyt/dsh-btw · ★ 11

iyllyt

A DeepSeek Harness plugin recreating the /btw command from Claude Code.

README body is shown in Chinese.

License
MIT
Added
2026-08-23
Maintenance
active
Install kind
github

No manifest check is available; listing does not imply compatibility or security review.

安装

dsh plugin --profile web add github:iyllyt/dsh-btw

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

For install and environment setup, plus plugin development tutorials, see DSH community docs ↗

README

Source README · body: zh · Read Chinese README

Table of contents
  1. /btw 是做什么的?
  2. 什么时候不该用 /btw?
  3. 功能
  4. 使用效果
  5. 实现架构
  6. 1. Client 输入拦截
  7. 2. Trusted Host RPC
  8. 3. 上下文快照
  9. 4. 一次性模型调用
  10. 5. 隐藏 sidechain
  11. 6. skipCacheWrite 等价处理
  12. 安装
  13. 环境要求
  14. 方法一:直接从 GitHub 安装
  15. 方法二:本地打包安装(本次实测方式)
  16. 卸载
  17. 配置
  18. 源码结构
  19. 开发
  20. 兼容性
  21. License

为 DeepSeek Harness 复刻的 /btw 旁路提问插件。

个人很喜欢 Claude Code 里的 /btw 指令,于是为 DeepSeek Harness(DSH)做了一个复刻插件。

/btw 用来在不打断主 Agent 的情况下快速问一个与当前上下文有关的问题。问题由独立的一次性模型请求回答,结果显示在输入框上方的临时面板中;它不会成为主对话消息,也不会写入 DSH 的普通会话目录。

本项目是非官方社区插件,与 Anthropic、Claude Code 或 DeepSeek AI 没有关联。

/btw 是做什么的?

/btw 可以理解成在主会话旁边“顺手问一句”。当 Agent 正在执行一个较长任务时,你经常会临时想确认一个细节:刚才提到的配置文件叫什么、某段已经读过的代码为什么这样写、之前决定采用哪个方案。直接发送普通消息会改变主会话的走向并增加后续上下文,而另开会话又会失去当前任务已经积累的信息。

BTW 解决的正是这个夹缝问题:它读取截至提交时父会话可安全复用的上下文,独立生成一次回答,然后把结果放进可关闭的临时面板。主 Agent 继续原来的任务,问题和回答也不会进入普通会话历史。

它的核心价值是:

  • 不打断主任务:主 Agent 正在思考或调用工具时仍可提问,BTW 在旁路独立运行。
  • 不污染主上下文:临时问题不会改变主任务方向,也不会占用后续对话历史。
  • 不用重新交代背景:它知道父会话已经讨论过的代码、结论和决策。
  • 快速确认细节:适合答案已经存在于当前上下文中的短问题。

典型用法:

/btw 刚才说的配置文件叫什么?
/btw 为什么这里选择队列而不是直接执行?
/btw 我们最终决定使用哪种缓存策略?
/btw 这个报错和刚才修改的代码有关吗?

什么时候不该用 /btw?

需求 应该选择
询问当前会话已经知道的内容,只需要一次快速回答 /btw
需要读取尚未看过的文件、执行命令或联网搜索 普通消息或 subagent
需要连续追问、共同讨论或改变实现方案 普通消息
需要真正修改文件或执行操作 普通消息或带工具的 subagent

BTW 没有工具权限,也没有后续轮次。它不是免费的本地查询,而是额外的一次模型请求;插件会尽可能复用父请求的共享 prompt/cache 前缀,以降低重复上下文的成本。

这一交互定位参考了 Claude Code 官方 /btw 文档,DSH 版本的底层实现、私有 sidechain 和缓存兼容层均为本项目独立实现。

功能

能力 行为
主任务并行 主 Agent 忙碌时也可以提交 /btw,主任务不会被暂停
共享上下文 复用父会话当前的模型配置、系统提示词、工具 schema 和安全消息前缀
一次性回答 只进行一轮模型生成,不执行工具,也不会继续追问
会话隔离 不向主 SessionStore 写入用户消息、回答或隐藏 Session
临时界面 Markdown 回答显示在 composer 上方,不遮挡输入框
隐私存档 可选择私有 JSONL、仅内存或完全不保存三种 sidechain 模式
缓存保护 Anthropic/pi-ai 路由把缓存边界移回共享前缀;其他路由交给 provider 管理
可取消 关闭面板会中止请求,并支持独立超时控制

使用效果

先在主会话发送至少一条消息,然后在输入框中输入:

/btw 这个错误最可能是什么原因?

DSH 会立即释放输入框,主 Agent 可以继续工作。BTW 回答完成后会显示在输入框正上方。

  • ↑ / ↓:滚动长回答
  • Enter / Space / Esc:关闭回答
  • 请求尚未完成时点击 Cancel:中止本次 BTW

面板关闭后,BTW 不会出现在主对话历史、会话侧栏或普通 Session log 中。

实现架构

flowchart LR
    A["Composer: /btw question"] --> B["Client InputTrigger"]
    B --> C["Session-scoped BtwController"]
    C -->|"authenticated /api/dsh-btw/ask"| D["Host BTW Service"]
    D --> E["Context Snapshot"]
    E --> F["Tool-free One-shot LLM"]
    D --> G["Private Sidechain Kernel"]
    F --> H["Composer Dock Panel"]

1. Client 输入拦截

Client 通过 DSH 的 input-trigger 管线认领 /btw。提交后不会走普通消息发送流程,因此问题不会进入主会话事件流。每个父 Session 都有独立的 BtwController,负责请求状态、取消和 UI 生命周期。

2. Trusted Host RPC

浏览器通过受信 Host RPC 把 sessionId、requestId 和问题发送给 Host。Host 只接受结构合法、仍有 live Agent 的会话请求,并把浏览器取消信号与插件超时合并。

3. 上下文快照

Host 从父 Agent 中快照:

  • 当前 provider、model、reasoning、sampling 等请求配置
  • 当前 system prompt
  • 当前 tool schemas
  • 最长的工具调用平衡消息前缀
  • 正在处理的当前用户消息(如果已经进入父 Session)

工具调用平衡算法不会留下“只有 tool call、没有 tool result”的残缺历史。

4. 一次性模型调用

BTW 使用独立的 sidechainId 发起一次生成。工具 schema 会保留,以尽量维持与父请求相同的 prompt/cache 前缀,但插件不会注册工具执行器,也不会进行第二轮模型调用。如果模型只返回工具调用,界面会显示可读的降级说明。

5. 隐藏 sidechain

BTW 不创建普通 DSH Session。可选的审计记录由插件自己的 sidechain kernel 管理:

  • private-jsonl:默认模式,写入 $DSH_HOME/btw-sidechains/v1
  • memory:只保留在当前进程内存中
  • none:完全不保存

private-jsonl 目录权限为 0700,文件权限为 0600,并按天数和最大数量自动清理。记录中包含问题、上下文快照和回答;共享机器上请根据隐私要求选择合适模式。

6. skipCacheWrite 等价处理

目标 DSH 版本没有公开的 skipCacheWrite 平台开关。本插件对 pi-ai 的 Anthropic Messages 路由使用每次请求独立的 adapter,并通过 onPayload 把一次性 BTW 尾部上的 cache_control 标记移动到最后一个共享前缀块,避免为不会复用的尾部写缓存。桥接层固定针对 0.2.1-rc.2 的内部结构,保留 auth 和附件解析钩子;不修改已注册的官方 adapter。直连路径同时复刻 0.2.1 的请求投影,避免和父请求的 prompt/cache 前缀分叉。

原生 DeepSeek 自动服务端缓存没有对应的 wire-level 关闭参数,因此保持 provider-managed,不伪造客户端能力。

安装

环境要求

  • Node.js ^22.19.0 || >=24.0.0(本次实测为 24.16.0,DSH 0.2.1 桌面运行时为 24.21.0)
  • pnpm / Corepack
  • DeepSeek Harness 0.2.1-rc.2
  • 已经可以正常启动的 desktop profile(桌面 GUI)或 web profile

0.4.0 面向 DSH 0.2.1-rc.2;0.1.5-rc.1 / 0.1.5-rc.2 已不在支持范围内。请先升级 DSH,并备份现有 Profile。兼容范围以精确版本记录为准,不代表后续版本自动兼容;完整证据及尚未验证的项目见兼容性记录。

方法一:直接从 GitHub 安装

dsh plugin --profile desktop add github:iyllyt/dsh-btw --ignore-scripts

若使用纯 Web profile,把 desktop 换成 web;web profile 可以用 dsh --profile web --dump-config 核对 id: btw。desktop profile 由 Electron 应用独占,CLI 的 --dump-config 会拒绝读取,请改为检查 profile 的 package.json 与 node_modules/dsh-btw/package.json。先备份目标 Profile,并使用已经确认版本的 DSH。若没有全局命令,可使用 npx @deepseek-ai/dsh@0.2.1-rc.2。安装后完全退出并重新启动 DSH 桌面应用,再刷新 GUI;新增 bundle 不能只依赖 patch 热更新。

仓库提交了预构建的 lib/,因此从 GitHub 安装时不需要授权执行 prepare 构建脚本。生产环境建议锁定 commit:

dsh plugin --profile desktop add github:iyllyt/dsh-btw#<commit-sha> --ignore-scripts

方法二:本地打包安装(本次实测方式)

不要直接 add ./dsh-btw 或链接开发目录:Node 可能沿链接加载仓库里的开发依赖,而宿主使用自己的 DSH 依赖图。打包安装避免了这个风险,但仍应检查实际依赖版本。

仓库已包含预构建 lib/,仅安装无需重新构建。在仓库根目录执行以下 PowerShell 命令,dsh 使用你原来的宿主:

$dshProfileHome = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
$artifactDir = Join-Path $dshProfileHome 'plugin-artifacts'
New-Item -ItemType Directory -Force -Path $artifactDir | Out-Null
npm.cmd pack --ignore-scripts --pack-destination "$artifactDir"
dsh plugin --profile desktop add "$artifactDir/dsh-btw-0.4.0.tgz" --ignore-scripts
# 完全退出并重新启动 DSH 桌面应用后生效

如果修改过源码,先执行开发验证,再按上面的步骤打包:

pnpm install --frozen-lockfile --ignore-scripts
pnpm run typecheck
pnpm run build
pnpm test

web profile 的 --dump-config 中应出现 id: btw;desktop profile 以 package.json 的 bundles 和已安装的 dsh-btw 版本为准。保留安装时引用的 tarball,以便重装;后续更新使用新版本号和新文件名。Windows 执行策略、peer 警告及认证排查见安装说明。

卸载

dsh plugin --profile desktop remove dsh-btw

卸载插件不会自动删除已经写入 $DSH_HOME/btw-sidechains/v1 的私有审计记录。

配置

bundle 自带以下默认配置:

- insert:
    - id: btw
      name: dsh-btw
      config:
        timeoutMs: 120000
        sidechain:
          mode: private-jsonl
          retentionDays: 7
          maxSessions: 500

如需覆盖默认值,在 $DSH_HOME/profiles/desktop/cordis.patch.yml(或 web profile 对应文件)中追加同一个 id: btw 的完整插件行。例如完全禁用 BTW 存档:

- insert:
    - id: btw
      name: dsh-btw
      config:
        timeoutMs: 120000
        sidechain:
          mode: none
          retentionDays: 7
          maxSessions: 500

可配置项:

字段 默认值 说明
timeoutMs 120000 Host 侧单次 BTW 超时,单位毫秒
sidechain.mode private-jsonl private-jsonl、memory 或 none
sidechain.root $DSH_HOME/btw-sidechains/v1 私有 JSONL 的自定义绝对路径
sidechain.retentionDays 7 文件保留天数
sidechain.maxSessions 500 最多保留的 sidechain 数量

DSH 的 patch 会替换同一插件行的整个 config,而不是递归合并,所以覆盖时请写出希望保留的全部配置字段。

源码结构

src/
├── client/
│   ├── input-source.ts       # /btw 命令识别与输入管线接管
│   ├── controller.ts         # 每个 Session 的异步状态与取消
│   ├── overlay.tsx           # Dock 面板、Markdown 与键盘交互
│   └── index.tsx             # Client 插件注册
├── host/
│   ├── service.ts            # 请求校验、超时与编排
│   ├── rpc-route.ts          # 官方认证载体下的插件自有 API 路径
│   ├── context-snapshot.ts   # 父会话请求头与平衡上下文快照
│   ├── one-shot.ts           # 无工具的一次性模型生成
│   ├── cache-boundary.ts     # Anthropic 缓存边界迁移
│   ├── btw-pi-ai-adapter.ts  # 0.2.1 请求级缓存 adapter
│   └── sidechain-kernel.ts   # 隐藏 JSONL / memory / none 存储
└── shared/
    └── protocol.ts           # Client/Host RPC 协议与运行时校验

Host 和 Client 是同一个 DSH bundle 的两个运行面:cordis.patch.yml 加载 Host 插件,package.json 的 dsh.client 元数据加载浏览器端插件。

开发

pnpm install
pnpm test
pnpm run typecheck
pnpm run build

当前测试覆盖上下文平衡、系统提示词历史更新、缓存边界、输入接管、官方 prepared-call 运行时、认证载体的请求信封、前端产物模块加载、sidechain 隔离以及 Controller 生命周期。前端产物测试读取 lib/client.js,修改源码后应先构建再测试。

兼容性

  • 当前版本:0.4.0
  • 目标 DSH:0.2.1-rc.2(Web 与 Desktop GUI 同一套客户端运行时)
  • Node.js:^22.19.0 || >=24.0.0
  • 已验证:类型检查、22 项自动测试、构建,以及隔离 Profile 的安装、启动、认证 RPC 和卸载。
  • 0.4.0 适配点:宿主请求带上 session.toolHistory();pi-ai 直连路径复刻 0.2.1 的 projectToolUpdates / 文件 / 图片投影;客户端补齐 MarkdownLabels.code.toolbarLabels;CommandClaim 增加 name;工具结果按 0.2.1 的 role: 'tool' 消息平衡。
  • 自动检查未覆盖:真实模型生成、浏览器完整交互、真实服务缓存行为、Node.js 22、Linux/macOS、回滚。compatible 不等于所有环境和场景均已验收。
  • pi-ai 缓存桥接会在预期的 adapter internals 改变时 fail closed;其他 provider 仍走 DSH 公共 LlmRuntime.prepareCall() 路径。
  • 本地 pnpm-workspace.yaml 固定官方 DSH 依赖图,并使用 nodeLinker: hoisted 让本仓库在 Windows junction 布局下解析全部传递依赖;该设置不影响已安装的 Profile。

完整验证过程及复现命令见兼容性记录。

License

MIT