Files
smartmate/docs/功能决策记录/Agent流式协议_前后端对齐_决策记录.md
Losita 146b94fd50 Version: 0.9.30.dev.260419
后端:
1. 工具事件推送从通用 EmitStatus 重构为 EmitToolCallStart / EmitToolCallResult 结构化双事件
- newAgent/node/execute.go:executeToolCall / executePendingTool 两处调用路径分离为 Start + Result 两步推送;blocked 场景显式传入状态码,不再复用通用状态
- 新增工具事件摘要生成链:resolveToolEventResultStatus(结果状态映射)、buildToolEventResultSummary / tryExtractToolResultSummaryCN(JSON→中文结论提炼)、buildToolCallStartSummary /
buildToolArgumentsPreviewCN(参数白名单中文标签)、resolveToolDisplayNameCN(17 个工具中文名映射)、formatToolArgValueByKeyCN / formatToolArgValueCN(参数值格式化)
- newAgent/stream/emitter.go:EmitStatus / EmitToolCallStart / EmitToolCallResult 统一收敛到 emitExtraOnly,不再回写 reasoning_content;EmitToolCallResult 新增 status 参数

前端:
1. 全局侧边栏统一提升到 App.vue
- App.vue 新增 MainSidebar + smartflow-layout 双栏布局,三个页面共享导航;AssistantView / DashboardView / ScheduleView 移除各自内联 sidebar 定义、路由跳转、拖拽逻辑及全部样式
2. Assistant 消息流从纯文本重构为结构化 block 时间线
- AssistantPanel 新增 ToolTraceEvent / StatusTraceEvent / DisplayAssistantBlock 类型;handleStreamExtraEvent 按 extra.kind 分发四类事件;getDisplayAssistantBlocks 按 seq 排序统一渲染 tool/status/reasoning/content 五种 block
- 模板层改为 TransitionGroup 动态渲染;工具卡片左侧彩色状态条 + 可展开详情;状态行显示节点阶段中文文案;兼容旧协议 tool_* 状态码归并
- SSE 协议切换到 extra-only:shouldSuppressReasoningDeltaByExtraKind 抑制 status/tool 事件的 reasoning 累积;会话/首页加载锁定 800ms 最少时间保证骨架屏动画
3. 设计系统从渐变毛玻璃迁移到 Flat Modern 扁平化
- 全局色板统一 #3b82f6 / #f8fafc / #f1f5f9,替代旧蓝紫渐变;confirm 卡片琥珀色顶条、用户气泡蓝底白字、工具卡片状态色条
- 新增 dashboard-item-pop / board-item-pop / message-stagger / fade-switch / task-detail 等入场动画;WeekPlanningBoard 格子弹簧动画按行列错峰;TaskClassSidebar 详情展开 max-height 过渡 + 角标旋转
4. 路由新增 /prototype/tool-trace 原型页(ToolTracePrototypeView)
2026-04-19 00:21:44 +08:00

