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

98 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 子代理完成卡双轨「已消化」降级 · 设计(2026-10-04)
> ✅ 拍板通过(2026-10-04,2/2 按建议:D1 自动折叠默认开/D2 trace 随 namespace 批;见 [拍板集](../滚动规范/拍板集-2026-10-04.md))
> 来源: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)。