Files
DevFlow/docs/02-架构设计/专项设计/子代理完成卡已消化降级-设计-2026-10-04.md
T
lxy b994cf2c54 文档: 设计定稿与评估纪律登记
- 无人值守长任务设计定稿,含效率与可观测补遗
- u-relay wire 协议规格与五项评估结论
- 新能力引入评估纪律五项清单
- todo 销账与狗粮短板分析登记
2026-10-04 16:27:32 +08:00

6.5 KiB
Raw Blame History

子代理完成卡双轨「已消化」降级 · 设计(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 统一出口 emit AiAgentFinished{status,summary,rounds,tokens,rejected_tools,stop_kind}(挂父会话)+ 整轨迹落库(V44 origin='sub_agent')。

1. 问题定义

「双轨无降级」的三层含义:

  1. 信息层:父 LLM 与前端卡各持一份(上下文折叠摘要 vs 前端全文),两者无互认,用户在卡上看到的细节 LLM 答不上;
  2. 生命周期层:卡永久挂在消息流(直到会话删除),无「已读/已消化」状态;多轮追问后卡仍以初始完整态占据视觉焦点;
  3. 一致性层:父 LLM 被追问报告细节时若折叠摘要不够,唯一出路是重新 ai_sub_agent_list 反查轨迹(LLM 未必想到/舍得花 token)。

2. 设计目标

  1. 卡可标记「已消化」,视觉降级(折叠/淡化)但可展开复原,信息不丢;
  2. 父 LLM 追问细节时有结构化自助通道(不用重跑子代理);
  3. 「已消化」状态持久化(重启/切会话后保留);
  4. 零后端 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. 验收

  1. 标记已消化 → 卡单行化 → 重启应用后仍单行(KV 持久);
  2. 展开已消化卡 → 全文复原;
  3. LLM 调 ai_sub_agent_trace 能返回指定子代理 summary 全文;
  4. 未做任何标记的会话,渲染与现状逐像素一致(回归门);
  5. 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)。