Skip to content

功能规格说明:BTW 命令 ​

创建日期:2026-04-15 更新日期:2026-10-30

本规格同时覆盖 CLI(packages/code)与 Webview 四入口(VS Code / JetBrains / Desktop,以及手机上的远控 Web 页)。 CLI 端交互(overlay、↑/↓ 滚动、Esc 关闭)见下方用户故事一、二、三; Webview 端交互(BTW 面板、斜杠命令弹窗插入、点击/Esc 关闭、加载状态展示)见用户故事『Webview 端附带提问』。 远控 Web 页的语义与 Panel 交互与其余三端完全一致,差别只在传输(经中继到 AgentBridge 的 askBtw,白名单与流式通知的承载见 remote/remote-web.md 的「Web 页也能用 /btw 旁路提问」故事)。

用户场景与测试 (必填) ​

用户故事:提出附带问题(优先级:P1) ​

作为 CLI 用户,我希望输入 /btw <question> 来快速提出一个附带问题,以便我可以在不触发工具执行或打断主对话的情况下获得答案。

验收场景:

  1. 假设用户处于主对话模式,当用户输入 /btw <question> 并按下 Enter 时,则 附带问题绕过主消息队列并立即处理,BtwDisplay 出现并显示问题。
  2. 假设 btw 请求发出,则 请求复用主对话的 system prompt、工具列表与记忆注入(fork 请求前缀与主对话字节级一致),以命中模型 prompt 缓存(支持缓存标记的模型),并继承主对话的模型与 thinking 参数。
  3. 假设 btw 请求发出,则 请求仅执行一轮(maxTurns: 1),模型不能调用任何工具;若模型仍返回工具调用,BtwDisplay 显示 "(The model tried to call X...)" 提示,不执行工具。
  4. 假设 btw 请求的上下文包含主对话消息,则 请求只携带最近一次 compact 边界之后的完整消息,并剔除进行中(尚未结束)的 assistant 消息,保证请求前缀与主对话已完成的请求一致。
  5. 假设 AI 已响应附带问题,则 BtwDisplay 显示 Markdown 答案。
  6. 假设附带问题不会被添加到主聊天历史或用户输入历史中。

用户故事:BTW 期间的视觉反馈与交互操作(优先级:P2) ​

作为 CLI 用户,我希望在附带问题激活时有清晰的视觉指示器,并能够通过键盘快速关闭,以便我可以将其与主对话区分开来并流畅操作。

验收场景:

  1. 假设附带问题正在加载,则 BtwDisplay 显示静态 loading 指示(✻)与 "Answering" 文本,并在其后显示当前流式文本的最后 30 个字符(推理与普通文本共用同一尾部通道),直到回答完成(详见"BTW 加载状态"用户故事)。
  2. 假设附带问题正在加载或已回答,则 BtwDisplay 显示 /btw 黄色加粗前缀与 dim 色问题文本。
  3. 假设回答或错误已显示且未超出视口,则 BtwDisplay 底部显示 "Escape to dismiss" 提示;回答超出视口时该提示改为 "↑/↓ to scroll · Esc to dismiss"(见"CLI 长回答滚动"用户故事)。
  4. 假设附带问题处于活动状态,则 任务列表(TaskList)隐藏,避免与旁路问题展示争抢空间(对齐 Claude Code:local-jsx 命令显示期间抑制展开的任务列表)。
  5. 假设附带问题处于活动状态,当用户按下 ESC 时,则 BtwDisplay 关闭,用户返回主对话模式(输入框恢复,任务列表恢复显示)。
  6. 假设附带问题正在加载,当用户按下 ESC 时,则 请求被中止(abort),BtwDisplay 关闭。
  7. 假设附带问题处于活动状态,当用户按下 Enter/Space/Ctrl+C/Ctrl+D 或其他键时,则 按键被忽略(overlay 期间仅 ESC 有效,Ctrl+C 不会退出应用);回答超出视口时 ↑/↓(及 Ctrl+P/Ctrl+N)由回答视口接管用于滚动(见"CLI 长回答滚动"用户故事)。
  8. 假设裸 /btw(不带问题)触发 usage 消息显示,则 输入行一并隐藏(与问题 overlay 一致),提示 "Escape to dismiss";当用户按下 ESC 时,则 usage 消息关闭,输入行恢复。其他按键(含 Enter/Space/Ctrl+C/Ctrl+D)在 usage 显示期间被忽略。

用户故事:CLI 长回答滚动(优先级:P2) ​

作为 CLI 用户,我希望长回答被限制在一个固定高度的视口里、用 ↑/↓ 在里面滚动,以便整帧不溢出终端、输入区不把顶部内容顶掉(对齐 Claude Code 的 /btw:固定视口 + 内部滚动,不依赖终端 scrollback)。

