deerflow-code/docs/agentscope-多智能体报告协作工作台-前端实施计划.md
2026-09-07 18:24:55 +08:00

720 lines
36 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.

# AgentScope 2.0 多智能体报告协作工作台——前端实施计划
> 文档状态:前端代码已落地、契约冻结;联调等待后端运行中干预与报告改写
> 编写日期:2026-09-02;进度更新日期:2026-09-06
> 目标项目:`F:\react01\deeflow-code\deerflow-server\frontend-web`
> 视觉与交互参考:`F:\react01\coze-frontend\frontend\apps\coze-studio`
> 参考页面:`http://localhost:3000/work_flow?space_id=1&workflow_id=wf_88cb9f4c6642`
> 配套后端计划:`docs/agentscope-多智能体报告协作工作台-后端实施计划.md`
> 本文只规划新增页面,不修改现有多智能体会商页面,不复用旧 Workflow Studio 执行状态。
## 0. 当前进度
`frontend-web/src/report-collaboration/` 已实现两栏工作台、会话/方案/run API 客户端、mock driver、SSE reducer、`MessageList` 适配、方案卡、画布、节点抽屉、Composer、报告预览与历史。`RC-FE-001`~`013` 的页面骨架与契约层视为完成。
后端已通规划前路径(澄清 → 出方案 → 选定 → `queued` run),见后端计划 §0。前端真实执行体验仍受阻:
- `GET /runs/{id}/stream` 已挂载(`RC-BE-011`);dispatcher/租约已落地(`RC-BE-012`),默认 `worker_enabled=false` 仍不自动领取 queued run。
- 报告改写 / 恢复接口已由后端 `RC-BE-015` 挂载。
- 质量角色已由 `QualityRoleKernel` 跑通(`RC-BE-013`);真实 AgentScope 模型/`web_search` 仍待后续票。
联调顺序:先打开 `report_collaboration.enabled` 验证规划前 REST 与 `GET /runs/{id}/stream` 重放;画布自动执行需同时打开 `worker_enabled`(默认关)。
## 1. 前端目标
新增独立的「报告协作」工作台。用户可以通过对话提出任意报告需求,查看系统生成的多个协作方案,点击方案卡片在流程图中预览协作结构,确认后观察多智能体执行,并在全过程通过统一对话框提出修改意见。
前端必须满足:
1. 页面采用“左侧对话、右侧流程画布”的固定两栏布局,画布、工具栏、弹窗和抽屉参考 Coze Studio 页面风格。
2. 消息列表必须复用 DeerFlow 现有 `MessageList`,不复制 Coze 的会话消息实现。
3. 所有执行过程、AgentScope 团队消息、智能体回复、工具调用及其原始返回、错误、协助卡、返工和最终报告入口都通过现有消息协议按时间顺序显示在左侧对话区,不设置独立执行结果面板,也不另做“阶段摘要”替代实时消息。
4. 候选方案、流程节点、对话进度和报告使用同一份后端事实,不各自推断状态。
5. 用户可在规划中、运行中、等待输入和报告完成后继续对话。
6. 用户协助卡的出现和提交都不能在前端被解释为“节点已经完成”。
7. 页面刷新、SSE 断线重连、历史会话切换后能恢复到一致状态。
暂定:
- 页面名称:`报告协作`。
- 路由:`/page/workspace/report-collaboration`。
- 会话路由:`/page/workspace/report-collaboration/:sessionId`。
- 默认候选方案数量:3。
- 点击画布节点时打开覆盖式节点说明抽屉;抽屉只展示节点职责和合同,不展示节点执行结果。
---
## 2. 范围与非目标
### 2.1 本期范围
- 新建、查看、重命名、删除协作报告会话。
- 使用对话澄清报告需求。
- 显示 2~3 个候选方案卡片。
- 卡片与右侧流程图预览联动。
- 节点说明抽屉:职责、所依据的信息类型、预期产出、工具、资料要求和验收条件。
- 实时展示节点排队、运行、校验、等待用户、完成、返工、失败和取消。
- 在左侧对话时间线中直接展示每个智能体的流式文本、团队对话、工具调用和工具返回,并展示审稿意见、报告文件和报告版本。
- 并行阶段用横向的智能体选择器切换当前查看对象;选择器只控制同一份消息流的聚焦范围,不创建另一套执行结果视图。
- 运行期间发送补充要求、重新检索、重新分析、节点重跑等指令。
- 完成后进行报告问答、章节重写、全文润色和版本恢复。
- 报告模板选择、Markdown 预览、Markdown/Word 下载。
- 响应式布局、键盘操作、加载反馈和错误恢复。
### 2.2 明确不做
- 不引入 `@coze-workflow/playground` 或 `@coze-arch/coze-design`。
- 不加载 Coze workflow definition、run 或 node run。
- 不允许前端拖拽连线后直接改变执行逻辑。
- 不新增第二套消息气泡、Markdown、引用和文件卡渲染器。
- 不展示模型原始 chain-of-thought、系统/内部 prompt、密钥和被标记为内部控制信息的字段。
- 不把用户有权查看的 AgentScope TeamSay、智能体文本、工具调用或工具返回压缩成“正在检索”等摘要卡;这些原始业务消息必须进入复用的 `MessageList`。敏感字段只能按统一脱敏策略替换,不能以摘要替代。
- 不增加第三栏、常驻详情栏、节点执行结果栏或独立执行时间线。
- 节点抽屉不展示节点生成正文、工具返回、证据列表、错误堆栈或 attempt 历史;这些过程统一在左侧 `MessageList` 的原生消息/工具步骤中查看。
- 不改造现有圆桌、多智能体会商、深度研究和 AI 写作页面。
- 不把浏览器状态作为业务事实源。
---
## 3. 参考页面行为映射
| 目标行为 | Coze 参考文件 | DeerFlow 目标组件 | 说明 |
|---|---|---|---|
| 两栏骨架 | `workflow-studio-layout.tsx` 的面板比例与分隔条 | `ReportCollaborationLayout.tsx` | 左对话、右画布;只保留一条可调整分隔线 |
| 顶栏 | `workflow-studio-header.tsx` | `ReportCollaborationHeader.tsx` | 替换为会话、模板、报告、停止等操作 |
| 候选卡片 | `workflow-proposal-cards.tsx` | `ReportPlanCards.tsx` | 点击预览,明确确认后才执行 |
| 右侧画布 | `workflow-canvas.tsx` | `ReportFlowCanvas.tsx` | 使用 `@xyflow/react` 重建,不引入 Coze Playground |
| 左侧消息区 | `run-conversation-panel.tsx` | `ReportConversationPanel.tsx` | 外层风格参考 Coze,内部复用 DeerFlow `MessageList` |
| 节点说明抽屉 | Coze 节点配置面板的视觉与抽屉行为 | `NodeInspectorDrawer.tsx` | 点击画布节点打开,只展示职责与输入输出合同 |
| 全程执行反馈 | 参考其进度和状态表达 | `AgentStageSelector` + DeerFlow `MessageList` | 选择智能体后直接显示其流式消息、TeamSay、工具调用与返回;不再合成为阶段摘要 |
| 状态栏 | `connection-status.tsx` | `ConnectionStatusBar.tsx` | 展示连接、重连和事件游标 |
| 对话历史 | `left-panel-tabs.tsx` | `ConversationSidebarTabs.tsx` | 对话与历史,不增加“节点资源”Tab |
| 异步反馈 | 规划进度、运行状态 | MessageList 步骤条 + 画布状态 | 操作超过 300ms 必须有反馈 |
主要参考源:
- `F:\react01\coze-frontend\frontend\apps\coze-studio\src\workflow-standalone\components\workflow-studio-layout.tsx`
- `F:\react01\coze-frontend\frontend\apps\coze-studio\src\workflow-standalone\components\workflow-studio-composition.tsx`
- `F:\react01\coze-frontend\frontend\apps\coze-studio\src\workflow-standalone\components\workflow-studio-header.tsx`
- `F:\react01\coze-frontend\frontend\apps\coze-studio\src\workflow-standalone\components\run-conversation\workflow-proposal-cards.tsx`
- `F:\react01\coze-frontend\frontend\apps\coze-studio\src\workflow-standalone\styles.module.less`
若直接复制 Apache-2.0 源码片段或样式,必须保留版权头并维护来源说明;默认做行为映射和视觉重建。
---
## 4. 页面结构
```text
┌──────────────────────────────────────────────────────────────────────────┐
│ 返回 报告协作 / 会话标题 保存状态 模板 报告 停止/继续 更多 │
├────────────────────────────────┬─────────────────────────────────────────┤
│ 对话 / 历史 │ 协作流程图 │
│ │ │
│ DeerFlow MessageList │ @xyflow/react │
│ · 并行时:[协调者][市场][政策] │ · 节点状态与活动连线 │
│ · 用户与协调者/成员消息 │ · 缩放、适配视图、小地图 │
│ · 原生 ToolCall / ToolMessage │ · 点击节点打开覆盖式说明抽屉 │
│ · 协助卡、报告文件和版本 │ │
│ │ │
│ 统一输入框 │ │
├────────────────────────────────┴─────────────────────────────────────────┤
│ 已连接 · run_xxx · 事件 128 │
└──────────────────────────────────────────────────────────────────────────┘
```
节点抽屉覆盖在右侧画布之上,不占用第三栏:
```text
┌─────────────────────────────────────────┐
│ 节点名称 关闭 × │
│ 角色 / 当前状态 │
├─────────────────────────────────────────┤
│ 节点职责 │
│ 要根据什么:所需输入、上游类型、资料要求 │
│ 要产出什么:成果类型、格式、验收条件 │
│ 可用工具与边界 │
│ 上下游关系 │
├─────────────────────────────────────────┤
│ 在对话中对此节点提出意见 │
└─────────────────────────────────────────┘
```
抽屉明确不展示实际执行结果、生成正文、工具返回、来源明细、错误堆栈或 attempt 时间线;这些信息只在左侧原生消息流中展示。
布局默认值:
- 顶栏高度:56px。
- 左侧面板:默认 480px,最小 360px,最大 720px。
- 右侧画布:最小 480px,使用剩余空间。
- 节点说明抽屉:覆盖画布右侧,建议宽度 420px;关闭后完整归还画布空间。
- 状态栏:24~28px。
- 低于 960px:左侧对话和右侧画布改为顶部按钮切换的单面板模式;节点说明仍使用覆盖式 Drawer。
- 两栏分隔条:支持 pointer 拖动、方向键、Home、End。
### 4.1 原生消息流与并行智能体切换
“复用 `MessageList`”在本页面的含义是复用它现有的 assistant 文本、`tool_calls`、`tool` 消息、引用、文件和协助卡渲染语义;不把 AgentScope 的运行过程先解析成专用步骤条、进度摘要或阶段结果卡。
单个智能体:
- `agent.reply.started` 立即创建一条稳定的 assistant 消息;`message.delta` 持续更新同一 `messageId`,所以用户会先看到流式状态、再看到逐字回复,而不是等待节点结束。
- 工具调用创建/更新该 assistant 消息的 `tool_calls`;工具返回创建匹配 `tool_call_id` 的原生 `tool` 消息。现有 `MessageGroup` 负责把两者配对显示,不再另写工具过程渲染器。
- AgentScope TeamSay 作为带 `agentRunId` 的普通 assistant 消息进入同一流,按到达顺序显示。它不是节点完成的证据,节点状态仍由右侧画布和后端状态机决定。
并行智能体:
```text
多角度并行研究 3/4 进行中
[ 协调者 ] [ 市场规模 ✓ ] [ 品牌竞争 ● ] [ 海外市场 ● ] [ 政策风险 ! ]
└──────────────────── 当前选中智能体的原生 MessageList ────────────────────┘
```
- `AgentStageSelector` 只在并行阶段出现,横向放置在左侧对话区顶部;使用现有图标体系的头像/角色图标、名称、状态文字和非纯颜色状态标识。默认选中第一位已开始运行的成员;用户手动切换后保持选择,不因其他成员返回而抢走阅读焦点。
- 所有成员的事件都持续接收、按每个 `agentRunId` 持久化和更新,即使当前未选中;切回即可看到完整历史与正在更新的同一条消息,不丢 token、不重新请求、不把结果拼成摘要。
- 当前选择只将共享用户消息、协调者广播消息和目标成员消息组成一个 `BaseStream<AgentThreadState>` 交给同一个 `MessageList`。切换标签仅切换该视图的消息范围,不改变 run、节点或消息的后端事实。
- 某成员请求用户协助时,其标签显示“待回复”徽标,选择器显示待处理数;点击徽标切到该成员,原生协助工具消息仍由现有 `MessageList` 协助卡渲染。其他成员可继续运行。
- 节点抽屉打开某并行成员时,同步聚焦对应标签;抽屉仍只展示合同。用户从抽屉或输入框发送反馈时带 `targetNodeId`/`agentRunId`,后端在安全点生效。
这不是把完整日志另做成调试面板:对话区展示的是模型和工具的真实业务消息;只有 chain-of-thought、内部提示词及按权限必须脱敏的字段不进入该消息流。
### 4.2 页面主要状态
| 状态 | 左侧对话区 | 右侧流程画布 | 主要操作 |
|---|---|---|---|
| `empty` | 欢迎语和输入框 | 空态 | 输入需求、选模板 |
| `clarifying` | 澄清问题和协助卡 | 需求理解节点 | 回答或补充 |
| `planning` | 用户消息和规划进度 | 骨架或需求图 | 继续补充,等待安全点生效 |
| `proposal_ready` | 2~3 张方案卡 | 点击卡片预览对应图 | 切换、修改、采用 |
| `running` | 协调者与成员原生消息、工具过程和用户反馈 | 实时节点状态 | 干预、停止、在对话中要求重跑 |
| `awaiting_input` | 等待用户卡片、原因和影响 | 对应节点显示等待 | 回答、取消 |
| `reviewing` | 审稿意见和返工过程 | 评审/返工节点状态 | 接受或补充要求 |
| `completed` | 总结、报告文件卡、版本和后续对话 | 完整执行图 | 问答、改写、导出 |
| `failed` | 错误说明和恢复建议 | 失败节点 | 通过对话重试或取消 |
| `cancelled` | 已保留成果说明 | 未完成节点取消 | 从已有成果继续或新建方案 |
---
## 5. 前端目录与组件边界
建议新增:
```text
frontend-web/src/report-collaboration/
api/
client.ts
sessions.ts
plans.ts
runs.ts
reports.ts
types.ts
components/
ReportCollaborationLayout.tsx
ReportCollaborationHeader.tsx
ConversationSidebarTabs.tsx
ReportConversationPanel.tsx
AgentStageSelector.tsx
ReportComposer.tsx
ReportPlanCards.tsx
ReportFlowCanvas.tsx
ReportFlowNode.tsx
NodeInspectorDrawer.tsx
ReportPreviewDialog.tsx
InterventionCard.tsx
SessionHistoryPanel.tsx
ConnectionStatusBar.tsx
hooks/
useReportCollaborationSession.ts
useReportCollaborationStream.ts
useReportCollaborationMessages.ts
useReportPlanSelection.ts
useReportPanelLayout.ts
state/
event-normalizer.ts
event-reducer.ts
selectors.ts
message-adapter.ts
pages/
ReportCollaborationPage.tsx
styles/
report-collaboration.css
tests/
```
修改范围:
- `frontend-web/src/pages/WorkspaceRoutes.tsx`:增加页面和会话路由。
- `frontend-web/src/components/workspace/workspace-nav-chat-list.tsx`:增加导航入口。
- `frontend-web/src/components/workspace/messages/message-list.tsx`:仅允许增加一个向后兼容的通用业务卡片插槽。
- `frontend-web/src/core/messages/utils.ts`:如确需识别通用业务卡类型,只做集中式扩展。
不得把新功能放进:
- `frontend-web/src/roundtable-planning/`
- `frontend-web/src/open-canvas/`
- Coze 项目的 `workflow-standalone/`
---
## 6. 数据来源与前端状态
### 6.1 三层状态
前端状态分为:
1. 服务器快照:session、原生 messages、plans、run、nodes、artifacts、report versions;每条消息带稳定的 `agentRunId`、`nodeRunId`、`phaseId` 和可见性标记,其中 artifacts 只用于生成左侧消息卡和报告文件,不形成独立结果面板。
2. durable SSE reducer:从 `seq` 连续应用事件,更新服务器快照投影。
3. 纯展示状态:预览中的方案、选中的节点、聚焦的并行 `agentRunId`、两栏宽度、节点抽屉开关、窄屏当前视图和画布位置。
纯展示状态不能改变执行结果。点击卡片只改变 `previewPlanId`;只有点击“采用方案”才改变服务器 `selectedPlanId`。
### 6.2 前端事件包
```ts
interface CollaborationEvent<T = unknown> {
eventId: string;
sessionId: string;
runId?: string;
seq: number;
type: string;
timestamp: string;
data: T;
}
```
必须处理:
- 快照先到、事件后到。
- 事件重复。
- 事件短暂乱序。
- SSE 断线后从 `after_seq` 重放。
- 页面切换时旧连接晚到事件。
- token delta 多次更新同一消息。
- TeamSay、assistant 文本、tool-call 参数 delta、tool 返回 delta 分别更新各自稳定消息,不得等节点完成后批量生成摘要。
- 并行成员的消息可交错到达;Reducer 必须按 `agentRunId + messageId` 更新,而不是按当前被选中的标签丢弃未聚焦成员的事件。
- 节点重新打开后出现新 attempt。
Reducer 以 `sessionId + runId + seq` 去重;消息行以 `messageId`、工具结果以 `toolCallId`、标签以 `agentRunId` 使用后端稳定 ID,禁止使用数组下标。
---
## 7. 分步实施计划
### FE-0:冻结参考视觉与行为基线
任务:
1. 在 1440×900、1280×800、1024×768 打开参考页面。
2. 保存初始态、方案态、运行态和节点说明抽屉四组截图。
3. 记录顶栏、两栏比例、间距、圆角、边框、阴影、画布工具栏和状态色。
4. 形成“参考组件—目标组件—允许差异”表。
5. 明确消息列表保持 DeerFlow 原样,不纳入像素对齐。
交付物:
- 视觉基线截图。
- 视觉 token 表。
- 页面行为清单。
验收:参考的每个用户可见状态都有截图或明确说明不存在。
### FE-1:路由、菜单和静态页面骨架
任务:
1. 增加两个路由和菜单项。
2. 创建 `ReportCollaborationPage`。
3. 创建顶栏、左侧对话栏、右侧画布和底部连接栏。
4. 实现可调整宽度的两栏布局,以及“专注对话/专注画布”切换。
5. 实现窄屏单面板切换与覆盖式节点 Drawer。
验收:
- 不连接后端也能呈现完整空态。
- 375~1440px 不出现页面级横向滚动。
- 对话/画布切换不会卸载会话状态或清空输入内容。
- 键盘可以调整两栏分隔条。
### FE-2:页面设计系统与 Coze 风格重建
建立页面专用语义变量:
```text
--rc-bg-page
--rc-bg-panel
--rc-bg-canvas
--rc-border
--rc-text-primary
--rc-text-secondary
--rc-accent
--rc-running
--rc-waiting
--rc-success
--rc-danger
--rc-panel-shadow
--rc-card-radius
```
规则:
- 从 DeerFlow 主题 token 派生,不在组件中散落十六进制颜色。
- 使用 Lucide SVG 图标,不使用 emoji。
- hover/focus/展开动画控制在 150~300ms。
- 支持 `prefers-reduced-motion`。
- 交互状态不能只靠颜色表达。
- 正文对比度达到 4.5:1。
- 操作超过 300ms 显示 spinner、骨架或流式状态。
验收:除 MessageList 内部外,两栏布局、密度、卡片、画布工具栏、弹窗和节点抽屉达到参考基线。
### FE-3:API 类型和 TanStack Query 层
实现:
- session CRUD。
- messages 查询与发送。
- plan request、plans 查询、select。
- run 创建、查询、停止、重试。
- command 创建、确认、取消。
- artifacts、sources、reports、versions 查询。
每个写请求携带:
- `idempotencyKey`
- `expectedRevision`
冲突行为:
- `409`:刷新当前快照并提示用户重新确认。
- `422`:在对应操作附近显示具体错误。
- `429`:显示预算/并发限制,不自动重试。
- `5xx`:保留用户输入,允许使用同一幂等键重试。
验收:API 层不包含页面展示逻辑,类型与后端 OpenAPI 一致。
### FE-4:SSE、快照和事件 Reducer
实现 `useReportCollaborationStream`:
1. 先拉 session snapshot。
2. 使用 snapshot 的 `lastSeq` 建立 SSE。
3. 校验每个事件 session/run 身份。
4. 按 seq 应用事件并去重。
5. 出现序号缺口时暂停 live apply,补拉缺失事件。
6. 断线指数退避并支持 `Last-Event-ID`。
7. 终态后完成最后一次事件补拉再关闭连接。
Reducer 必须覆盖:
- 消息流增量。
- 计划候选和 revision。
- node/node attempt 状态。
- artifact 创建和校验。
- command 分类和执行。
- report delta 和正式版本。
- 错误、取消、接管恢复。
- AgentScope 原始可见消息和工具事件:`message.created/delta/completed`、`tool_call.created/delta/completed`、`tool_result.created/delta/completed`、`team_message.created/delta/completed`。
验收:重复事件、乱序事件和重连都不产生重复消息、重复节点或状态倒退。
### FE-5:复用 DeerFlow `MessageList`
复用:
- `frontend-web/src/components/workspace/messages/message-list.tsx`
- `frontend-web/src/components/workspace/messages/message-list-item.tsx`
- `frontend-web/src/components/workspace/messages/message-group.tsx`
- `frontend-web/src/components/workspace/messages/context.ts`
实现无损协议适配 `message-adapter.ts`:
1. 将已持久化的 `CollaborationMessage` 一对一映射为 LangGraph SDK `Message[]`,不将文本或工具结果二次概括。
2. 构造最小 `BaseStream<AgentThreadState>` 外观:`messages`、`isLoading`、`isThreadLoading`、`values`。
3. 协调者、成员 AgentScope TeamSay 和成员回复都映射为普通 assistant 消息;保留 `messageId`、文本 chunk、角色/成员名称、`agentRunId`、`nodeRunId`、`phaseId`、来源事件 ID 和完成态。
4. AgentScope 工具调用映射为该 assistant 消息的标准 `tool_calls`;调用结果映射为标准 `tool` 消息,并严格复用原有 `tool_call_id` 配对。工具参数、返回正文及增量保持原文,只有后端明确标注的脱敏字段被替换。
5. 将来源、文件、报告 Markdown delta 和正式版本继续映射为既有引用、文件卡和普通 assistant 消息;规划卡、用户确认卡和报告替换卡仍通过一个通用业务卡片插槽渲染。
6. 错误、恢复建议、命令影响范围和报告版本变化也必须进入同一时间线;错误堆栈以可读错误消息替代,但不能吞掉已发生的工具/成员消息。
7. `selectMessagesForAgentRun(allMessages, focusedAgentRunId)` 只在客户端从已同步消息中选出共享消息与目标成员消息;并行选择器不得重新拉取、重新排序或改写消息。
约束:
- 不使用 LangGraph `useThreadStream` 发送消息。
- 新页面输入框调用报告协作 API。
- 不增加多个页面专用 MessageList props。
- 普通聊天、AI 写作、深度研究等未传插槽时必须零变化。
- 不另建执行结果列表、节点结果面板或成果时间线。
- 不用“运行中”“已检索 N 条”等专用摘要替代真实消息。`MessageList` 本身的流式状态和原生工具步骤是唯一过程视图。
验收:
- 历史和流式消息使用同一行稳定更新。
- 单成员首次开始回复、每次工具启动和工具返回均在 300ms 内出现可见的原生消息行或原生工具步骤;不允许持续数秒只有静态加载圈。
- 并行标签切换后显示目标成员的完整已持久化消息和实时 delta;未选中成员持续接收,标签上的运行/待回复状态及时更新。
- 用户上翻阅读时不强制滚底。
- 用户发送新消息后滚到最新位置。
- 卡片显示成功不改变后端节点状态。
### FE-6:需求澄清和候选方案卡片
`ReportPlanCards` 展示:
- 推荐标签、策略、标题、摘要和推荐理由。
- 分析角度和参与角色。
- 关键步骤与质量门。
- 预计时间、成本等级和资料范围。
- 方案验证错误。
交互:
- 点击卡片或“查看流程”只切换预览。
- “采用此方案”调用 select API。
- “开始协作”再次校验并创建 run。
- 方案调整后显示新 revision;旧 revision 只读。
- 过期 revision 返回 409 后不静默覆盖。
验收:连续快速切换三张卡时,画布最终显示最后一次选择,不闪回旧图。
### FE-7:协作流程画布
技术:`@xyflow/react`。可以借鉴但不直接耦合:
- `frontend-web/src/components/ai-elements/canvas.tsx`
- `frontend-web/src/roundtable-planning/components/FlowGraphPanel.tsx`
节点显示:
- 节点名、角色名和分析角度。
- 状态文字、图标和颜色。
- 等待用户、返工、失败和 superseded 标记。
画布能力:
- 自动布局。
- 拖动节点只保存浏览器展示位置。
- 缩放、适配视图、方向切换、小地图。
- 活动边低强度流动动画。
- 点击节点打开覆盖在画布上的节点说明抽屉。
- 节点重跑、补充或纠偏一律通过左侧对话完成;抽屉只提供“在对话中对此节点提出意见”入口。
- 方案切换后清理不属于新方案的本地坐标。
验收:
- 30 个节点内流畅操作。
- 单个 node event 不导致整个 React Flow 重挂。
- `awaiting_input`、`reopened`、`superseded` 不与 `completed` 混淆。
### FE-8:节点说明抽屉与对话定位
点击画布节点打开 `NodeInspectorDrawer`。抽屉只展示计划合同:
1. 节点名称、角色、分析角度和当前状态标签。
2. 节点职责:负责解决什么问题。
3. 要根据什么:所需输入类型、上游节点类型、资料范围和时效要求。
4. 要产出什么:成果类型、结构要求和验收条件。
5. 可用工具、禁止事项、预算上限。
6. 上游与下游关系。
抽屉不展示:
- 节点实际生成内容。
- 工具调用返回值。
- EvidenceBundle 或其他成果物正文。
- attempt 执行时间线。
- 错误堆栈和调试信息。
- 报告正文。
交互:
- “在对话中对此节点提出意见”关闭抽屉、聚焦左侧 Composer,并绑定 `targetNodeId` 上下文。
- 若该节点对应正在并行运行的成员,同时绑定该成员的 `agentRunId` 并切换左侧选择器,使用户发送前能先看到该成员的真实对话与工具过程。
- 用户仍需在对话区输入“重新检索”“重新分析”等要求;抽屉不直接发起业务变更。
- 状态标签来自后端节点状态,但不加载节点结果接口。
- 关闭抽屉不清空 selected node;再次点击同一节点可恢复说明。
报告预览不使用常驻第三栏。最终报告、章节候选和版本先作为左侧 MessageList 中的普通消息/文件卡出现;点击文件卡时复用 `ArtifactFileDetail` 或现有 Markdown 能力打开大尺寸 Dialog,关闭后回到两栏工作台。
验收:
- 抽屉宽度不改变两栏布局,不挤压左侧对话区。
- 抽屉只读取节点合同和图结构,不请求节点执行结果。
- 所有原生成员消息、工具过程、错误和报告入口都能在左侧对话时间线找到。
### FE-9:全过程对话干预
`ReportComposer` 根据状态显示不同提示:
- 空闲:输入报告需求。
- 规划中:补充要求将在规划安全点应用。
- 运行中:协调者正在判断影响范围。
- 等待用户:优先回答等待问题。
- 完成后:可问答、重写、润色或重新研究。
发送流程:
1. 生成 idempotency key。
2. 插入 pending 用户消息;带 `targetNodeId`/`agentRunId` 时在相关成员消息流和共享上下文中引用同一条用户消息,不重复持久化。
3. 显示“正在识别修改范围”。
4. `command.classified` 后展示意图和影响节点。
5. 高成本或低置信度命令显示确认卡。
6. `command.accepted` 后显示排队或等待安全点。
7. 完成后关联新 node attempt 或 report version。
8. 失败时保留原消息和重试入口。
典型映射:
| 用户输入 | 预期操作 |
|---|---|
| “增加政策风险角度” | 新增角度节点和受影响下游 |
| “资料太旧,重新找” | 重新检索指定证据包 |
| “竞争格局分析不到位” | 复用证据,重新分析 |
| “重写第二章” | 只生成章节替换候选 |
| “语气更正式” | 新报告版本,不重新研究 |
| “为什么得出这个结论” | 只读问答,不修改报告 |
验收:
- 双击发送不创建重复命令。
- 选中“品牌竞争分析师”后发送补充要求,只影响该成员及依赖分析,其他并行成员仍保持消息流和运行状态。
- 运行中反馈不会让 run 或 node 误变 completed。
- “重写第二章”不会触发全量检索。
- “资料太旧”不会只做文字润色。
### FE-10:会话历史、报告版本与导出
- History Tab 显示标题、状态、更新时间、当前版本。
- 新建会话不删除旧会话。
- 会话切换时先关闭旧 SSE,再加载新快照。
- 报告修改先生成候选,确认后创建新版本。
- 版本恢复创建新的头版本,不删除历史。
- 下载复用现有 Markdown/Word 能力。
- 文件名来自报告标题,不暴露宿主机或沙箱路径。
验收:历史会话可完整恢复左侧消息流程、右侧节点状态和报告版本;不额外恢复节点结果面板。
### FE-11:测试、视觉回归和性能
单元测试:
- event normalizer/reducer。
- message adapter。
- plan revision 和选择状态。
- node status 和 available actions。
- command pending/idempotency。
组件测试:
- 空态、澄清、规划、候选、运行、等待、完成、失败、取消。
- 卡片选择、节点点击、只读说明 Drawer、确认弹窗和报告预览 Dialog。
- MessageList 通用业务卡插槽零回归。
- 单成员流式文本、TeamSay、工具调用与工具返回的原样重放;并行成员交错到达、切换标签、切回后不中断 delta。
- 非当前标签成员发起协助时显示待回复徽标,点击后使用原生协助卡回复到正确节点。
E2E:
1. 新建会话并输入新能源汽车报告要求。
2. 选择候选并开始。
3. 运行中增加风险角度。
4. 重新检索海外最新资料。
5. 完成后重写第二章。
6. 刷新、断网重连、切换会话。
7. 停止和重试失败节点。
性能门:
- 30 节点画布不卡顿。
- 长消息列表使用现有优化策略。
- SSE 高频 delta 合帧后再 setState。
- 画布和消息区使用独立 selector,避免互相触发整树重渲染。
- 节点抽屉只订阅节点合同和状态,不能因阶段产出更新而反复重渲染。
- 只渲染当前聚焦成员和共享消息的可视窗口;非当前成员的消息仍写入 store,但不因 token delta 重渲染当前 `MessageList`。
---
## 8. 后端接口依赖
前端开发前,后端必须冻结以下接口:
```text
POST /api/report-collaboration/sessions
GET /api/report-collaboration/sessions
GET /api/report-collaboration/sessions/{session_id}
PATCH /api/report-collaboration/sessions/{session_id}
DELETE /api/report-collaboration/sessions/{session_id}
POST /api/report-collaboration/sessions/{session_id}/messages
GET /api/report-collaboration/sessions/{session_id}/messages
POST /api/report-collaboration/sessions/{session_id}/plan-requests
GET /api/report-collaboration/sessions/{session_id}/plans
POST /api/report-collaboration/sessions/{session_id}/plans/{plan_id}/select
POST /api/report-collaboration/sessions/{session_id}/runs
GET /api/report-collaboration/runs/{run_id}
GET /api/report-collaboration/runs/{run_id}/events
GET /api/report-collaboration/runs/{run_id}/stream
POST /api/report-collaboration/runs/{run_id}/commands
POST /api/report-collaboration/runs/{run_id}/cancel
GET /api/report-collaboration/runs/{run_id}/nodes/{node_id}/contract
GET /api/report-collaboration/sessions/{session_id}/reports
POST /api/report-collaboration/sessions/{session_id}/report-rewrites
POST /api/report-collaboration/sessions/{session_id}/report-rewrites/{id}/apply
```
前后端共享枚举:
- session status。
- run status。
- node/node attempt status。
- command intent/status。
- event type/version。
- artifact type/schema version。
- report version/change type。
---
## 9. 前端开发顺序
页面与契约层已完成(代码在 `frontend-web/src/report-collaboration/`):
1. `RC-FE-001`:视觉截图与行为基线。
2. `RC-FE-002`:路由、菜单和左对话/右画布两栏空壳。
3. `RC-FE-003`:页面 token、弹窗、抽屉和响应式。
4. `RC-FE-004`:API 类型和 mock server。
5. `RC-FE-005`:SSE reducer 与快照恢复。
6. `RC-FE-006`:MessageList adapter 和通用卡片插槽。
7. `RC-FE-007`:需求澄清与候选方案卡。
8. `RC-FE-008`:流程画布和自定义节点。
9. `RC-FE-009`:只读节点说明抽屉与对话目标定位。
10. `RC-FE-010`:统一 Composer 和命令确认。
11. `RC-FE-011`:报告预览、版本和导出。
12. `RC-FE-012`:历史、重连和异常恢复。
13. `RC-FE-013`:组件/E2E/视觉/性能验收。
依赖规则:
- 契约已冻结为 `src/report-collaboration/api/types.ts`;后端 `RC-BE-001` 已对齐。
- 真实 SSE 联调:后端 `RC-BE-011` 已挂载 `GET /runs/{id}/stream`;默认无后台循环时流只会重放已入库事件。
- 报告版本操作已接后端 `RC-BE-015`(改写候选 / apply / restore)。
- 执行画布实时状态依赖打开 `worker_enabled`;质量角色内核已在 `RC-BE-013` 落地,真实成员见 `RC-BE-017`。
---
## 10. 前端完成定义
页面与 mock 联调路径已落地。真实后端可联调 `GET /runs/{id}/stream`、领取/恢复(`RC-BE-012`,默认不挂 worker)、质量角色(`RC-BE-013`)以及报告改写/恢复(`RC-BE-015`)。此前以 mock driver 覆盖交互,不以「前端未编码」计未完成。
前端只有同时满足以下条件才算完成:
1. 页面结构与 Coze 参考页面逐状态验收通过。
2. 消息区复用 DeerFlow `MessageList`,其他聊天页面无回归。
3. 候选卡、左侧对话流程、右侧流程图和报告来自同一 session/run/event 状态。
4. 点击候选只预览,明确确认后才执行。
5. 用户可以在规划、运行、完成后三个阶段继续对话。
6. 协助卡显示或提交不会导致前端误标完成。
7. 节点点击只打开说明抽屉,可查看职责、所需输入、预期输出、工具和验收条件,不展示执行结果。
8. 节点重开、返工和 superseded 状态表达正确。
9. SSE 重连、刷新和历史切换无重复消息和状态倒退。
10. 报告修改以候选和版本形式完成,不直接覆盖正式报告。
11. 页面始终只有对话与画布两个常驻区域,所有执行过程和产出入口都能在对话时间线中找到。
12. 响应式、键盘、对比度、加载反馈和错误恢复通过验收。