220 lines
9.0 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.
# Agent 流式协议前后端对齐 决策记录
## 1. 基本信息
- 记录编号FDR-009
- 功能名称Agent Chat SSE 协议前后端对齐(去伪思考化)
- 记录日期2026-04-18
- 决策状态:提议(评审后执行)
- 负责人SmartFlow 团队
- 关联需求 / Issue
- 工具调用信息前端可视化(折叠式、通俗文案)
- 降低“深度思考”误导(当前为伪装块)
## 2. 背景与问题
- 业务背景:
- 目前聊天页已经在做流式展示、确认卡片、会话管理;
- 计划将“工具调用过程”以专属样式内联展示。
- 现状问题:
1. 后端阶段状态/工具状态,会通过 `reasoning_content` 回传给前端,形成“看起来像深度思考”的内容;
2. 前端目前只消费 `extra.kind=confirm_request`,其他 `extra` 结构化事件并未真正用于渲染;
3. 用户感知层面会误以为模型正在“深度思考”,但其中大量内容其实是流程状态(非真实思考)。
- 不做此决策的后果:
1. 前端即使先移除“深度思考框”,也会连同状态可见性一起丢失;
2. 前后端协议继续漂移,工具可视化落地会重复返工;
3. 后续“真流式 speak”与“工具事件流”会相互干扰排查困难。
## 3. 决策目标
- 目标 1统一 SSE 协议语义边界:`reasoning_content` 仅承载真实思考文本,不再承载阶段/工具状态文案。
- 目标 2`extra.kind` 作为结构化事件主通道,前端据此渲染工具/状态专属 UI。
- 目标 3明确迁移顺序先后端协议就位再前端切换展示最后清理兼容层。
- 非目标(本次不解决):
- 不在本轮实现“每一次 speak 都改成 chat 节点流式消息头”;
- 不在本轮重构全部历史会话数据存储格式。
## 4. 备选方案
### 方案 A先改前端先隐藏深度思考区
- 描述:前端先把思考区关闭或默认不展示,后端暂不改。
- 优点:
- 见效快UI 即刻变“干净”。
- 缺点:
- 只是遮罩,不是协议治理;
- 状态可见性与思考内容耦合,后续仍要返工。
- 复杂度 / 成本:低(短期)/ 高(长期返工)
### 方案 B先改后端协议再改前端渲染采纳
- 描述:后端先把状态/工具事件改为结构化主通道,前端再切换消费逻辑与样式。
- 优点:
- 语义边界清晰,长期维护成本低;
- 前端可直接做“折叠式工具行”,不再依赖伪思考文本;
- 可通过双写/开关平滑迁移,风险可控。
- 缺点:
- 首轮需要前后端并行协作与联调。
- 复杂度 / 成本:中
### 方案 C前后端同一轮同时硬切
- 描述:单次发布同时切后端协议和前端展示,不保留兼容层。
- 优点:
- 路径最短,代码最“干净”。
- 缺点:
- 回归风险高,灰度与回滚空间小;
- 一旦线上混部或缓存命中旧逻辑,容易出现空白块/重复块。
- 复杂度 / 成本:中(开发)/ 高(上线风险)
## 5. 最终决策
- 采纳方案:方案 B先后端协议再前端渲染最后清理兼容层
- 关键理由:
1. 先解决协议语义,再做视觉层改造,避免 UI 层“治标不治本”;
2. 与“工具调用可视化”目标一致,能直接对接折叠式工具行;
3. 具备可灰度、可回滚的工程路径。
## 6. 影响范围
- 涉及模块:
- 后端:`backend/newAgent/stream``backend/newAgent/node`
- 前端:`frontend/src/components/dashboard/AssistantPanel.vue`
- 数据与存储影响:
- 无数据库结构变更;
- 仅影响实时 SSE 事件解释方式。
- 接口 / 协议影响:
- `POST /api/v1/agent/chat` 的 SSE chunk 语义调整(见第 7/8 节)。
- 监控与日志影响:
- 需新增“事件类型计数”与“前端解析命中率”观测。
## 7. 前后端接口现状AS-IS
### 7.1 SSE 外层协议(当前)
- 后端已定义 OpenAI 兼容壳 + `extra` 扩展,代码位置:
- `backend/newAgent/stream/openai.go`
- `backend/newAgent/stream/emitter.go`
- `extra.kind` 已有枚举:`status``tool_call``tool_result``confirm_request` 等。
### 7.2 当前关键现象
1. 后端 `EmitStatus` 会把阶段文案同时写入:
- `extra.kind=status`
- `choices[0].delta.reasoning_content`(降级文本)
2. 执行节点多数工具过程仍通过 `EmitStatus(code=tool_call/tool_blocked)` 推送;
3. 前端 `processSseBlock` 当前只显式处理:
- `parsed.extra?.kind === 'confirm_request'`
4. 结果大量状态文案作为“reasoning”显示形成伪“深度思考”体验。
### 7.3 当前事件样例(简化)
```json
{
"choices": [
{
"delta": {
"reasoning_content": "阶段execute\n正在调用工具queue_status"
}
}
],
"extra": {
"kind": "status",
"status": {
"code": "tool_call",
"summary": "正在调用工具queue_status"
}
}
}
```
## 8. 目标协议TO-BE
### 8.1 总体原则
1. `reasoning_content`:只承载真实模型思考文本;
2. `extra.kind`:承载流程状态和工具事件(前端主消费通道);
3. 前端渲染:默认不把状态事件塞入“深度思考区”,而是进入工具/状态专属样式。
### 8.2 目标事件约定
| 事件类型 | `extra.kind` | 前端默认表现 | 是否进入 reasoning 区 |
|---|---|---|---|
| 阶段状态 | `status` | 轻量状态行 / 提示条 | 否 |
| 工具调用开始 | `tool_call` | 折叠工具行(默认摘要) | 否 |
| 工具调用结果 | `tool_result` | 更新同一工具行状态与详情 | 否 |
| 待确认 | `confirm_request` | 确认卡片 | 否 |
| 真思考 | `reasoning_text` | 思考区(可折叠) | 是 |
| 正文输出 | `assistant_text` | 正文区 | 否 |
### 8.3 目标工具事件样例(简化)
```json
{
"choices": [],
"extra": {
"kind": "tool_call",
"stage": "execute",
"tool": {
"name": "queue_status",
"status": "start",
"summary": "已调用工具:查看任务队列",
"arguments_preview": "默认参数"
}
}
}
```
```json
{
"choices": [],
"extra": {
"kind": "tool_result",
"stage": "execute",
"tool": {
"name": "queue_status",
"status": "done",
"summary": "待处理 3 项,已完成 1 项"
}
}
}
```
## 9. 实施计划(先后端、再前端)
### 里程碑 1后端协议对齐先做
- 目标:状态/工具事件走结构化主通道,不再依赖伪 reasoning 文本。
- 开工清单(后端):
1. `execute` 工具链路改用 `EmitToolCallStart/EmitToolCallResult`
2. `EmitStatus` 增加策略开关:支持“仅 extra不回写 reasoning_content”模式
3. `tool_blocked` 统一归类到工具事件(或结构化 status避免文本拼接歧义
4. 输出契约补充到 `backend/newAgent/ARCHITECTURE.md`
### 里程碑 2前端事件消费切换
- 目标:前端按 `extra.kind` 渲染,不再把流程状态当“深度思考”。
- 开工清单(前端):
1. `processSseBlock` 增加 `status/tool_call/tool_result` 解析;
2. 新增“折叠式工具行”状态机(默认摘要、展开详情);
3. 深度思考区默认只接收真 `reasoning_text`
4. 确认卡片逻辑保持兼容。
### 里程碑 3兼容层收敛
- 目标:确认稳定后去除伪思考降级写法。
- 开工清单:
1. 关闭后端状态写入 `reasoning_content`
2. 清理前端旧降级路径;
3. 补齐回归用例与文档。
## 10. 风险与应对
- 风险 1前端未及时消费 `extra.kind`,导致状态缺失。
- 应对策略:后端先双写一段窗口期(可配置开关),灰度切换。
- 风险 2工具事件顺序乱序导致 UI 折叠状态错位。
- 应对策略:使用 `block_id + tool.name + stage` 做关联键,按到达顺序幂等更新。
- 风险 3历史会话与新会话混合展示不一致。
- 应对策略:仅对新流式消息生效,历史消息维持只读展示。
## 11. 验证与回滚
- 验证方式:
1. 后端单测:事件序列与 payload 结构校验;
2. 前端联调:`tool_call -> tool_result -> summary` 顺序回放;
3. 手工场景:普通问答 / 工具调用 / confirm / tool_blocked。
- 成功判定标准:
1. 状态类文本不再出现在“深度思考区”;
2. 工具事件能稳定渲染为折叠行;
3. confirm 卡片行为不回归。
- 回滚方案:
- 后端切回“状态写 reasoning_content + 旧前端渲染”兼容模式;
- 前端保留旧路径开关,必要时回退版本。
## 12. 后续计划
- 后续优化项 1把 speak 也统一到更细粒度真流式事件头(下一轮决策)。
- 后续优化项 2工具详情文案模板化通俗中文 + 可本地化)。
- 后续优化项 3工具事件接入埋点点击展开率、阅读停留、错误率
## 13. 复盘结论(上线后补充)
- 实际效果:待补充
- 与预期偏差:待补充
- 后续是否需要二次决策:待补充