验收场景:

  1. 假设回答的渲染行数超过视口,则 回答绘制在固定高度视口中,帧总行数不超过终端行数;视口高度 = max(5, 终端行数 - 11)(11 行为 overlay 自身外观 + 周边界面预留),随终端尺寸变化重新计算。
  2. 假设回答超出视口,当用户按下 ↑ 或 ↓ 时,则 视口每次滚动 3 行;Ctrl+P / Ctrl+N 与 ↑/↓ 等效。
  3. 假设回答超出视口,当视口已滚到顶部/底部时,则 继续按 ↑/↓ 不再移动(无循环滚动)。
  4. 假设回答未超出视口,则 回答视口不接管 ↑/↓,按键仍按 overlay 期间"其他键忽略"的规则处理(用户不会看到视口跳动)。
  5. 假设回答超出视口,则 底栏提示为 ↑/↓ to scroll · Esc to dismiss;未超出时保持 Escape to dismiss。
  6. 假设回答正在流式加载("✻ Answering" + 流式尾部),则 加载行按原样单行显示,不进入滚动视口,也不显示滚动提示。
  7. 假设回答超出视口,当用户按下 ESC 时,则 overlay 依旧关闭(关闭键仍只有 ESC,不引入 Space/Enter/Ctrl+C/Ctrl+D 关闭)。
  8. 假设终端在回答显示期间被缩放,则 视口高度按新的终端行数重算,已滚动位置被夹紧到新的合法范围内。
  9. 假设回答里含折行的长行,则 折行产生的行也计入视口容量(滚动按终端行而不是 Markdown 逻辑行)。

用户故事:BTW 加载状态(优先级:P2) ​

作为 CLI 用户,我希望附带问题加载期间在 "✻ Answering" 后看到当前流式传输文本的最后 30 个字符,以便我知道请求正在进行且能看到输出进度,而不被不完整的流式中间文本干扰。

验收场景:

  1. 假设附带问题正在加载且尚无任何流式输出,则 BtwDisplay 显示问题行与静态 loading 指示(✻)+ "Answering" 文本,不显示流式尾部。
  2. 假设附带问题正在加载且模型已输出文本(普通文本或推理内容,推理流经同一尾部通道),则 BtwDisplay 在 "✻ Answering" 后显示该文本的最后 30 个字符;文本不超过 30 字符时原样显示,超过 30 字符时以 … 前缀截断(换行折叠为 \n,与主对话流式尾部样式一致)。
  3. 假设回答已完成,则 BtwDisplay 将完整答案以 Markdown 渲染显示,"✻ Answering" 加载文本与流式尾部消失。
  4. 假设答案仍在加载,当用户按下 ESC 时,则 请求被中止(abort),BtwDisplay 关闭。

用户故事:Webview 端附带提问(优先级:P1) ​

作为 Webview 用户(VS Code / JetBrains / Desktop),我希望输入 /btw <question> 快速提出旁路问题,以便在不打断主对话、不触发工具执行的情况下获得答案,且附带问题不污染聊天历史。

验收场景:

  1. 假设用户处于主对话模式,当用户在输入框输入 /btw <question> 并按下 Enter 时,则 附带问题绕过主消息队列,输入区上方显示 BTW 面板(问题标题 + 加载指示),主对话与输入框不受影响。
  2. 假设用户在斜杠命令弹窗中选择 /btw,则 输入框插入 /btw 前缀并将光标置于其后等待输入问题,不立即执行。
  3. 假设用户输入不带问题的 /btw 并按下 Enter,则 不发起请求,BTW 面板标题区域仍显示 /btw 标题占位(关闭按钮不漂移到左侧),内容区显示中文 usage 文案 "用法:/btw <你的问题>"(与 Webview 的"正在回答"加载文案一致;CLI 端保持与 Claude Code 一致的英文 "Usage: /btw <your question>")。
  4. 假设 btw 请求发出,则 请求复用主对话的 system prompt、工具列表与记忆注入(fork 请求前缀与主对话字节级一致),并继承主对话的模型与 thinking 参数,仅执行一轮且不执行任何工具(与 CLI 共用同一 agent.askBtw fork 路径)。
  5. 假设 btw 请求已发出,则 BTW 面板显示闪烁光标与"正在回答"中文文案作为加载指示(与主对话消息列表的流式光标一致,不使用 emoji),直到回答完成。
  6. 假设 btw 请求已发出且模型已输出流式文本,则 BTW 面板在加载指示(闪烁光标 + "正在回答")后显示该文本的最后 30 个字符(换行折叠为 \n、超过 30 字符以 … 前缀截断,与主对话/CLI 流式尾部样式一致);模型尚无输出时仅显示加载指示,不显示完整流式中间文本。
  7. 假设回答完成,则 BTW 面板以 Markdown 渲染完整答案,加载指示消失,回答区域可滚动。
  8. 假设附带问题正在加载或已回答,当用户点击关闭按钮或按下 Esc 时,则 BTW 面板关闭,输入框恢复主对话模式。
  9. 假设附带问题正在加载且主对话同时在流式输出,当用户按下 Esc 时,则 仅关闭 BTW 面板,不终止正在进行的 agent loop(主对话继续流式输出)。
  10. 假设附带问题正在加载(含流式输出中)时被手动关闭(关闭按钮或 Esc),则 面板立即消失,迟到的流式增量与最终回答均被丢弃,不显示于界面(与"切走"不同:切走只是隐去,请求继续、切回可恢复——见场景 14)。
  11. 假设 btw 请求失败(如 API 错误),则 BTW 面板显示 "(API error: ...)" 错误信息,不中断主对话。
  12. 假设附带问题不会被添加到主聊天历史或用户输入历史中。
  13. 假设主对话恰好在响应中(assistant 消息未结束)时提出 /btw,则 btw 请求剔除该进行中的消息,从上一轮完成的请求前缀继续。
  14. 假设 BTW 面板打开(加载中或已回答),当用户切换到另一对话(会话)时,则 面板随发起它的对话保留、新对话以干净状态开始(不显示旧对话的附带问题);当用户再切回原对话时,则 面板按离开时的样子恢复——已回答的恢复原答案,仍在加载的继续显示"正在回答"并接着接收该请求的流式尾部(切走期间请求不中断、也不丢弃,迟到回复照旧落在它所属的对话上)。
  15. 假设用户在远控 Web 页(手机浏览器打开的 /remote/)输入 /btw <question>,则 上述 1–14 条全部照旧成立(同一个 askBtw fork 路径、同一个 BtwPanel、不污染历史、Esc 只关面板),即页面不把 /btw 当普通消息发出去;差别只在传输:请求经中继到宿主进程的 askBtw,流式尾部来自宿主的 btwContent 通知。当页面连的是前台 CLI 会话(该宿主尚未接 /btw)时,面板显示一句「该宿主不支持」的可见文案,不停在加载中。承载与白名单见 remote/remote-web.md 的「Web 页也能用 /btw 旁路提问」故事。

