7.1 KiB
Agent Note: 将 plan mode 组合进 Web 产品
Status: implemented
English | 中文
问题
Web 宿主可以通过可选会话 RPC 契约投影 plan 状态,但已交付的 Web 产品既未挂载 plan 服务,也未公开模式控件。若只挂载浏览器切换控件,模型将缺少 plan 引导和 exit_plan_mode;若只挂载宿主服务,该功能将难以发现,也无法显示正在等待下一请求边界的状态。
选择 plan mode 并不是停止命令。plan 服务会有意将最新目标排到模型请求边界生效,使当前请求在内部保持一致。UI 必须同时显示已提交状态和待生效目标,包括 pending: false,且不能越过宿主响应进行推测。由模型发起的退出也必须沿用现有的结构化 plan 评审,不能再建立一条仅供 Web 使用的审批路径。
决策
@deepseek-ai/dsh-client-ui-plan 是一个 Web 功能插件,包含生命周期耦合的宿主入口和浏览器入口。宿主入口使用 Web 产品的完整 plan 策略挂载 @deepseek-ai/dsh-plan-mode。浏览器入口则把 PlanModeControl 注册到会话作用域的 conversation.composer.controls 列表槽。dsh web 的插件清单只需选择该包一次:插件发现机制会加载浏览器入口,同一次清单挂载则提供宿主行为。
该策略是此组合边界上由产品拥有的配置。它要求模型先检查再规划、规划期间避免修改、无需询问即可自行查明能够发现的事实、使 plan 包含完成决策所需的全部信息,并把 plan 作为唯一且最终的 exit_plan_mode 调用提交。plan 包(package)继续拥有已记录的状态、边界时序、提示词段激活、稳定的退出工具 schema 和评审语义。Web 插件不会复制其中任何机制。
ui-conversation 拥有并渲染新增的可叠加控件槽,其位置在 composer 主操作左侧。该槽不提供业务载荷;各入口接收标准会话注入项。替换整个 composer 的功能仍走另一条由选择器路由的 conversation.composer 链,因此待处理的问题会替换 InputBar 及其控件,两个功能均无需导入对方。
当 planMode 为 null 时,控件不会出现。否则,其选中值为 pending ?? active,而待生效状态的呈现依据是字段是否存在,而非字段真值。在日志提交替换快照前,控件会显示 计划 · 待生效 或 默认 · 待生效。透明的原生 select 会将焦点状态映射到可见的 chip,并引用一条动态无障碍描述,以区分已提交模式和待生效目标。选择操作只会在自身 RPC 执行期间禁用选择器。生成过程不会禁用该控件:在运行中的轮次里选择模式,既不会调用取消,也不会改变该轮次;取消生成也不会清除待生效目标。
交互语义
| 观察到的状态 | 控件 | 用户操作 | 结果 |
|---|---|---|---|
{ active: false } |
默认 | 选择「计划」 | 宿主确认 { active: false, pending: true } |
{ active: false, pending: true } |
计划,待生效 | 发送提示词 | 边界记录 plan/mode: true;控件变为已提交的「计划」 |
{ active: true },运行中 |
计划 | 选择「默认」 | 轮次继续;控件显示「默认,待生效」 |
{ active: true, pending: false } |
默认,待生效 | 停止 | 待生效目标保留;下一条提示词提交「默认」 |
null |
隐藏 | — | 产品组合不会公开不受支持的控件 |
业务故障和传输故障都会保持已确认的快照不变,重新启用选择器,并在其旁边渲染一条紧凑且可见的失败信息。组件会防止卸载后完成的异步操作继续更新状态,因此切换会话不会更新已经退出使用的控件。
退出评审
exit_plan_mode 在两种模式下都会保持注册,以维持请求缓存稳定性。在 plan mode 中,模型通过该工具提交完整的 Markdown plan。plan 服务经由 ctx.userInteraction 发起询问,已组合进 Web 的问题插件会展示 plan 详情,并提供「批准」、「继续规划」和自由文本回答渠道。问题详情会复用 assistant 输出所用的 Markdown 基础组件及其不受信任内容策略。设有高度上限的问题卡片会固定显示标题、导航操作和提交操作,而完整 plan 与选项共享同一个内部滚动区域。由于 composer 接管是该等待状态的唯一呈现方式,聊天流程不会渲染通用的待处理问题占位块。
批准会将未激活模式排到下一步骤生效,不会重写当前工具批次。选择继续规划或提供自定义反馈时,plan mode 保持激活,并向模型返回修正反馈。若评审渠道不可用或已中止,工具会采取失败关闭策略,策略则要求模型请用户手动切换模式。
产品组合与证据
fixture(测试前置数据)模式在内存中实现相同的待生效与边界行为,因此浏览器验收测试无需密钥即可覆盖组合后的产品。无密钥浏览器流程依次选择「计划」、通过提示词提交该模式、在生成期间选择「默认」、停止生成且不丢失待生效目标,再通过下一条提示词提交「默认」。文件快照记录每个用户可见状态。另一个使用 mock 提供方的真实 dsh web 进程还证明:插件清单会挂载 plan mode,状态 RPC 会报告该功能,并且激活的 Web 策略会随工作区指令一同进入提供方请求。
考虑过的替代方案
把选择器直接放进 ui-conversation。 不予采纳,因为会话骨架将因此获得 plan 领域知识和宿主依赖。新增的可叠加槽让 ui-plan 保持对功能的归属,并为彼此独立的控件留出空间。
在宿主运行时无条件挂载 plan mode。 不予采纳,因为 plan mode 是产品组合选择。可选 RPC 契约必须继续表达未选择该功能的宿主。
乐观地翻转本地布尔值。 不予采纳,因为宿主追加失败、其他界面、恢复或经工具评审的退出都可能与该值不一致。控件只显示宿主确认的已提交状态和待生效状态。
生成运行期间禁用切换,或让切换停止当前轮次。 不予采纳,因为这会改变 plan 服务的边界契约,并将协作状态与取消操作耦合。待生效状态的存在,正是为了让这两项操作彼此独立。
创建 Web 专用的 plan 审批组件。 不予采纳,因为 plan 评审已经是一项结构化的用户交互问题。复用问题 composer 可以保留单一评审协议和自由文本修正路径。
后果
Web 产品现在会在保留插件边界的同时,公开与现有终端和 ACP(Agent Client Protocol)产品组合相同的 plan 交互模型。选择该功能会增加一个宿主策略/工具所有者和一个浏览器槽入口;移除其 fiber 会同时移除二者。模型工具目录在模式切换期间保持稳定,但激活的系统提示词段会在 plan 边界发生变化,因此请求前缀也会改变。Plan mode 仍是引导机制,而非执行沙箱:需要强制只读规划的部署仍需组合彼此独立的沙箱策略和审批策略。