diff --git a/docs/plans/2026-05-12-dashboard-workflow-graph.md b/docs/plans/2026-05-12-dashboard-workflow-graph.md index c88bd67..c58c0aa 100644 --- a/docs/plans/2026-05-12-dashboard-workflow-graph.md +++ b/docs/plans/2026-05-12-dashboard-workflow-graph.md @@ -1,68 +1,53 @@ # Dashboard Workflow Graph Visualization **Issue**: #198 -**Status**: Draft +**Status**: In Progress **Author**: xingyue ## Overview 在 Dashboard 的 ThreadDetail 页面中嵌入一个交互式流程图,将 workflow 的 `ModeratorTable` 可视化为有向图。用户可以一眼看到角色流转结构和当前执行进度。 -## 数据流 +## 数据层(✅ 已完成 — PR #201) -### 问题:ModeratorTable 在 bundle 端,Dashboard 在前端 +### WorkflowGraph 类型 -`ModeratorTable` 是运行时数据结构(包含 JS 函数引用如 `check`),无法直接序列化给前端。需要一个**静态图描述格式**作为中间层。 - -### 方案:扩展 WorkflowDescriptor - -当前 `WorkflowDescriptor` 只有 roles + description,不包含转换图信息: +`WorkflowDefinition.moderator`(函数)已替换为 `WorkflowDefinition.table`(声明式 `ModeratorTable`),`buildDescriptor` 自动从 table 提取 graph: ```ts -type WorkflowDescriptor = { - description: string; - roles: Record; -}; -``` - -**扩展为**: - -```ts -type TransitionEdge = { - condition: string; // condition.name,或 "FALLBACK" - description: string | null; // condition.description,FALLBACK 为 null - target: string; // role name 或 "__end__" +type WorkflowGraphEdge = { + from: string; // source role 或 "__start__" + to: string; // target role 或 "__end__" + condition: string; // condition.name 或 "FALLBACK" + conditionDescription: string | null; }; -type WorkflowGraph = Record; -// key = source role name 或 "__start__" +type WorkflowGraph = { + edges: readonly WorkflowGraphEdge[]; +}; type WorkflowDescriptor = { description: string; roles: Record; - graph: WorkflowGraph | null; // null = legacy bundles without graph + graph: WorkflowGraph; // 必填,新 bundle 自动生成 }; ``` -在 `buildDescriptor`(`workflow-register`)中,从 `ModeratorTable` 提取静态图结构。`condition.check` 函数不序列化,只保留 `name` 和 `description`。 - -### 数据暴露路径 +### 数据流 ``` -ModeratorTable (runtime) - → buildDescriptor() 提取 graph - → descriptor.yaml 持久化 - → CLI serve /workflows API 返回 +ModeratorTable (WorkflowDefinition.table) + → buildDescriptor() 自动提取 graph + → descriptor.yaml 持久化(hash.yaml) + → CLI serve /workflows/:name API 返回 descriptor → Dashboard 前端拿到 graph ``` -同时需要新增或扩展一个 API,让 Dashboard 能拿到指定 workflow 的 descriptor(含 graph): +### 剩余数据层工作 -``` -GET /workflows/:name → { descriptor: WorkflowDescriptor } -``` +**serve API 需要返回 descriptor**:当前 `GET /workflows/:name` 只返回 registry entry(hash + timestamp),不含 descriptor。需要从 `bundles/{hash}.yaml` 读取 descriptor 并返回给前端。 -或者在现有 `listWorkflows` 返回中附带。 +方案:在 `routes-workflow.ts` 的 `GET /workflows/:name` 响应中附带 `descriptor` 字段。或者:thread-detail 发现 workflow name 后,请求 `GET /workflows/:name/descriptor` 拿到 graph。 ## 前端渲染 @@ -87,17 +72,17 @@ GET /workflows/:name → { descriptor: WorkflowDescriptor } ### 图结构映射 ``` -WorkflowGraph → React Flow nodes + edges +WorkflowGraph.edges → React Flow nodes + edges -节点: +节点(自动从 edges 推导): - __start__ → 圆形小节点(入口) - role → 圆角矩形,显示 role name + description - __end__ → 圆形小节点(终止) 边: - FALLBACK → 虚线(dashed),无 label - - condition → 实线,label = condition.name - hover tooltip = condition.description + - condition → 实线,label = condition + hover tooltip = conditionDescription ``` ### 布局 @@ -172,7 +157,7 @@ function getNodeStates(records: ThreadRecord[]): Map