feat(flow,web): 全链路可视化 P2 — 泳道/并行分支 + 节点活动状态 + 节点实时日志
- 后端 trace/graph.go(395→470):泳道感知游标 —— parents 记住被跳过容器(state_transition)的父链、laneLast 按泳道分别的末节点游标;泳道首节点挂 subagent 根、后续步骤在本泳道内串链;**子代理根不再推进主干游标**(否则 spawn 之后的主干节点会被算成最后一条分支的步骤);node kind 抽具名常量。+ graph_lane_test.go(并行双泳道断言精确边集/嵌套泳道/主干游标不回归/laneOf 环保护)
- 前端新增 flow/{tone,lanes,layout,NodeDetail,LaneSummary}:分组=沿入边反向 BFS 取最近 kind=subagent 祖先(纯 edges,故无需新增 wire 字段);布局=主干沿用 P1 最长路径分层 + 每泳道一条独立横带(带内最长路径深度、逐带下推 y 不重叠、横向滚动);Flow.tsx/FlowGraph.tsx 加泳道框/虚线泳道边/运行闪烁(既有 mu-blink)/选中高亮/图例
- 实时日志:选中态按 node id 保存,随每帧 graph_update 重新 find → 自动显示追加后的 log[];空时区分「运行中(事件随 span 结束回填)」与「未记录事件」,不合成事件
- 未新增 wire 字段 → 无契约变化(因此未动 lib/types.ts / wsParse.ts);<FlowGraphView> 旧签名兼容,Agents/Backthink 页不受影响
- 验收:go build/vet/test 全绿 + linux/darwin 交叉编译 + npm run build(177 模块) + 逻辑测试 lanes 40 / channelStatus 45 / enums 47 / messageSync 54
- ⚠️ 已核实、未伪造的缺口:生产路径当前产不出子代理数据 —— Scheduler.Spawn 全仓仅测试调用方(0 生产)、编排包无 bus 订阅入口、无「派子代理」工具/capability → 泳道要真的亮需先接线;Span.Record 同样无生产调用方 → log[] 恒空(UI 已诚实显示空态)
This commit is contained in:
1 parent
49d12d9a64
commit
2c100fe3d9
10 files changed
+1532
-338
No files matched your search
@@ -0,0 +1,59 @@
|
||||
import type { AgentStatus, FlowNode } from "../../../lib/types";
|
||||
import type { TagTone } from "../../../components/primitives";
|
||||
|
||||
/** Miuix status presentation for flow nodes (design/19 §2: 节点闪烁=运行中、
|
||||
* ok=成功、err=失败). The stroke/fill colors are Miuix tokens so the graph
|
||||
* follows the panel theme (light/dark) without hard-coded colors. */
|
||||
export interface FlowTone {
|
||||
stroke: string;
|
||||
fill: string;
|
||||
label: string;
|
||||
tag: TagTone;
|
||||
}
|
||||
|
||||
export const FLOW_TONE: Record<AgentStatus, FlowTone> = {
|
||||
idle: {
|
||||
stroke: "var(--mu-surface-5)",
|
||||
fill: "color-mix(in srgb, var(--mu-surface-5) 18%, transparent)",
|
||||
label: "空闲",
|
||||
tag: "neutral",
|
||||
},
|
||||
running: {
|
||||
stroke: "var(--mu-accent)",
|
||||
fill: "color-mix(in srgb, var(--mu-accent) 18%, transparent)",
|
||||
label: "运行中",
|
||||
tag: "accent",
|
||||
},
|
||||
blocked: {
|
||||
stroke: "var(--mu-warn)",
|
||||
fill: "color-mix(in srgb, var(--mu-warn) 18%, transparent)",
|
||||
label: "阻塞",
|
||||
tag: "warn",
|
||||
},
|
||||
done: {
|
||||
stroke: "var(--mu-ok)",
|
||||
fill: "color-mix(in srgb, var(--mu-ok) 18%, transparent)",
|
||||
label: "完成",
|
||||
tag: "ok",
|
||||
},
|
||||
error: {
|
||||
stroke: "var(--mu-err)",
|
||||
fill: "color-mix(in srgb, var(--mu-err) 18%, transparent)",
|
||||
label: "错误",
|
||||
tag: "err",
|
||||
},
|
||||
};
|
||||
|
||||
/** Legend / aggregate order, coldest to most alarming. */
|
||||
export const STATUS_ORDER: ReadonlyArray<AgentStatus> = [
|
||||
"idle",
|
||||
"running",
|
||||
"blocked",
|
||||
"done",
|
||||
"error",
|
||||
];
|
||||
|
||||
/** statusOf narrows a node's optional status to a concrete AgentStatus. */
|
||||
export function statusOf(node: FlowNode): AgentStatus {
|
||||
return node.status ?? "idle";
|
||||
}
|
||||
Reference in new issue
Block a user