边界情况 ​

  • 用户输入不带问题的 /btw 怎么办? 命令不进入 BTW 状态:CLI 显示英文 "Usage: /btw <your question>"(与 Claude Code 一致),Webview 显示中文 "用法:/btw <你的问题>";输入行随 usage 消息隐藏,仅按 ESC 关闭,其他按键被忽略。
  • 用户提出通常会触发工具的 /btw 问题怎么办? btw 请求携带与主对话相同的工具列表(缓存键一致),但仅执行一轮且不反馈工具结果;模型若尝试调用工具,显示 "(The model tried to call X...)" 提示。
  • 请求失败(如 API 错误)怎么办? BtwDisplay 显示 "(API error: ...)" 错误信息,不中断主对话。
  • 模型只输出 thinking 而无最终答案怎么办? BtwDisplay 显示 thinking 内容(而非 "No response received"),避免思考阶段输出被丢弃。
  • 主对话恰好在响应中(assistant 消息未结束)时提出 /btw 怎么办? btw 请求剔除该进行中的消息,从上一轮完成的请求前缀继续。
  • 附带问题不会被添加到主聊天历史或用户输入历史中。
  • CLI 中回答较长如何滚动? 回答绘制在固定高度视口内(高度 = max(5, 终端行数 - 11)),用 ↑/↓(或 Ctrl+P/Ctrl+N)滚动 3 行,不依赖终端 scrollback;超出视口时底栏提示 ↑/↓ to scroll · Esc to dismiss,未超出时保持 Escape to dismiss。关闭键仍只有 ESC。
  • Webview 中回答较长如何滚动? BTW 面板回答区域内部滚动(鼠标/触控板),无需 CLI 的 ↑/↓ 键。
  • Webview 中按 Esc 会终止主对话吗? 不会。BTW 面板打开期间 Esc 在事件捕获阶段被面板拦截(stopPropagation),仅关闭面板;主对话 agent loop(即使正在流式输出)不受影响。
  • 模型 thinking 结束后还显示 thinking 内容吗? 不显示。加载期间只显示流式尾部(当前流式文本的最后 30 个字符),不显示完整中间文本;回答完成后只以 Markdown 渲染最终答案。
  • 切换对话时 BTW 面板会残留吗? 不会残留(不串对话),也不会丢:面板属于发起它的那个对话,切到别的对话时不显示它,新对话始终以干净状态开始;切回来时原样恢复,包括还在"正在回答"的那种(后台请求不中断,流式尾部接着更新)。
  • 会话被删除后 BTW 面板会复活吗? 不会。面板随会话一起消失,此后再进不来那个会话,自然也无从恢复(与面板布局、预览地址等会话级 UI 状态同命运)。
  • 桌面端多 pane 并排时切换焦点会关闭 BTW 面板吗? 不会。BTW 面板是对话级别的,不是焦点级别的:焦点从 pane 1 切到 pane 2 时,pane 1 上已打开的 BTW 面板保持显示;host 仅下发 desktopPanes(focusedPaneId 变化)而不推送新会话,各 pane 自己的 currentSession 不变。只有某 pane 绑定的会话真正切换时,该 pane 才换成新会话的视图(原会话的面板随之隐去,切回原会话时照旧恢复)。