DAG 实时布局(真算法)

不是写死坐标的示意图。这里内置了和后端 graph_layout 一致的布局算法 (lane / tier / depth + 占列规则),喂节点数据 → 算法自己算出每个节点的位置 → 画出来。 切换下面的场景看不同数据跑出来的布局。通信线默认隐藏,鼠标移到图上才显示。

节点:◇ ROOT  ○ user  △ llm  □ code  ◉ merge
颜色 = 分支身份(每条 lane 一色)
线型 = 连线类型:
 ━ 同分支  - - retry  -·- spawn  ··· 通信(hover)  ═ 合并  ┄ attach
列规则:fork 占两列(竖线列 + 节点列)

设计原则(DAG 怎么画 —— 全部规则)

1. 连线:每个节点连它的父,先往下、再往右

唯一的连线规则:每个节点连它的【父】,从父先往下(父正下方画竖线到子的行)、再往右(横到子)。所有连线都这样,没有例外。

2. 节点形状 = 角色

◇ ROOT(菱形,白填充) · ○ user(真人用户消息,圆) · △ llm(AI / agent 消息,三角) · □ code(工具 / 函数调用,方块) · ◉ merge(合并汇聚点,实心带孔圆)。
agent 之间发来的消息是 △(三角),不是 ○——圆只给真人用户。

3. 颜色 = 分支身份(不表示线的类型)

每条 lane(分支)一个颜色。任何线都用它所属/指向分支的 lane 颜色。绝不用颜色区分线的类型——那会和"颜色=分支"冲突。

4. 线型 = 连线类型(颜色之外的另一维,正交)

5. 列(lane / tier)

6. 行(depth)= 时间序

按全局 created_at(seq)排,早发生的在上。所以一条已存在的分支(如被通信的 B)排在引用它的操作(send)之前,不会被画成"通信时才新建"。retry 的兄弟对齐到同一行(同一时刻的平行可能)。

7. 分支间通信(agent ↔ agent)—— 异步

不是同步阻塞(那会让 A 干等 B、两条并行分支变串行甚至死锁)。是异步,像"派后台 agent 干活 + 还能继续聊天":

8. 分支合并 / 子分支服务

9. 软连接线:默认隐藏,hover 端点才显示 + 动画

调用线(同分支 / retry / spawn —— 结构骨架)常驻显示。
软连接线(通信 send→收到、返回 应答→回复了、merge 汇入、attach 回流 —— 凡是跨分支的"谁连了谁")默认全部隐藏:只有鼠标放到这条线连接的两个端点节点中的任意一个上时,这条线才显示出来,并带流动动画(虚线流动,表示方向)。移开就隐藏。
理由:这类线会非常多,常驻会把图糊成一团;按需 hover 显示,既不挡视线又能查"这个节点连去了哪"。

10. 本图是什么

不是写死坐标的示意图。这里内置了和后端 graph_layout 一致的布局算法(lane/tier/depth + 占列规则),喂节点数据 → 算法自己算出每个节点的位置 → 画出来。上方切换场景看不同数据跑出来的真实布局。