- 无人值守长任务设计定稿,含效率与可观测补遗 - u-relay wire 协议规格与五项评估结论 - 新能力引入评估纪律五项清单 - todo 销账与狗粮短板分析登记
6.5 KiB
子代理完成卡双轨「已消化」降级 · 设计(2026-10-04)
✅ 拍板通过(2026-10-04,2/2 按建议:D1 自动折叠默认开/D2 trace 随 namespace 批;见 拍板集)
来源:todo.md 子代理深查「P2 完成卡(前端全文)与父上下文(压缩)双轨无『已消化』降级机制[需设计]」。 勘察结论(2026-10-04 现场核实,以源码为准,修正深查一处过时结论):
- 完成卡前端已非「重启蒸发」:
aiShared.ts:677已有按父 conv 经ai_sub_agent_list反查重建完成卡(轨迹存在即视为 completed),重启回补链路已通。剩余缺口即「已消化」降级。- 双轨现状:前端卡持 summary 全文(
AgentFinishedCard.summary,卡面 160 字截断展示);父上下文中报告经 namespace 引用+context_helpers.rs视图压缩(TOOL_RESULT_SUMMARIZE_BYTES=2048/TOOL_RESULT_JSON_STR_FIELD_MAX=512),父 LLM 后续轮次只能看到 ≤512 字符折叠摘要。- 事件链:
sub_agent.rs:495统一出口 emitAiAgentFinished{status,summary,rounds,tokens,rejected_tools,stop_kind}(挂父会话)+ 整轨迹落库(V44 origin='sub_agent')。
1. 问题定义
「双轨无降级」的三层含义:
- 信息层:父 LLM 与前端卡各持一份(上下文折叠摘要 vs 前端全文),两者无互认,用户在卡上看到的细节 LLM 答不上;
- 生命周期层:卡永久挂在消息流(直到会话删除),无「已读/已消化」状态;多轮追问后卡仍以初始完整态占据视觉焦点;
- 一致性层:父 LLM 被追问报告细节时若折叠摘要不够,唯一出路是重新
ai_sub_agent_list反查轨迹(LLM 未必想到/舍得花 token)。
2. 设计目标
- 卡可标记「已消化」,视觉降级(折叠/淡化)但可展开复原,信息不丢;
- 父 LLM 追问细节时有结构化自助通道(不用重跑子代理);
- 「已消化」状态持久化(重启/切会话后保留);
- 零后端 schema 变更(复用现有落库轨迹)。
非目标:不做卡全文注入上下文(会反向膨胀 prompt);不做自动消化判定(何时算「消化」留人工,v2 可议 LLM 显式 ack)。
3. 方案
3.1 「已消化」状态与持久化
前端 AgentFinishedCard 增字段:
+ digested?: boolean // 默认 false
持久化载体:复用 KV 存储(app 已有 settings/KV 表),key = agentCardDigested:{parentConvId} → string[](agentId 列表,JSON)。切换/挂载回补时(aiShared.ts:677 重建路径)读 KV 合并标记。不落 SQLite 新列/新表——卡本身是派生态(由轨迹重建),消化标记是用户偏好,KV 语义足够。
3.2 视觉降级交互
未消化卡: 现状(标题行+status 徽章+160 字摘要+展开全文)
已消化卡: 标题行单行化(✓ 已消化 · summary 首 40 字 · status 徽章淡化),点击展开复原全文
手动标记: 卡右上角「标记已消化」动作(hover 显现),支持批量(同会话多卡)
自动辅助: 同会话出现新完成卡时,旧未消化卡自动折叠为单行(不标已消化,仅视觉收纳,复用 ToolCardList 分组折叠的 touched 语义——用户手动展开过则不自动收)
3.3 父 LLM 自助通道(关键补强)
现状 LLM 有 ai_sub_agent_list(列轨迹元数据)但没有读单条轨迹全文的工具(前端卡经 IPC ai_sub_agent_list 拉的是轨迹列表,LLM 侧工具面无对应读全文入口)。
新增 LLM 工具(注册进 tool_registry,risk=Low 只读):
ai_sub_agent_trace(conversation_id, agent_id) -> { summary, status, rounds, tokens, messages_tail? }
- 返回该子代理轨迹的关键内容(summary 全文 + 末 N 条消息摘要),只读、走现有 V44 落库数据,零新存储;
- system prompt 子代理指引段补一句:「追问子代理产出细节时,先调 ai_sub_agent_trace 而非重新 spawn」;
- 这同时是 namespace 淘汰治理( sister 设计文档)中「报告蒸发死路」的兜底——即使 namespace 条目被淘,轨迹在 DB,工具可读。
3.4 「已消化」与上下文压缩的联动(可选增强,默认关)
AgentFinishedCard.digested=true 时,前端在后续轮次注入的用户消息尾部不加任何内容(保持零侵入);该标记仅影响 UI 与用户心智。不把 digested 同步回后端压缩策略(避免跨端状态同步复杂度)。
4. 改动面清单
| 层 | 文件 | 改动 |
|---|---|---|
| 前端 | src/composables/ai/aiShared.ts |
AgentFinishedCard+digested;重建路径读 KV 合并 |
| 前端 | 完成卡渲染组件(MessageList 内 SubAgentCard 或同域) | 降级态渲染+标记动作+批量 |
| 前端 | KV 读写封装(复用现有 settings composable) | get/set agentCardDigested:{convId} |
| 后端 | src-tauri/src/commands/ai/agentic/sub_agent.rs |
暴露 ai_sub_agent_trace IPC(读库组装) |
| 后端 | tool_registry.rs |
注册 ai_sub_agent_trace(Low/只读白名单) |
| 提示词 | system prompt 子代理指引段 | 追问先 trace 不重跑 |
5. 风险与对策
| 风险 | 对策 |
|---|---|
| KV 标记与轨迹删除不同步(轨迹删了 KV 残留) | 重建路径只对「轨迹存在的卡」应用标记,孤儿 key 自然失效,无需清理任务 |
| trace 工具被滥用(LLM 反复查大轨迹) | 返回体加尾部分页/上限(messages_tail ≤ 20 条),复用 T-05 工具结果截断口径 |
| 卡交互改动碰 MessageList 渲染热点 | 卡是独立组件,降级态纯展示层,vue-tsc+手测三态(未消化/已消化/展开) |
6. 验收
- 标记已消化 → 卡单行化 → 重启应用后仍单行(KV 持久);
- 展开已消化卡 → 全文复原;
- LLM 调 ai_sub_agent_trace 能返回指定子代理 summary 全文;
- 未做任何标记的会话,渲染与现状逐像素一致(回归门);
- cargo test(新增 trace IPC 组装单测)+ vue-tsc 0 error。
7. 拍板点(2 项)
- 拍板1:旧卡自动折叠(§3.2)默认开还是关?建议开( touched 语义保护手动展开)。
- 拍板2:ai_sub_agent_trace 本期做还是随 namespace 治理批一起做?建议随 namespace 批(同域文件+互为兜底)。
8. 工作量估算
约 1-1.5 天:digested+KV(2h)+ 卡降级渲染(3h)+ trace IPC+注册(3h)+ 提示词(0.5h)+ 测试(2h)。