footprint-explainable-ui 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +1 -0
  2. package/dist/flowchart.cjs +1366 -343
  3. package/dist/flowchart.cjs.map +1 -1
  4. package/dist/flowchart.d.cts +513 -6
  5. package/dist/flowchart.d.ts +513 -6
  6. package/dist/flowchart.js +1257 -262
  7. package/dist/flowchart.js.map +1 -1
  8. package/dist/index.cjs +941 -436
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +6 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +852 -352
  13. package/dist/index.js.map +1 -1
  14. package/package.json +10 -3
  15. package/dist/adapters/fromRuntimeSnapshot.d.ts +0 -81
  16. package/dist/adapters/fromRuntimeSnapshot.d.ts.map +0 -1
  17. package/dist/adapters/fromRuntimeSnapshot.js +0 -226
  18. package/dist/adapters/fromRuntimeSnapshot.js.map +0 -1
  19. package/dist/components/ExplainableShell/ExplainableShell.d.ts +0 -169
  20. package/dist/components/ExplainableShell/ExplainableShell.d.ts.map +0 -1
  21. package/dist/components/ExplainableShell/ExplainableShell.js +0 -702
  22. package/dist/components/ExplainableShell/ExplainableShell.js.map +0 -1
  23. package/dist/components/ExplainableShell/index.d.ts +0 -3
  24. package/dist/components/ExplainableShell/index.d.ts.map +0 -1
  25. package/dist/components/ExplainableShell/index.js +0 -2
  26. package/dist/components/ExplainableShell/index.js.map +0 -1
  27. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts +0 -11
  28. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts.map +0 -1
  29. package/dist/components/FlowchartView/SubflowBreadcrumb.js +0 -49
  30. package/dist/components/FlowchartView/SubflowBreadcrumb.js.map +0 -1
  31. package/dist/components/FlowchartView/SubflowTree.d.ts +0 -29
  32. package/dist/components/FlowchartView/SubflowTree.d.ts.map +0 -1
  33. package/dist/components/FlowchartView/SubflowTree.js +0 -153
  34. package/dist/components/FlowchartView/SubflowTree.js.map +0 -1
  35. package/dist/components/FlowchartView/index.d.ts +0 -39
  36. package/dist/components/FlowchartView/index.d.ts.map +0 -1
  37. package/dist/components/FlowchartView/index.js +0 -26
  38. package/dist/components/FlowchartView/index.js.map +0 -1
  39. package/dist/components/FlowchartView/useSubflowNavigation.d.ts +0 -60
  40. package/dist/components/FlowchartView/useSubflowNavigation.d.ts.map +0 -1
  41. package/dist/components/FlowchartView/useSubflowNavigation.js +0 -99
  42. package/dist/components/FlowchartView/useSubflowNavigation.js.map +0 -1
  43. package/dist/components/GanttTimeline/GanttTimeline.d.ts +0 -18
  44. package/dist/components/GanttTimeline/GanttTimeline.d.ts.map +0 -1
  45. package/dist/components/GanttTimeline/GanttTimeline.js +0 -123
  46. package/dist/components/GanttTimeline/GanttTimeline.js.map +0 -1
  47. package/dist/components/GanttTimeline/index.d.ts +0 -3
  48. package/dist/components/GanttTimeline/index.d.ts.map +0 -1
  49. package/dist/components/GanttTimeline/index.js +0 -2
  50. package/dist/components/GanttTimeline/index.js.map +0 -1
  51. package/dist/components/MemoryInspector/MemoryInspector.d.ts +0 -19
  52. package/dist/components/MemoryInspector/MemoryInspector.d.ts.map +0 -1
  53. package/dist/components/MemoryInspector/MemoryInspector.js +0 -118
  54. package/dist/components/MemoryInspector/MemoryInspector.js.map +0 -1
  55. package/dist/components/MemoryInspector/index.d.ts +0 -3
  56. package/dist/components/MemoryInspector/index.d.ts.map +0 -1
  57. package/dist/components/MemoryInspector/index.js +0 -2
  58. package/dist/components/MemoryInspector/index.js.map +0 -1
  59. package/dist/components/NarrativeLog/NarrativeLog.d.ts +0 -15
  60. package/dist/components/NarrativeLog/NarrativeLog.d.ts.map +0 -1
  61. package/dist/components/NarrativeLog/NarrativeLog.js +0 -65
  62. package/dist/components/NarrativeLog/NarrativeLog.js.map +0 -1
  63. package/dist/components/NarrativeLog/index.d.ts +0 -3
  64. package/dist/components/NarrativeLog/index.d.ts.map +0 -1
  65. package/dist/components/NarrativeLog/index.js +0 -2
  66. package/dist/components/NarrativeLog/index.js.map +0 -1
  67. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts +0 -13
  68. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts.map +0 -1
  69. package/dist/components/NarrativeTrace/NarrativeTrace.js +0 -134
  70. package/dist/components/NarrativeTrace/NarrativeTrace.js.map +0 -1
  71. package/dist/components/NarrativeTrace/index.d.ts +0 -3
  72. package/dist/components/NarrativeTrace/index.d.ts.map +0 -1
  73. package/dist/components/NarrativeTrace/index.js +0 -2
  74. package/dist/components/NarrativeTrace/index.js.map +0 -1
  75. package/dist/components/ResultPanel/ResultPanel.d.ts +0 -11
  76. package/dist/components/ResultPanel/ResultPanel.d.ts.map +0 -1
  77. package/dist/components/ResultPanel/ResultPanel.js +0 -54
  78. package/dist/components/ResultPanel/ResultPanel.js.map +0 -1
  79. package/dist/components/ResultPanel/index.d.ts +0 -3
  80. package/dist/components/ResultPanel/index.d.ts.map +0 -1
  81. package/dist/components/ResultPanel/index.js +0 -2
  82. package/dist/components/ResultPanel/index.js.map +0 -1
  83. package/dist/components/ScopeDiff/ScopeDiff.d.ts +0 -17
  84. package/dist/components/ScopeDiff/ScopeDiff.d.ts.map +0 -1
  85. package/dist/components/ScopeDiff/ScopeDiff.js +0 -87
  86. package/dist/components/ScopeDiff/ScopeDiff.js.map +0 -1
  87. package/dist/components/ScopeDiff/index.d.ts +0 -3
  88. package/dist/components/ScopeDiff/index.d.ts.map +0 -1
  89. package/dist/components/ScopeDiff/index.js +0 -2
  90. package/dist/components/ScopeDiff/index.js.map +0 -1
  91. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts +0 -17
  92. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts.map +0 -1
  93. package/dist/components/SnapshotPanel/SnapshotPanel.js +0 -85
  94. package/dist/components/SnapshotPanel/SnapshotPanel.js.map +0 -1
  95. package/dist/components/SnapshotPanel/index.d.ts +0 -3
  96. package/dist/components/SnapshotPanel/index.d.ts.map +0 -1
  97. package/dist/components/SnapshotPanel/index.js +0 -2
  98. package/dist/components/SnapshotPanel/index.js.map +0 -1
  99. package/dist/components/StageNode/StageNode.d.ts +0 -52
  100. package/dist/components/StageNode/StageNode.d.ts.map +0 -1
  101. package/dist/components/StageNode/StageNode.js +0 -314
  102. package/dist/components/StageNode/StageNode.js.map +0 -1
  103. package/dist/components/StageNode/index.d.ts +0 -3
  104. package/dist/components/StageNode/index.d.ts.map +0 -1
  105. package/dist/components/StageNode/index.js +0 -2
  106. package/dist/components/StageNode/index.js.map +0 -1
  107. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts +0 -13
  108. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts.map +0 -1
  109. package/dist/components/TimeTravelControls/TimeTravelControls.js +0 -120
  110. package/dist/components/TimeTravelControls/TimeTravelControls.js.map +0 -1
  111. package/dist/components/TimeTravelControls/index.d.ts +0 -3
  112. package/dist/components/TimeTravelControls/index.d.ts.map +0 -1
  113. package/dist/components/TimeTravelControls/index.js +0 -2
  114. package/dist/components/TimeTravelControls/index.js.map +0 -1
  115. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts +0 -33
  116. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts.map +0 -1
  117. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js +0 -119
  118. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js.map +0 -1
  119. package/dist/components/TimeTravelDebugger/index.d.ts +0 -3
  120. package/dist/components/TimeTravelDebugger/index.d.ts.map +0 -1
  121. package/dist/components/TimeTravelDebugger/index.js +0 -2
  122. package/dist/components/TimeTravelDebugger/index.js.map +0 -1
  123. package/dist/flowchart.d.ts.map +0 -1
  124. package/dist/index.d.ts.map +0 -1
  125. package/dist/theme/ThemeProvider.d.ts +0 -27
  126. package/dist/theme/ThemeProvider.d.ts.map +0 -1
  127. package/dist/theme/ThemeProvider.js +0 -30
  128. package/dist/theme/ThemeProvider.js.map +0 -1
  129. package/dist/theme/index.d.ts +0 -9
  130. package/dist/theme/index.d.ts.map +0 -1
  131. package/dist/theme/index.js +0 -6
  132. package/dist/theme/index.js.map +0 -1
  133. package/dist/theme/presets.d.ts +0 -18
  134. package/dist/theme/presets.d.ts.map +0 -1
  135. package/dist/theme/presets.js +0 -92
  136. package/dist/theme/presets.js.map +0 -1
  137. package/dist/theme/styles.d.ts +0 -32
  138. package/dist/theme/styles.d.ts.map +0 -1
  139. package/dist/theme/styles.js +0 -37
  140. package/dist/theme/styles.js.map +0 -1
  141. package/dist/theme/tokens.d.ts +0 -49
  142. package/dist/theme/tokens.d.ts.map +0 -1
  143. package/dist/theme/tokens.js +0 -79
  144. package/dist/theme/tokens.js.map +0 -1
  145. package/dist/tsconfig.tsbuildinfo +0 -1
  146. package/dist/types.d.ts +0 -60
  147. package/dist/types.d.ts.map +0 -1
  148. package/dist/types.js +0 -2
  149. package/dist/types.js.map +0 -1
package/dist/flowchart.js CHANGED
@@ -201,6 +201,27 @@ function StageIcon({ type, color }) {
201
201
  /* @__PURE__ */ jsx2("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
202
202
  /* @__PURE__ */ jsx2("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
203
203
  ] });
204
+ // System prompt — document with lines
205
+ case "system-prompt":
206
+ case "prompt":
207
+ case "instructions":
208
+ case "document":
209
+ return /* @__PURE__ */ jsxs("svg", { ...props, children: [
210
+ /* @__PURE__ */ jsx2("rect", { x: "3.5", y: "2", width: "9", height: "12", rx: "1.5", stroke: color, strokeWidth: "1.3", fill: "none" }),
211
+ /* @__PURE__ */ jsx2("line", { x1: "5.5", y1: "5", x2: "10.5", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
212
+ /* @__PURE__ */ jsx2("line", { x1: "5.5", y1: "7.5", x2: "10.5", y2: "7.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
213
+ /* @__PURE__ */ jsx2("line", { x1: "5.5", y1: "10", x2: "8.5", y2: "10", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
214
+ ] });
215
+ // Messages / conversation — chat bubble
216
+ case "messages":
217
+ case "chat":
218
+ case "conversation":
219
+ return /* @__PURE__ */ jsxs("svg", { ...props, children: [
220
+ /* @__PURE__ */ jsx2("rect", { x: "2.5", y: "3", width: "11", height: "8", rx: "2", stroke: color, strokeWidth: "1.3", fill: "none" }),
221
+ /* @__PURE__ */ jsx2("path", { d: "M5.5 11L5.5 13.5L8.5 11", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
222
+ /* @__PURE__ */ jsx2("line", { x1: "5", y1: "6", x2: "11", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
223
+ /* @__PURE__ */ jsx2("line", { x1: "5", y1: "8.5", x2: "9", y2: "8.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
224
+ ] });
204
225
  // Loop — circular arrow
205
226
  case "loop":
206
227
  case "retry":
@@ -251,20 +272,29 @@ var StageNode = memo(function StageNode2({
251
272
  injectedRef.current = true;
252
273
  }, []);
253
274
  const isOnPath = active || done;
254
- const bg = active ? theme.primary : done ? theme.success : error ? theme.error : theme.bgSecondary;
255
- const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : theme.border;
256
- const shadow = active ? `0 0 16px color-mix(in srgb, ${theme.primary} 40%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
275
+ const isHero = data.emphasis === "hero";
276
+ const isMuted = data.emphasis === "muted";
277
+ const sizeScale = data.size === "lg" ? 1.3 : data.size === "sm" ? 0.85 : 1;
278
+ const restingBg = isHero ? `color-mix(in srgb, ${theme.primary} 12%, ${theme.bgSecondary})` : theme.bgSecondary;
279
+ const restingBorder = isHero ? theme.primary : theme.border;
280
+ const restingShadow = isHero ? `0 0 10px color-mix(in srgb, ${theme.primary} 22%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
281
+ const bg = active ? theme.primary : done ? theme.success : error ? theme.error : restingBg;
282
+ const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : restingBorder;
283
+ const shadow = active ? `0 0 22px color-mix(in srgb, ${theme.primary} 55%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : restingShadow;
257
284
  const textColor = active || done || error ? "#fff" : theme.textPrimary;
258
285
  return /* @__PURE__ */ jsxs(Fragment, { children: [
259
286
  /* @__PURE__ */ jsx2(Handle, { type: "target", position: Position.Top, style: { opacity: 0 } }),
260
- /* @__PURE__ */ jsxs(
287
+ /* @__PURE__ */ jsx2("div", { style: { width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs(
261
288
  "div",
262
289
  {
263
290
  style: {
264
291
  position: "relative",
265
292
  display: "flex",
266
293
  alignItems: "center",
267
- gap: 6
294
+ gap: 6,
295
+ // Plumbing recedes. Layers with the run-overlay `dimmed` (not-yet-run)
296
+ // — a muted AND not-run node is faintest, which is correct.
297
+ opacity: isMuted ? 0.5 : void 0
268
298
  },
269
299
  children: [
270
300
  stepNumbers && stepNumbers.length > 0 && isOnPath && /* @__PURE__ */ jsx2(
@@ -333,6 +363,26 @@ var StageNode = memo(function StageNode2({
333
363
  }
334
364
  }
335
365
  ),
366
+ active && /* @__PURE__ */ jsx2(
367
+ "div",
368
+ {
369
+ style: {
370
+ position: "absolute",
371
+ top: -9,
372
+ right: -8,
373
+ zIndex: 11,
374
+ background: theme.warning,
375
+ color: "#1a1a1a",
376
+ fontSize: 9,
377
+ fontWeight: 800,
378
+ letterSpacing: 0.6,
379
+ padding: "2px 6px",
380
+ borderRadius: 10,
381
+ boxShadow: `0 0 10px color-mix(in srgb, ${theme.warning} 60%, transparent)`
382
+ },
383
+ children: "NOW"
384
+ }
385
+ ),
336
386
  isDecider ? /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: 120, height: 72 }, children: [
337
387
  /* @__PURE__ */ jsx2(
338
388
  "div",
@@ -438,9 +488,9 @@ var StageNode = memo(function StageNode2({
438
488
  {
439
489
  style: {
440
490
  background: bg,
441
- border: `2px ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
491
+ border: `${isHero ? "2.5px" : isMuted ? "1px" : "2px"} ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
442
492
  borderRadius: theme.radius,
443
- padding: description ? "8px 16px" : "10px 20px",
493
+ padding: description ? `${Math.round(8 * sizeScale)}px ${Math.round(16 * sizeScale)}px` : `${Math.round(10 * sizeScale)}px ${Math.round(20 * sizeScale)}px`,
444
494
  display: "flex",
445
495
  flexDirection: "column",
446
496
  alignItems: "center",
@@ -473,8 +523,8 @@ var StageNode = memo(function StageNode2({
473
523
  "span",
474
524
  {
475
525
  style: {
476
- fontSize: 13,
477
- fontWeight: 500,
526
+ fontSize: Math.round(13 * sizeScale),
527
+ fontWeight: isHero ? 700 : 500,
478
528
  color: textColor,
479
529
  whiteSpace: "nowrap"
480
530
  },
@@ -549,26 +599,8 @@ var StageNode = memo(function StageNode2({
549
599
  )
550
600
  ]
551
601
  }
552
- ),
553
- /* @__PURE__ */ jsx2(Handle, { type: "source", position: Position.Bottom, style: { opacity: 0 } }),
554
- /* @__PURE__ */ jsx2(
555
- Handle,
556
- {
557
- id: "loop-source",
558
- type: "source",
559
- position: Position.Bottom,
560
- style: { background: "transparent", border: "none", width: 6, height: 6, left: "75%" }
561
- }
562
- ),
563
- /* @__PURE__ */ jsx2(
564
- Handle,
565
- {
566
- id: "loop-target",
567
- type: "target",
568
- position: Position.Right,
569
- style: { background: "transparent", border: "none", width: 6, height: 6 }
570
- }
571
- )
602
+ ) }),
603
+ /* @__PURE__ */ jsx2(Handle, { type: "source", position: Position.Bottom, style: { opacity: 0 } })
572
604
  ] });
573
605
  });
574
606
 
@@ -1138,7 +1170,461 @@ import {
1138
1170
  BackgroundVariant,
1139
1171
  MarkerType
1140
1172
  } from "@xyflow/react";
1141
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1173
+
1174
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
1175
+ import { BaseEdge, useStore } from "@xyflow/react";
1176
+
1177
+ // src/components/FlowchartView/_internal/loopRouting.ts
1178
+ var LOOP_LANE_GAP = 56;
1179
+ function loopLaneX(contentRights, gap = LOOP_LANE_GAP) {
1180
+ let max = -Infinity;
1181
+ for (const r of contentRights) if (r > max) max = r;
1182
+ if (!Number.isFinite(max)) max = 0;
1183
+ return max + gap;
1184
+ }
1185
+ function loopBackPath(source, target, laneX, radius = 22) {
1186
+ const { right: sx, centerY: sy } = source;
1187
+ const { right: tx, centerY: ty } = target;
1188
+ const r = Math.max(
1189
+ 0,
1190
+ Math.min(radius, Math.abs(sy - ty) / 2, laneX - sx, laneX - tx)
1191
+ );
1192
+ const up = ty <= sy;
1193
+ const vy1 = up ? sy - r : sy + r;
1194
+ const vy2 = up ? ty + r : ty - r;
1195
+ return [
1196
+ `M ${sx},${sy}`,
1197
+ `L ${laneX - r},${sy}`,
1198
+ `Q ${laneX},${sy} ${laneX},${vy1}`,
1199
+ `L ${laneX},${vy2}`,
1200
+ `Q ${laneX},${ty} ${laneX - r},${ty}`,
1201
+ `L ${tx},${ty}`
1202
+ ].join(" ");
1203
+ }
1204
+
1205
+ // src/components/FlowchartView/_internal/groupLayout.ts
1206
+ var GROUP_CONTAINER_NODE_TYPE = "groupContainer";
1207
+ var DEFAULT_PADDING = 16;
1208
+ var DEFAULT_HEADER = 44;
1209
+ var DEFAULT_NODE_W = 200;
1210
+ var DEFAULT_NODE_H = 80;
1211
+ function footprintOf(node, fallbackW, fallbackH) {
1212
+ const style = node.style ?? {};
1213
+ const w = typeof style.width === "number" ? style.width : fallbackW;
1214
+ const h = typeof style.height === "number" ? style.height : fallbackH;
1215
+ return { width: w, height: h };
1216
+ }
1217
+ function applyGroupLayout(graph, opts) {
1218
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
1219
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
1220
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;
1221
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;
1222
+ const baseLayout = opts.baseLayout;
1223
+ const requested = new Set(opts.groupedSubflowIds);
1224
+ const membersBySubflow = /* @__PURE__ */ new Map();
1225
+ for (const n of graph.nodes) {
1226
+ const of = n.data?.subflowOf;
1227
+ if (of !== void 0 && requested.has(of)) {
1228
+ const arr = membersBySubflow.get(of) ?? [];
1229
+ arr.push(n);
1230
+ membersBySubflow.set(of, arr);
1231
+ }
1232
+ }
1233
+ const mountBySubflow = /* @__PURE__ */ new Map();
1234
+ for (const n of graph.nodes) {
1235
+ const sfId = n.data?.subflowId;
1236
+ if (n.data?.isSubflow && sfId !== void 0 && requested.has(sfId) && membersBySubflow.has(sfId)) {
1237
+ mountBySubflow.set(sfId, n);
1238
+ }
1239
+ }
1240
+ const activeGroups = /* @__PURE__ */ new Set();
1241
+ for (const sfId of mountBySubflow.keys()) activeGroups.add(sfId);
1242
+ if (activeGroups.size === 0) {
1243
+ return graph;
1244
+ }
1245
+ const memberIds = /* @__PURE__ */ new Set();
1246
+ for (const sfId of activeGroups) {
1247
+ for (const m of membersBySubflow.get(sfId) ?? []) memberIds.add(m.id);
1248
+ }
1249
+ const containerNodes = [];
1250
+ const nestedMembers = [];
1251
+ const groupBox = /* @__PURE__ */ new Map();
1252
+ for (const sfId of activeGroups) {
1253
+ const members = membersBySubflow.get(sfId);
1254
+ const innerOnlyEdges = graph.edges.filter((e) => {
1255
+ const s = members.some((m) => m.id === e.source);
1256
+ const t = members.some((m) => m.id === e.target);
1257
+ return s && t;
1258
+ });
1259
+ const innerPositioned = baseLayout({ nodes: members, edges: innerOnlyEdges });
1260
+ let minX = Infinity;
1261
+ let minY = Infinity;
1262
+ let maxX = -Infinity;
1263
+ let maxY = -Infinity;
1264
+ for (const m of innerPositioned.nodes) {
1265
+ const p = m.position;
1266
+ const { width, height } = footprintOf(m, nodeW, nodeH);
1267
+ if (p.x < minX) minX = p.x;
1268
+ if (p.y < minY) minY = p.y;
1269
+ if (p.x + width > maxX) maxX = p.x + width;
1270
+ if (p.y + height > maxY) maxY = p.y + height;
1271
+ }
1272
+ if (!Number.isFinite(minX)) {
1273
+ minX = 0;
1274
+ minY = 0;
1275
+ maxX = 0;
1276
+ maxY = 0;
1277
+ }
1278
+ const boxWidth = maxX - minX + padding2 * 2;
1279
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
1280
+ groupBox.set(sfId, { width: boxWidth, height: boxHeight, minX, minY, members: innerPositioned.nodes });
1281
+ }
1282
+ const outerNodes = graph.nodes.filter((n) => !memberIds.has(n.id)).map((n) => {
1283
+ const box = n.data?.subflowId ? groupBox.get(n.data.subflowId) : void 0;
1284
+ return box ? {
1285
+ ...n,
1286
+ style: { ...n.style ?? {}, width: box.width, height: box.height },
1287
+ data: { ...n.data, isGroupContainer: true }
1288
+ } : n;
1289
+ });
1290
+ const outerEdges = graph.edges.filter(
1291
+ (e) => !memberIds.has(e.source) && !memberIds.has(e.target)
1292
+ );
1293
+ const outerPositioned = baseLayout({ nodes: outerNodes, edges: outerEdges });
1294
+ const outerPosById = new Map(outerPositioned.nodes.map((n) => [n.id, n.position]));
1295
+ for (const sfId of activeGroups) {
1296
+ const mount = mountBySubflow.get(sfId);
1297
+ const box = groupBox.get(sfId);
1298
+ const { width: boxWidth, height: boxHeight, minX, minY } = box;
1299
+ const mountPos = outerPosById.get(mount.id) ?? mount.position ?? { x: 0, y: 0 };
1300
+ containerNodes.push({
1301
+ ...mount,
1302
+ type: GROUP_CONTAINER_NODE_TYPE,
1303
+ position: mountPos,
1304
+ style: { ...mount.style ?? {}, width: boxWidth, height: boxHeight },
1305
+ data: { ...mount.data, isGroupContainer: true }
1306
+ });
1307
+ for (const m of box.members) {
1308
+ const relX = m.position.x - minX + padding2;
1309
+ const relY = m.position.y - minY + headerHeight + padding2;
1310
+ nestedMembers.push({
1311
+ ...m,
1312
+ parentId: mount.id,
1313
+ extent: "parent",
1314
+ position: { x: relX, y: relY }
1315
+ });
1316
+ }
1317
+ }
1318
+ const containerById = new Map(containerNodes.map((c) => [c.id, c]));
1319
+ const outerOut = outerPositioned.nodes.map(
1320
+ (n) => containerById.get(n.id) ?? n
1321
+ );
1322
+ return {
1323
+ nodes: [...outerOut, ...nestedMembers],
1324
+ edges: graph.edges
1325
+ };
1326
+ }
1327
+ function createGroupedLayout(opts) {
1328
+ return (graph) => applyGroupLayout(graph, opts);
1329
+ }
1330
+ var MAIN_CHART_BOX_ID = "__main_chart__";
1331
+ function wrapInMainChartBox(graph, opts) {
1332
+ if (graph.nodes.length === 0) return graph;
1333
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
1334
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
1335
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;
1336
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;
1337
+ const mainId = opts.id ?? MAIN_CHART_BOX_ID;
1338
+ const positioned = opts.baseLayout(graph);
1339
+ const topLevel = positioned.nodes.filter((n) => n.parentId === void 0);
1340
+ let minX = Infinity;
1341
+ let minY = Infinity;
1342
+ let maxX = -Infinity;
1343
+ let maxY = -Infinity;
1344
+ for (const n of topLevel) {
1345
+ const p = n.position;
1346
+ const { width, height } = footprintOf(n, nodeW, nodeH);
1347
+ if (p.x < minX) minX = p.x;
1348
+ if (p.y < minY) minY = p.y;
1349
+ if (p.x + width > maxX) maxX = p.x + width;
1350
+ if (p.y + height > maxY) maxY = p.y + height;
1351
+ }
1352
+ if (!Number.isFinite(minX)) {
1353
+ minX = 0;
1354
+ minY = 0;
1355
+ maxX = 0;
1356
+ maxY = 0;
1357
+ }
1358
+ const hasLoopEdge = graph.edges.some((e) => e.data?.kind === "loop");
1359
+ const loopReserve = hasLoopEdge ? LOOP_LANE_GAP : 0;
1360
+ const boxWidth = maxX - minX + padding2 * 2 + loopReserve;
1361
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
1362
+ const container = {
1363
+ id: mainId,
1364
+ type: GROUP_CONTAINER_NODE_TYPE,
1365
+ position: { x: 0, y: 0 },
1366
+ style: { width: boxWidth, height: boxHeight },
1367
+ data: {
1368
+ label: opts.label ?? "Chart",
1369
+ isDecider: false,
1370
+ isFork: false,
1371
+ isStreaming: false,
1372
+ isSubflow: false,
1373
+ isGroupContainer: true,
1374
+ isMainChart: true,
1375
+ ...opts.kind !== void 0 && { kind: opts.kind },
1376
+ prevIds: [],
1377
+ nextIds: []
1378
+ }
1379
+ };
1380
+ const topLevelIds = new Set(topLevel.map((n) => n.id));
1381
+ const reparented = positioned.nodes.map((n) => {
1382
+ if (!topLevelIds.has(n.id)) return n;
1383
+ return {
1384
+ ...n,
1385
+ parentId: mainId,
1386
+ extent: "parent",
1387
+ position: {
1388
+ x: n.position.x - minX + padding2,
1389
+ y: n.position.y - minY + headerHeight + padding2
1390
+ }
1391
+ };
1392
+ });
1393
+ return { nodes: [container, ...reparented], edges: graph.edges };
1394
+ }
1395
+ function createMainChartBoxLayout(opts) {
1396
+ return (graph) => wrapInMainChartBox(graph, opts);
1397
+ }
1398
+
1399
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
1400
+ import { jsx as jsx6 } from "react/jsx-runtime";
1401
+ var LOOP_DASH = "5 5";
1402
+ var LOOP_STROKE_OPACITY_CAP = 0.55;
1403
+ var LOOP_STROKE_WIDTH = 1.5;
1404
+ function softenLoopStyle(style) {
1405
+ const passedStrokeOpacity = typeof style?.strokeOpacity === "number" ? style.strokeOpacity : 1;
1406
+ return {
1407
+ ...style,
1408
+ strokeDasharray: style?.strokeDasharray ?? LOOP_DASH,
1409
+ strokeOpacity: Math.min(passedStrokeOpacity, LOOP_STROKE_OPACITY_CAP),
1410
+ strokeWidth: LOOP_STROKE_WIDTH
1411
+ };
1412
+ }
1413
+ var LOOP_CORNER_RADIUS = 28;
1414
+ function rightEdge(node) {
1415
+ return node.internals.positionAbsolute.x + (node.measured.width ?? 0);
1416
+ }
1417
+ function centerY(node) {
1418
+ return node.internals.positionAbsolute.y + (node.measured.height ?? 0) / 2;
1419
+ }
1420
+ function LoopBackEdge({ id, source, target, markerEnd, style }) {
1421
+ const path = useStore((s) => {
1422
+ const src = s.nodeLookup.get(source);
1423
+ const tgt = s.nodeLookup.get(target);
1424
+ if (!src || !tgt) return "";
1425
+ const contentRights = [];
1426
+ for (const n of s.nodeLookup.values()) {
1427
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
1428
+ contentRights.push(rightEdge(n));
1429
+ }
1430
+ const laneX = loopLaneX([...contentRights, rightEdge(src), rightEdge(tgt)], LOOP_LANE_GAP);
1431
+ return loopBackPath(
1432
+ { right: rightEdge(src), centerY: centerY(src) },
1433
+ { right: rightEdge(tgt), centerY: centerY(tgt) },
1434
+ laneX,
1435
+ LOOP_CORNER_RADIUS
1436
+ );
1437
+ });
1438
+ if (!path) return null;
1439
+ return /* @__PURE__ */ jsx6(
1440
+ BaseEdge,
1441
+ {
1442
+ id,
1443
+ path,
1444
+ markerEnd,
1445
+ style: softenLoopStyle(style),
1446
+ "aria-label": "Loop back"
1447
+ }
1448
+ );
1449
+ }
1450
+
1451
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
1452
+ import { BaseEdge as BaseEdge2, getSmoothStepPath, useStore as useStore2 } from "@xyflow/react";
1453
+ import { Position as Position2 } from "@xyflow/react";
1454
+
1455
+ // src/components/FlowchartView/_internal/stepRouting.ts
1456
+ function staggeredBendY(sourceBottom, targetTop, others, minGapFromTarget = 8) {
1457
+ let lowestSkippedBottom = -Infinity;
1458
+ for (const n of others) {
1459
+ const cy = (n.top + n.bottom) / 2;
1460
+ if (cy > sourceBottom && cy < targetTop && n.bottom > lowestSkippedBottom) {
1461
+ lowestSkippedBottom = n.bottom;
1462
+ }
1463
+ }
1464
+ if (lowestSkippedBottom === -Infinity) return null;
1465
+ return Math.min((lowestSkippedBottom + targetTop) / 2, targetTop - minGapFromTarget);
1466
+ }
1467
+
1468
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
1469
+ import { jsx as jsx7 } from "react/jsx-runtime";
1470
+ function SmartStepEdge({
1471
+ id,
1472
+ source,
1473
+ target,
1474
+ sourceX,
1475
+ sourceY,
1476
+ targetX,
1477
+ targetY,
1478
+ sourcePosition,
1479
+ targetPosition,
1480
+ markerEnd,
1481
+ style
1482
+ }) {
1483
+ const bendY = useStore2((s) => {
1484
+ const src = s.nodeLookup.get(source);
1485
+ const tgt = s.nodeLookup.get(target);
1486
+ if (!src || !tgt) return null;
1487
+ const sourceBottom = src.internals.positionAbsolute.y + (src.measured.height ?? 0);
1488
+ const targetTop = tgt.internals.positionAbsolute.y;
1489
+ const others = [];
1490
+ for (const n of s.nodeLookup.values()) {
1491
+ if (n.id === source || n.id === target) continue;
1492
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
1493
+ const top = n.internals.positionAbsolute.y;
1494
+ others.push({ top, bottom: top + (n.measured.height ?? 0) });
1495
+ }
1496
+ return staggeredBendY(sourceBottom, targetTop, others);
1497
+ });
1498
+ const [path] = getSmoothStepPath({
1499
+ sourceX,
1500
+ sourceY,
1501
+ sourcePosition: sourcePosition ?? Position2.Bottom,
1502
+ targetX,
1503
+ targetY,
1504
+ targetPosition: targetPosition ?? Position2.Top,
1505
+ // Override the bend only for a staggered edge; otherwise let getSmoothStepPath
1506
+ // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).
1507
+ ...bendY !== null ? { centerY: bendY } : {}
1508
+ });
1509
+ return /* @__PURE__ */ jsx7(BaseEdge2, { id, path, markerEnd, style });
1510
+ }
1511
+
1512
+ // src/components/FlowchartView/_internal/dagreTraceLayout.ts
1513
+ import dagre from "dagre";
1514
+ var DEFAULT_NODE_W2 = 200;
1515
+ var DEFAULT_NODE_H2 = 80;
1516
+ function sizeOf(node, fallbackW, fallbackH, resolver) {
1517
+ const style = node.style ?? {};
1518
+ const styleW = typeof style.width === "number" ? style.width : void 0;
1519
+ const styleH = typeof style.height === "number" ? style.height : void 0;
1520
+ if (node.data?.isGroupContainer && styleW !== void 0 && styleH !== void 0) {
1521
+ return { width: styleW, height: styleH };
1522
+ }
1523
+ const resolved = resolver?.(node);
1524
+ if (resolved) return { width: resolved.width, height: resolved.height };
1525
+ return {
1526
+ width: styleW ?? fallbackW,
1527
+ height: styleH ?? fallbackH
1528
+ };
1529
+ }
1530
+ function reorderSiblingEdges(edges, siblingOrder) {
1531
+ const bySource = /* @__PURE__ */ new Map();
1532
+ for (const e of edges) {
1533
+ if (e.data?.kind === "loop") continue;
1534
+ const arr = bySource.get(e.source);
1535
+ if (arr) arr.push(e);
1536
+ else bySource.set(e.source, [e]);
1537
+ }
1538
+ const out = [];
1539
+ for (const [src, group] of bySource) {
1540
+ if (group.length < 2) {
1541
+ out.push(...group);
1542
+ continue;
1543
+ }
1544
+ const ordered = siblingOrder(src, group.map((e) => e.target));
1545
+ const byTarget = new Map(group.map((e) => [e.target, e]));
1546
+ const used = /* @__PURE__ */ new Set();
1547
+ for (const t of ordered) {
1548
+ const e = byTarget.get(t);
1549
+ if (e && !used.has(t)) {
1550
+ out.push(e);
1551
+ used.add(t);
1552
+ }
1553
+ }
1554
+ for (const e of group) if (!used.has(e.target)) out.push(e);
1555
+ }
1556
+ return out;
1557
+ }
1558
+ function dagreTraceLayout(graph, options = {}) {
1559
+ if (graph.nodes.length === 0) return graph;
1560
+ const direction = options.direction ?? "TB";
1561
+ const rankSep = options.rankSep ?? 80;
1562
+ const nodeSep = options.nodeSep ?? 60;
1563
+ const edgeSep = options.edgeSep ?? 20;
1564
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
1565
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
1566
+ const g = new dagre.graphlib.Graph({ compound: true });
1567
+ g.setGraph({ rankdir: direction, ranksep: rankSep, nodesep: nodeSep, edgesep: edgeSep });
1568
+ g.setDefaultEdgeLabel(() => ({}));
1569
+ const sizes = /* @__PURE__ */ new Map();
1570
+ const resolvedStyleSizes = /* @__PURE__ */ new Map();
1571
+ for (const node of graph.nodes) {
1572
+ const resolved = options.nodeSize?.(node);
1573
+ const size = sizeOf(node, fallbackW, fallbackH, options.nodeSize);
1574
+ sizes.set(node.id, size);
1575
+ if (resolved && resolved.width === size.width && resolved.height === size.height) {
1576
+ resolvedStyleSizes.set(node.id, resolved);
1577
+ }
1578
+ g.setNode(node.id, { width: size.width, height: size.height });
1579
+ if (node.parentId) {
1580
+ g.setParent(node.id, node.parentId);
1581
+ }
1582
+ }
1583
+ const layoutEdges = options.siblingOrder ? reorderSiblingEdges(graph.edges, options.siblingOrder) : graph.edges;
1584
+ for (const e of layoutEdges) {
1585
+ if (e.data?.kind === "loop") continue;
1586
+ if (g.hasNode(e.source) && g.hasNode(e.target)) {
1587
+ const label = {};
1588
+ const weight = options.edgeWeight?.(e);
1589
+ const minlen = options.edgeMinLen?.(e);
1590
+ if (typeof weight === "number") label.weight = weight;
1591
+ if (typeof minlen === "number") label.minlen = minlen;
1592
+ g.setEdge(e.source, e.target, label);
1593
+ }
1594
+ }
1595
+ dagre.layout(g);
1596
+ const positioned = graph.nodes.map((node) => {
1597
+ const laidOut = g.node(node.id);
1598
+ if (!laidOut) return node;
1599
+ const size = sizes.get(node.id);
1600
+ let x = laidOut.x - size.width / 2;
1601
+ let y = laidOut.y - size.height / 2;
1602
+ if (node.parentId) {
1603
+ const parent = g.node(node.parentId);
1604
+ const parentSize = sizes.get(node.parentId);
1605
+ if (parent && parentSize) {
1606
+ x -= parent.x - parentSize.width / 2;
1607
+ y -= parent.y - parentSize.height / 2;
1608
+ }
1609
+ }
1610
+ const styleSize = resolvedStyleSizes.get(node.id);
1611
+ if (styleSize) {
1612
+ return {
1613
+ ...node,
1614
+ position: { x, y },
1615
+ style: { ...node.style ?? {}, width: styleSize.width, height: styleSize.height }
1616
+ };
1617
+ }
1618
+ return { ...node, position: { x, y } };
1619
+ });
1620
+ return { nodes: positioned, edges: graph.edges };
1621
+ }
1622
+ function createDagreTraceLayout(options = {}) {
1623
+ return (graph) => dagreTraceLayout(graph, options);
1624
+ }
1625
+
1626
+ // src/components/FlowchartView/TraceFlow.tsx
1627
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1142
1628
  var Y_STEP = 100;
1143
1629
  var X_SPREAD = 200;
1144
1630
  var defaultTraceFlowLayout = (graph) => {
@@ -1227,7 +1713,11 @@ function styleEdge(edge, colors) {
1227
1713
  const color = kind === "loop" ? colors.loop : kind === "fork-branch" ? colors.forkBranch : kind === "decision-branch" ? colors.decisionBranch : colors.next;
1228
1714
  const styled = {
1229
1715
  ...edge,
1230
- type: kind === "loop" ? "step" : "smoothstep",
1716
+ // Loop back-edges use the custom `loopBack` edge — a curve routed along the
1717
+ // right margin (clear of the spine) instead of a straight/step center line.
1718
+ // Every other edge uses `smartStep`: a smoothstep superset that routes a
1719
+ // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).
1720
+ type: kind === "loop" ? "loopBack" : "smartStep",
1231
1721
  animated: false,
1232
1722
  style: { stroke: color, strokeWidth: 1.5 },
1233
1723
  markerEnd: { type: MarkerType.ArrowClosed, color, width: 16, height: 16 }
@@ -1238,6 +1728,7 @@ function styleEdge(edge, colors) {
1238
1728
  return styled;
1239
1729
  }
1240
1730
  var DEFAULT_NODE_TYPES = { stageNode: StageNode };
1731
+ var DEFAULT_EDGE_TYPES = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };
1241
1732
  function toStageNode(node) {
1242
1733
  if (node.type !== void 0 && node.type !== "stage") {
1243
1734
  return node;
@@ -1254,7 +1745,9 @@ function toStageNode(node) {
1254
1745
  ...data.description !== void 0 && { description: data.description },
1255
1746
  ...data.icon !== void 0 && { icon: data.icon },
1256
1747
  ...data.subflowId !== void 0 && { subflowId: data.subflowId },
1257
- ...data.isLazy === true && { isLazy: true }
1748
+ ...data.isLazy === true && { isLazy: true },
1749
+ ...data.emphasis !== void 0 && { emphasis: data.emphasis },
1750
+ ...data.size !== void 0 && { size: data.size }
1258
1751
  };
1259
1752
  return {
1260
1753
  ...node,
@@ -1284,7 +1777,7 @@ function TraceFlow(props) {
1284
1777
  "[TraceFlow] neither `recorder` nor `graph` prop was provided \u2014 rendering an empty chart. Pass one of: <TraceFlow recorder={handle} /> OR <TraceFlow graph={{nodes, edges}} />."
1285
1778
  );
1286
1779
  }
1287
- const layout = props.layout ?? defaultTraceFlowLayout;
1780
+ const layout = props.layout ?? dagreTraceLayout;
1288
1781
  const edgeColors = useMemo4(
1289
1782
  () => ({ ...DEFAULT_EDGE_COLORS, ...props.edgeColors ?? {} }),
1290
1783
  [props.edgeColors]
@@ -1328,7 +1821,11 @@ function TraceFlow(props) {
1328
1821
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES,
1329
1822
  [userNodeTypes]
1330
1823
  );
1331
- return /* @__PURE__ */ jsx6(
1824
+ const mergedEdgeTypes = useMemo4(
1825
+ () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES,
1826
+ [userEdgeTypes]
1827
+ );
1828
+ return /* @__PURE__ */ jsx8(
1332
1829
  "div",
1333
1830
  {
1334
1831
  className: props.className,
@@ -1344,12 +1841,12 @@ function TraceFlow(props) {
1344
1841
  nodes: reactFlowNodes,
1345
1842
  edges: reactFlowEdges,
1346
1843
  nodeTypes: mergedNodeTypes,
1347
- ...userEdgeTypes && { edgeTypes: userEdgeTypes },
1844
+ edgeTypes: mergedEdgeTypes,
1348
1845
  onNodeClick: handleNodeClick,
1349
1846
  fitView: true,
1350
1847
  proOptions: { hideAttribution: true },
1351
1848
  children: [
1352
- /* @__PURE__ */ jsx6(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }),
1849
+ /* @__PURE__ */ jsx8(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }),
1353
1850
  props.children
1354
1851
  ]
1355
1852
  }
@@ -1541,19 +2038,6 @@ function buildSubflowBreadcrumb(graph, currentSubflowId) {
1541
2038
  }
1542
2039
 
1543
2040
  // src/components/FlowchartView/_internal/overlayProjection.ts
1544
- function leafId(id) {
1545
- const i = id.lastIndexOf("/");
1546
- return i >= 0 ? id.slice(i + 1) : id;
1547
- }
1548
- function normalizeSliceLeafIds(slice) {
1549
- return {
1550
- doneStageIds: new Set(Array.from(slice.doneStageIds).map(leafId)),
1551
- activeStageId: slice.activeStageId ? leafId(slice.activeStageId) : null,
1552
- executedStageIds: new Set(Array.from(slice.executedStageIds).map(leafId)),
1553
- executedOrderIds: slice.executedOrderIds.map(leafId),
1554
- errors: new Map(Array.from(slice.errors).map(([k, v2]) => [leafId(k), v2]))
1555
- };
1556
- }
1557
2041
  function aggregateMountStatus(slice, graph, currentSubflowId) {
1558
2042
  if (graph.nodes.length === 0) return slice;
1559
2043
  const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);
@@ -1565,10 +2049,9 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
1565
2049
  const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);
1566
2050
  if (members.length === 0) continue;
1567
2051
  const anyActive = members.some((m) => m.id === slice.activeStageId);
1568
- const anyDone = members.some((m) => slice.doneStageIds.has(m.id));
1569
2052
  const allDone = members.every((m) => slice.doneStageIds.has(m.id));
1570
2053
  if (allDone) doneIds.add(mount.id);
1571
- else if ((anyActive || anyDone) && currentSubflowId === null) {
2054
+ else if (anyActive && currentSubflowId === null) {
1572
2055
  activeId = mount.id;
1573
2056
  }
1574
2057
  }
@@ -1611,6 +2094,7 @@ import { useEffect as useEffect5 } from "react";
1611
2094
  function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
1612
2095
  const duration = options.duration ?? 200;
1613
2096
  const padding2 = options.padding ?? 0.1;
2097
+ const refitKey = options.refitKey;
1614
2098
  useEffect5(() => {
1615
2099
  const el = wrapperRef.current;
1616
2100
  if (!el || !rfInstance) return;
@@ -1630,12 +2114,25 @@ function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
1630
2114
  cancelAnimationFrame(raf);
1631
2115
  };
1632
2116
  }, [rfInstance, wrapperRef, duration, padding2]);
2117
+ useEffect5(() => {
2118
+ if (!rfInstance) return;
2119
+ let raf2 = 0;
2120
+ const raf1 = requestAnimationFrame(() => {
2121
+ raf2 = requestAnimationFrame(() => {
2122
+ rfInstance.fitView({ duration, padding: padding2 });
2123
+ });
2124
+ });
2125
+ return () => {
2126
+ cancelAnimationFrame(raf1);
2127
+ cancelAnimationFrame(raf2);
2128
+ };
2129
+ }, [rfInstance, refitKey, duration, padding2]);
1633
2130
  }
1634
2131
 
1635
2132
  // src/components/FlowchartView/SubflowBreadcrumbBar.tsx
1636
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2133
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1637
2134
  function SubflowBreadcrumbBar({ entries, onNavigate }) {
1638
- return /* @__PURE__ */ jsx7(
2135
+ return /* @__PURE__ */ jsx9(
1639
2136
  "div",
1640
2137
  {
1641
2138
  style: {
@@ -1656,7 +2153,7 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1656
2153
  {
1657
2154
  style: { display: "inline-flex", alignItems: "center", gap: 6 },
1658
2155
  children: [
1659
- /* @__PURE__ */ jsx7(
2156
+ /* @__PURE__ */ jsx9(
1660
2157
  "button",
1661
2158
  {
1662
2159
  type: "button",
@@ -1676,7 +2173,7 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1676
2173
  children: entry.label
1677
2174
  }
1678
2175
  ),
1679
- !isLast && /* @__PURE__ */ jsx7("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
2176
+ !isLast && /* @__PURE__ */ jsx9("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
1680
2177
  ]
1681
2178
  },
1682
2179
  entry.subflowId ?? "__top__"
@@ -1686,8 +2183,56 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1686
2183
  );
1687
2184
  }
1688
2185
 
2186
+ // src/components/GroupContainerNode/GroupContainerNode.tsx
2187
+ import { Handle as Handle2, Position as Position3 } from "@xyflow/react";
2188
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2189
+ var C = rawDefaults.colors;
2190
+ function GroupContainerNode({ data }) {
2191
+ const d = data;
2192
+ const borderColor = d.error ? C.error : d.active ? C.primary : d.done ? C.success : C.border;
2193
+ return /* @__PURE__ */ jsxs7(
2194
+ "div",
2195
+ {
2196
+ style: {
2197
+ width: "100%",
2198
+ height: "100%",
2199
+ boxSizing: "border-box",
2200
+ border: `1.5px ${d.active || d.done || d.error ? "solid" : "dashed"} ${borderColor}`,
2201
+ borderRadius: 12,
2202
+ // Translucent so the dotted background + nested children read clearly.
2203
+ background: "rgba(148, 163, 184, 0.06)",
2204
+ opacity: d.dimmed ? 0.4 : 1,
2205
+ position: "relative"
2206
+ },
2207
+ children: [
2208
+ /* @__PURE__ */ jsxs7(
2209
+ "div",
2210
+ {
2211
+ style: {
2212
+ display: "flex",
2213
+ alignItems: "center",
2214
+ gap: 6,
2215
+ padding: "8px 12px",
2216
+ fontSize: 12,
2217
+ fontWeight: 600,
2218
+ color: C.textMuted,
2219
+ letterSpacing: 0.2
2220
+ },
2221
+ children: [
2222
+ d.icon ? /* @__PURE__ */ jsx10("span", { "aria-hidden": true, children: d.icon }) : null,
2223
+ /* @__PURE__ */ jsx10("span", { children: d.label })
2224
+ ]
2225
+ }
2226
+ ),
2227
+ /* @__PURE__ */ jsx10(Handle2, { type: "target", position: Position3.Top, style: { opacity: 0 } }),
2228
+ /* @__PURE__ */ jsx10(Handle2, { type: "source", position: Position3.Bottom, style: { opacity: 0 } })
2229
+ ]
2230
+ }
2231
+ );
2232
+ }
2233
+
1689
2234
  // src/components/FlowchartView/TracedFlow.tsx
1690
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2235
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1691
2236
  var DEFAULT_COLORS = {
1692
2237
  default: rawDefaults.colors.textMuted,
1693
2238
  done: rawDefaults.colors.success,
@@ -1695,12 +2240,10 @@ var DEFAULT_COLORS = {
1695
2240
  error: rawDefaults.colors.error,
1696
2241
  loop: rawDefaults.colors.warning
1697
2242
  };
1698
- function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds) {
1699
- if (node.type !== void 0 && node.type !== "stage") {
1700
- return node;
1701
- }
2243
+ var EMPTY_SET = /* @__PURE__ */ new Set();
2244
+ function deriveOverlayFields(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
1702
2245
  const isDone = doneStageIds.has(node.id);
1703
- const isActive = activeStageId === node.id;
2246
+ const isActive = activeStageId === node.id || coActiveStageIds.has(node.id);
1704
2247
  const wasExecuted = isDone || isActive;
1705
2248
  const hasError = !!errorMessage;
1706
2249
  const dimmed = !wasExecuted && executedOrderIds.length > 0;
@@ -1712,21 +2255,62 @@ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage,
1712
2255
  }
1713
2256
  if (nums.length > 0) stepNumbers = nums;
1714
2257
  }
2258
+ return {
2259
+ active: isActive,
2260
+ done: isDone,
2261
+ error: hasError,
2262
+ dimmed,
2263
+ ...errorMessage && { errorMessage },
2264
+ ...stepNumbers && { stepNumbers }
2265
+ };
2266
+ }
2267
+ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
2268
+ const overlayFields = deriveOverlayFields(
2269
+ node,
2270
+ doneStageIds,
2271
+ activeStageId,
2272
+ errorMessage,
2273
+ executedOrderIds,
2274
+ coActiveStageIds
2275
+ );
2276
+ const { dimmed } = overlayFields;
2277
+ if (node.type !== void 0 && node.type !== "stage") {
2278
+ const consumerData = node.data ?? {};
2279
+ const consumerActive = consumerData.active === true;
2280
+ const consumerDone = consumerData.done === true;
2281
+ const consumerError = consumerData.error === true;
2282
+ const finalActive = consumerActive || overlayFields.active;
2283
+ const finalDone = consumerDone || overlayFields.done;
2284
+ const finalError = consumerError || overlayFields.error;
2285
+ const finalDimmed = !finalActive && !finalDone && dimmed;
2286
+ return {
2287
+ ...node,
2288
+ data: {
2289
+ ...node.data,
2290
+ active: finalActive,
2291
+ done: finalDone,
2292
+ error: finalError,
2293
+ ...overlayFields.errorMessage !== void 0 && consumerData.errorMessage === void 0 && {
2294
+ errorMessage: overlayFields.errorMessage
2295
+ },
2296
+ ...finalDimmed && { dimmed: true },
2297
+ ...overlayFields.stepNumbers && { stepNumbers: overlayFields.stepNumbers }
2298
+ },
2299
+ ...finalDimmed && { style: { ...node.style ?? {}, opacity: 0.35 } }
2300
+ };
2301
+ }
1715
2302
  const stageData = {
1716
2303
  label: node.data.label,
1717
2304
  isDecider: node.data.isDecider,
1718
2305
  isFork: node.data.isFork,
1719
2306
  isSubflow: node.data.isSubflow,
1720
- active: isActive,
1721
- done: isDone,
1722
- error: hasError,
2307
+ ...overlayFields,
1723
2308
  ...node.data.description !== void 0 && { description: node.data.description },
1724
2309
  ...node.data.icon !== void 0 && { icon: node.data.icon },
1725
2310
  ...node.data.subflowId !== void 0 && { subflowId: node.data.subflowId },
1726
2311
  ...node.data.isLazy === true && { isLazy: true },
1727
- ...dimmed && { dimmed: true },
1728
- ...stepNumbers && { stepNumbers },
1729
- ...errorMessage && { errorMessage }
2312
+ ...node.data.emphasis !== void 0 && { emphasis: node.data.emphasis },
2313
+ ...node.data.size !== void 0 && { size: node.data.size }
1730
2314
  };
1731
2315
  return {
1732
2316
  ...node,
@@ -1747,23 +2331,27 @@ function styleEdgeWithOverlay(edge, doneStageIds, activeStageId, colors) {
1747
2331
  else if (traversed) color = colors.done;
1748
2332
  const styled = {
1749
2333
  ...edge,
1750
- type: "smoothstep",
2334
+ // Loop back-edges use the custom `loopBack` edge — a curve routed along the
2335
+ // right margin (clear of the spine). It reads node bounds from the store
2336
+ // and anchors on right edges itself, so it needs NO dedicated loop handles
2337
+ // on the node (the old approach broke for any node missing them).
2338
+ // Every other edge uses `smartStep`: a smoothstep superset that routes a
2339
+ // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).
2340
+ type: kind === "loop" ? "loopBack" : "smartStep",
1751
2341
  animated: isLeadingEdge,
1752
2342
  style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },
1753
2343
  markerEnd: { type: MarkerType2.ArrowClosed, color, width: 16, height: 16 }
1754
2344
  };
1755
2345
  if (kind === "loop") {
1756
2346
  styled.style = { ...styled.style, strokeDasharray: "4 3" };
1757
- styled.data = {
1758
- ...styled.data ?? {},
1759
- pathOptions: { borderRadius: 14, offset: 36 }
1760
- };
1761
- styled.sourceHandle = "loop-source";
1762
- styled.targetHandle = "loop-target";
1763
2347
  }
1764
2348
  return styled;
1765
2349
  }
1766
- var DEFAULT_NODE_TYPES2 = { stageNode: StageNode };
2350
+ var DEFAULT_NODE_TYPES2 = {
2351
+ stageNode: StageNode,
2352
+ groupContainer: GroupContainerNode
2353
+ };
2354
+ var DEFAULT_EDGE_TYPES2 = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };
1767
2355
  function TracedFlow({
1768
2356
  graph,
1769
2357
  overlay,
@@ -1772,13 +2360,16 @@ function TracedFlow({
1772
2360
  colors: colorOverrides,
1773
2361
  onNodeClick,
1774
2362
  onSubflowChange,
2363
+ groupedSubflows,
2364
+ mainChartBox,
1775
2365
  nodeTypes: userNodeTypes,
1776
2366
  edgeTypes: userEdgeTypes,
2367
+ coActiveStageIds,
1777
2368
  children,
1778
2369
  className,
1779
2370
  style
1780
2371
  }) {
1781
- const layout = layoutProp ?? defaultTraceFlowLayout;
2372
+ const layout = layoutProp ?? dagreTraceLayout;
1782
2373
  const colors = useMemo5(
1783
2374
  () => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
1784
2375
  [colorOverrides]
@@ -1787,19 +2378,45 @@ function TracedFlow({
1787
2378
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES2, ...userNodeTypes } : DEFAULT_NODE_TYPES2,
1788
2379
  [userNodeTypes]
1789
2380
  );
1790
- const drill = useSubflowDrill(graph, onSubflowChange);
1791
- const filteredGraph = useMemo5(
1792
- () => filterGraphForDrill(graph, drill.currentSubflowId),
1793
- [graph, drill.currentSubflowId]
2381
+ const mergedEdgeTypes = useMemo5(
2382
+ () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES2, ...userEdgeTypes } : DEFAULT_EDGE_TYPES2,
2383
+ [userEdgeTypes]
1794
2384
  );
2385
+ const drill = useSubflowDrill(graph, onSubflowChange);
2386
+ const groupedSet = useMemo5(() => new Set(groupedSubflows ?? []), [groupedSubflows]);
2387
+ const filteredGraph = useMemo5(() => {
2388
+ const base = filterGraphForDrill(graph, drill.currentSubflowId);
2389
+ if (groupedSet.size === 0) return base;
2390
+ const baseIds = new Set(base.nodes.map((n) => n.id));
2391
+ const extraNodes = graph.nodes.filter(
2392
+ (n) => n.data?.subflowOf !== void 0 && groupedSet.has(n.data.subflowOf) && !baseIds.has(n.id)
2393
+ );
2394
+ if (extraNodes.length === 0) return base;
2395
+ const allIds = /* @__PURE__ */ new Set([...baseIds, ...extraNodes.map((n) => n.id)]);
2396
+ const baseEdgeIds = new Set(base.edges.map((e) => e.id));
2397
+ const extraEdges = graph.edges.filter(
2398
+ (e) => !baseEdgeIds.has(e.id) && allIds.has(e.source) && allIds.has(e.target)
2399
+ );
2400
+ return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };
2401
+ }, [graph, drill.currentSubflowId, groupedSet]);
1795
2402
  const breadcrumb = useMemo5(
1796
2403
  () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),
1797
2404
  [graph, drill.currentSubflowId]
1798
2405
  );
1799
- const positioned = useMemo5(
1800
- () => layout === "passthrough" ? filteredGraph : layout(filteredGraph),
1801
- [filteredGraph, layout]
1802
- );
2406
+ const positioned = useMemo5(() => {
2407
+ const realBase = layout === "passthrough" ? (g) => g : layout;
2408
+ if (groupedSet.size > 0) {
2409
+ const grouped = applyGroupLayout(filteredGraph, {
2410
+ groupedSubflowIds: [...groupedSet],
2411
+ baseLayout: realBase
2412
+ });
2413
+ return mainChartBox ? wrapInMainChartBox(grouped, { baseLayout: (g) => g, ...mainChartBox }) : grouped;
2414
+ }
2415
+ if (mainChartBox) {
2416
+ return wrapInMainChartBox(filteredGraph, { baseLayout: realBase, ...mainChartBox });
2417
+ }
2418
+ return layout === "passthrough" ? filteredGraph : layout(filteredGraph);
2419
+ }, [filteredGraph, layout, groupedSet, mainChartBox]);
1803
2420
  const slice = useMemo5(() => {
1804
2421
  const empty = {
1805
2422
  doneStageIds: /* @__PURE__ */ new Set(),
@@ -1810,8 +2427,7 @@ function TracedFlow({
1810
2427
  };
1811
2428
  if (!overlay) return empty;
1812
2429
  const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);
1813
- const normalized = normalizeSliceLeafIds(sliceOverlay(overlay, idx));
1814
- return aggregateMountStatus(normalized, graph, drill.currentSubflowId);
2430
+ return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);
1815
2431
  }, [overlay, scrubIndex, graph, drill.currentSubflowId]);
1816
2432
  const reactFlowNodes = useMemo5(
1817
2433
  () => positioned.nodes.map(
@@ -1820,10 +2436,11 @@ function TracedFlow({
1820
2436
  slice.doneStageIds,
1821
2437
  slice.activeStageId,
1822
2438
  slice.errors.get(n.id),
1823
- slice.executedOrderIds
2439
+ slice.executedOrderIds,
2440
+ coActiveStageIds ?? EMPTY_SET
1824
2441
  )
1825
2442
  ),
1826
- [positioned.nodes, slice]
2443
+ [positioned.nodes, slice, coActiveStageIds]
1827
2444
  );
1828
2445
  const reactFlowEdges = useMemo5(
1829
2446
  () => positioned.edges.map(
@@ -1834,17 +2451,17 @@ function TracedFlow({
1834
2451
  const handleNodeClick = useCallback3(
1835
2452
  (_, node) => {
1836
2453
  const data = node.data ?? {};
1837
- if (data.isSubflow && data.subflowId) {
2454
+ if (data.isSubflow && data.subflowId && !groupedSet.has(data.subflowId)) {
1838
2455
  drill.drillInto(data.subflowId);
1839
2456
  }
1840
2457
  onNodeClick?.(node.id);
1841
2458
  },
1842
- [drill, onNodeClick]
2459
+ [drill, onNodeClick, groupedSet]
1843
2460
  );
1844
2461
  const wrapperRef = useRef5(null);
1845
2462
  const [rfInstance, setRfInstance] = useState4(null);
1846
- useChartAutoRefit(wrapperRef, rfInstance);
1847
- return /* @__PURE__ */ jsxs7(
2463
+ useChartAutoRefit(wrapperRef, rfInstance, { refitKey: drill.currentSubflowId });
2464
+ return /* @__PURE__ */ jsxs8(
1848
2465
  "div",
1849
2466
  {
1850
2467
  ref: wrapperRef,
@@ -1858,26 +2475,26 @@ function TracedFlow({
1858
2475
  ...style
1859
2476
  },
1860
2477
  children: [
1861
- breadcrumb.length > 1 && /* @__PURE__ */ jsx8(
2478
+ breadcrumb.length > 1 && /* @__PURE__ */ jsx11(
1862
2479
  SubflowBreadcrumbBar,
1863
2480
  {
1864
2481
  entries: breadcrumb,
1865
2482
  onNavigate: drill.setCurrentSubflowId
1866
2483
  }
1867
2484
  ),
1868
- /* @__PURE__ */ jsx8("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsxs7(
2485
+ /* @__PURE__ */ jsx11("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsxs8(
1869
2486
  ReactFlow2,
1870
2487
  {
1871
2488
  nodes: reactFlowNodes,
1872
2489
  edges: reactFlowEdges,
1873
2490
  nodeTypes: mergedNodeTypes,
1874
- ...userEdgeTypes && { edgeTypes: userEdgeTypes },
2491
+ edgeTypes: mergedEdgeTypes,
1875
2492
  onNodeClick: handleNodeClick,
1876
2493
  onInit: setRfInstance,
1877
2494
  fitView: true,
1878
2495
  proOptions: { hideAttribution: true },
1879
2496
  children: [
1880
- /* @__PURE__ */ jsx8(Background2, { variant: BackgroundVariant2.Dots, gap: 20, size: 1 }),
2497
+ /* @__PURE__ */ jsx11(Background2, { variant: BackgroundVariant2.Dots, gap: 20, size: 1 }),
1881
2498
  children
1882
2499
  ]
1883
2500
  }
@@ -1888,7 +2505,7 @@ function TracedFlow({
1888
2505
  }
1889
2506
 
1890
2507
  // src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
1891
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2508
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1892
2509
  function TimeTravelDebugger({
1893
2510
  snapshots,
1894
2511
  graph,
@@ -1905,7 +2522,7 @@ function TimeTravelDebugger({
1905
2522
  const fs = fontSize[size];
1906
2523
  const pad = padding[size];
1907
2524
  if (snapshots.length === 0) {
1908
- return /* @__PURE__ */ jsx9(
2525
+ return /* @__PURE__ */ jsx12(
1909
2526
  "div",
1910
2527
  {
1911
2528
  className,
@@ -1926,7 +2543,7 @@ function TimeTravelDebugger({
1926
2543
  );
1927
2544
  if (idx >= 0) setSelectedIndex(idx);
1928
2545
  };
1929
- const chart = runtimeOverlay ? /* @__PURE__ */ jsx9(
2546
+ const chart = runtimeOverlay ? /* @__PURE__ */ jsx12(
1930
2547
  TracedFlow,
1931
2548
  {
1932
2549
  graph,
@@ -1934,11 +2551,11 @@ function TimeTravelDebugger({
1934
2551
  scrubIndex: selectedIndex,
1935
2552
  onNodeClick: handleNodeClick
1936
2553
  }
1937
- ) : /* @__PURE__ */ jsx9(TraceFlow, { graph, onNodeClick: handleNodeClick });
2554
+ ) : /* @__PURE__ */ jsx12(TraceFlow, { graph, onNodeClick: handleNodeClick });
1938
2555
  if (unstyled) {
1939
- return /* @__PURE__ */ jsxs8("div", { className, style, "data-fp": "time-travel-debugger", children: [
1940
- /* @__PURE__ */ jsx9("h3", { children: title }),
1941
- /* @__PURE__ */ jsx9(
2556
+ return /* @__PURE__ */ jsxs9("div", { className, style, "data-fp": "time-travel-debugger", children: [
2557
+ /* @__PURE__ */ jsx12("h3", { children: title }),
2558
+ /* @__PURE__ */ jsx12(
1942
2559
  "input",
1943
2560
  {
1944
2561
  type: "range",
@@ -1949,7 +2566,7 @@ function TimeTravelDebugger({
1949
2566
  }
1950
2567
  ),
1951
2568
  chart,
1952
- /* @__PURE__ */ jsx9(
2569
+ /* @__PURE__ */ jsx12(
1953
2570
  MemoryInspector,
1954
2571
  {
1955
2572
  snapshots,
@@ -1957,7 +2574,7 @@ function TimeTravelDebugger({
1957
2574
  unstyled: true
1958
2575
  }
1959
2576
  ),
1960
- /* @__PURE__ */ jsx9(
2577
+ /* @__PURE__ */ jsx12(
1961
2578
  NarrativeLog,
1962
2579
  {
1963
2580
  snapshots,
@@ -1965,7 +2582,7 @@ function TimeTravelDebugger({
1965
2582
  unstyled: true
1966
2583
  }
1967
2584
  ),
1968
- showGantt && /* @__PURE__ */ jsx9(
2585
+ showGantt && /* @__PURE__ */ jsx12(
1969
2586
  GanttTimeline,
1970
2587
  {
1971
2588
  snapshots,
@@ -1976,7 +2593,7 @@ function TimeTravelDebugger({
1976
2593
  )
1977
2594
  ] });
1978
2595
  }
1979
- return /* @__PURE__ */ jsxs8(
2596
+ return /* @__PURE__ */ jsxs9(
1980
2597
  "div",
1981
2598
  {
1982
2599
  className,
@@ -1991,7 +2608,7 @@ function TimeTravelDebugger({
1991
2608
  },
1992
2609
  "data-fp": "time-travel-debugger",
1993
2610
  children: [
1994
- /* @__PURE__ */ jsxs8(
2611
+ /* @__PURE__ */ jsxs9(
1995
2612
  "div",
1996
2613
  {
1997
2614
  style: {
@@ -2001,7 +2618,7 @@ function TimeTravelDebugger({
2001
2618
  flexShrink: 0
2002
2619
  },
2003
2620
  children: [
2004
- /* @__PURE__ */ jsxs8(
2621
+ /* @__PURE__ */ jsxs9(
2005
2622
  "div",
2006
2623
  {
2007
2624
  style: {
@@ -2011,7 +2628,7 @@ function TimeTravelDebugger({
2011
2628
  marginBottom: 8
2012
2629
  },
2013
2630
  children: [
2014
- /* @__PURE__ */ jsx9(
2631
+ /* @__PURE__ */ jsx12(
2015
2632
  "span",
2016
2633
  {
2017
2634
  style: {
@@ -2022,7 +2639,7 @@ function TimeTravelDebugger({
2022
2639
  children: title
2023
2640
  }
2024
2641
  ),
2025
- /* @__PURE__ */ jsx9(
2642
+ /* @__PURE__ */ jsx12(
2026
2643
  "span",
2027
2644
  {
2028
2645
  style: {
@@ -2035,8 +2652,8 @@ function TimeTravelDebugger({
2035
2652
  ]
2036
2653
  }
2037
2654
  ),
2038
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2039
- /* @__PURE__ */ jsx9(
2655
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2656
+ /* @__PURE__ */ jsx12(
2040
2657
  ScrubButton,
2041
2658
  {
2042
2659
  label: "\u25C0",
@@ -2044,7 +2661,7 @@ function TimeTravelDebugger({
2044
2661
  onClick: () => setSelectedIndex((i) => Math.max(0, i - 1))
2045
2662
  }
2046
2663
  ),
2047
- /* @__PURE__ */ jsx9(
2664
+ /* @__PURE__ */ jsx12(
2048
2665
  "input",
2049
2666
  {
2050
2667
  type: "range",
@@ -2060,7 +2677,7 @@ function TimeTravelDebugger({
2060
2677
  }
2061
2678
  }
2062
2679
  ),
2063
- /* @__PURE__ */ jsx9(
2680
+ /* @__PURE__ */ jsx12(
2064
2681
  ScrubButton,
2065
2682
  {
2066
2683
  label: "\u25B6",
@@ -2068,7 +2685,7 @@ function TimeTravelDebugger({
2068
2685
  onClick: () => setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))
2069
2686
  }
2070
2687
  ),
2071
- /* @__PURE__ */ jsxs8(
2688
+ /* @__PURE__ */ jsxs9(
2072
2689
  "span",
2073
2690
  {
2074
2691
  style: {
@@ -2088,7 +2705,7 @@ function TimeTravelDebugger({
2088
2705
  ]
2089
2706
  }
2090
2707
  ),
2091
- /* @__PURE__ */ jsxs8(
2708
+ /* @__PURE__ */ jsxs9(
2092
2709
  "div",
2093
2710
  {
2094
2711
  style: {
@@ -2098,7 +2715,7 @@ function TimeTravelDebugger({
2098
2715
  overflow: "hidden"
2099
2716
  },
2100
2717
  children: [
2101
- /* @__PURE__ */ jsx9(
2718
+ /* @__PURE__ */ jsx12(
2102
2719
  "div",
2103
2720
  {
2104
2721
  style: {
@@ -2110,8 +2727,8 @@ function TimeTravelDebugger({
2110
2727
  children: chart
2111
2728
  }
2112
2729
  ),
2113
- /* @__PURE__ */ jsxs8("div", { style: { flex: 1, overflow: "auto" }, children: [
2114
- /* @__PURE__ */ jsx9(
2730
+ /* @__PURE__ */ jsxs9("div", { style: { flex: 1, overflow: "auto" }, children: [
2731
+ /* @__PURE__ */ jsx12(
2115
2732
  MemoryInspector,
2116
2733
  {
2117
2734
  snapshots,
@@ -2119,7 +2736,7 @@ function TimeTravelDebugger({
2119
2736
  size
2120
2737
  }
2121
2738
  ),
2122
- /* @__PURE__ */ jsx9(
2739
+ /* @__PURE__ */ jsx12(
2123
2740
  "div",
2124
2741
  {
2125
2742
  style: {
@@ -2129,7 +2746,7 @@ function TimeTravelDebugger({
2129
2746
  }
2130
2747
  }
2131
2748
  ),
2132
- /* @__PURE__ */ jsx9(
2749
+ /* @__PURE__ */ jsx12(
2133
2750
  NarrativeLog,
2134
2751
  {
2135
2752
  snapshots,
@@ -2141,7 +2758,7 @@ function TimeTravelDebugger({
2141
2758
  ]
2142
2759
  }
2143
2760
  ),
2144
- showGantt && /* @__PURE__ */ jsx9(
2761
+ showGantt && /* @__PURE__ */ jsx12(
2145
2762
  "div",
2146
2763
  {
2147
2764
  style: {
@@ -2149,7 +2766,7 @@ function TimeTravelDebugger({
2149
2766
  background: theme.bgSecondary,
2150
2767
  flexShrink: 0
2151
2768
  },
2152
- children: /* @__PURE__ */ jsx9(
2769
+ children: /* @__PURE__ */ jsx12(
2153
2770
  GanttTimeline,
2154
2771
  {
2155
2772
  snapshots,
@@ -2169,7 +2786,7 @@ function ScrubButton({
2169
2786
  disabled,
2170
2787
  onClick
2171
2788
  }) {
2172
- return /* @__PURE__ */ jsx9(
2789
+ return /* @__PURE__ */ jsx12(
2173
2790
  "button",
2174
2791
  {
2175
2792
  onClick,
@@ -2196,13 +2813,13 @@ function ScrubButton({
2196
2813
 
2197
2814
  // src/components/FlowchartView/SubflowBreadcrumb.tsx
2198
2815
  import { memo as memo2 } from "react";
2199
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2816
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
2200
2817
  var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
2201
2818
  breadcrumbs,
2202
2819
  onNavigate
2203
2820
  }) {
2204
2821
  if (breadcrumbs.length <= 1) return null;
2205
- return /* @__PURE__ */ jsx10(
2822
+ return /* @__PURE__ */ jsx13(
2206
2823
  "div",
2207
2824
  {
2208
2825
  style: {
@@ -2219,10 +2836,10 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
2219
2836
  },
2220
2837
  children: breadcrumbs.map((crumb, i) => {
2221
2838
  const isLast = i === breadcrumbs.length - 1;
2222
- return /* @__PURE__ */ jsxs9("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2223
- i > 0 && /* @__PURE__ */ jsx10("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
2224
- isLast ? /* @__PURE__ */ jsxs9("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2225
- /* @__PURE__ */ jsx10(
2839
+ return /* @__PURE__ */ jsxs10("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2840
+ i > 0 && /* @__PURE__ */ jsx13("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
2841
+ isLast ? /* @__PURE__ */ jsxs10("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2842
+ /* @__PURE__ */ jsx13(
2226
2843
  "span",
2227
2844
  {
2228
2845
  style: {
@@ -2232,7 +2849,7 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
2232
2849
  children: crumb.label
2233
2850
  }
2234
2851
  ),
2235
- crumb.description && /* @__PURE__ */ jsxs9(
2852
+ crumb.description && /* @__PURE__ */ jsxs10(
2236
2853
  "span",
2237
2854
  {
2238
2855
  style: {
@@ -2246,7 +2863,7 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
2246
2863
  ]
2247
2864
  }
2248
2865
  )
2249
- ] }) : /* @__PURE__ */ jsx10(
2866
+ ] }) : /* @__PURE__ */ jsx13(
2250
2867
  "button",
2251
2868
  {
2252
2869
  onClick: () => onNavigate(i),
@@ -2345,7 +2962,7 @@ function useSubflowNavigation(rootGraph) {
2345
2962
 
2346
2963
  // src/components/FlowchartView/SubflowTree.tsx
2347
2964
  import { memo as memo3, useState as useState7, useCallback as useCallback5, useMemo as useMemo7 } from "react";
2348
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2965
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
2349
2966
  function graphToSubflowEntries(graph) {
2350
2967
  if (!graph?.nodes?.length) return [];
2351
2968
  const entries = [];
@@ -2378,8 +2995,8 @@ var TreeNode = memo3(function TreeNode2({
2378
2995
  }
2379
2996
  onNodeSelect?.(entry.name, !!entry.isSubflow);
2380
2997
  }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
2381
- return /* @__PURE__ */ jsxs10(Fragment2, { children: [
2382
- /* @__PURE__ */ jsxs10(
2998
+ return /* @__PURE__ */ jsxs11(Fragment2, { children: [
2999
+ /* @__PURE__ */ jsxs11(
2383
3000
  "button",
2384
3001
  {
2385
3002
  onClick: handleClick,
@@ -2410,7 +3027,7 @@ var TreeNode = memo3(function TreeNode2({
2410
3027
  }
2411
3028
  },
2412
3029
  children: [
2413
- hasChildren ? /* @__PURE__ */ jsx11(
3030
+ hasChildren ? /* @__PURE__ */ jsx14(
2414
3031
  "span",
2415
3032
  {
2416
3033
  style: {
@@ -2425,8 +3042,8 @@ var TreeNode = memo3(function TreeNode2({
2425
3042
  },
2426
3043
  children: "\u25B6"
2427
3044
  }
2428
- ) : /* @__PURE__ */ jsx11("span", { style: { width: 12, flexShrink: 0 } }),
2429
- /* @__PURE__ */ jsx11(
3045
+ ) : /* @__PURE__ */ jsx14("span", { style: { width: 12, flexShrink: 0 } }),
3046
+ /* @__PURE__ */ jsx14(
2430
3047
  "span",
2431
3048
  {
2432
3049
  style: {
@@ -2438,8 +3055,8 @@ var TreeNode = memo3(function TreeNode2({
2438
3055
  }
2439
3056
  }
2440
3057
  ),
2441
- /* @__PURE__ */ jsxs10("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
2442
- /* @__PURE__ */ jsxs10(
3058
+ /* @__PURE__ */ jsxs11("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
3059
+ /* @__PURE__ */ jsxs11(
2443
3060
  "span",
2444
3061
  {
2445
3062
  style: {
@@ -2451,11 +3068,11 @@ var TreeNode = memo3(function TreeNode2({
2451
3068
  },
2452
3069
  children: [
2453
3070
  entry.name,
2454
- entry.isSubflow && /* @__PURE__ */ jsx11("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
3071
+ entry.isSubflow && /* @__PURE__ */ jsx14("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
2455
3072
  ]
2456
3073
  }
2457
3074
  ),
2458
- entry.description && /* @__PURE__ */ jsx11(
3075
+ entry.description && /* @__PURE__ */ jsx14(
2459
3076
  "span",
2460
3077
  {
2461
3078
  style: {
@@ -2472,7 +3089,7 @@ var TreeNode = memo3(function TreeNode2({
2472
3089
  ]
2473
3090
  }
2474
3091
  ),
2475
- hasChildren && expanded && /* @__PURE__ */ jsx11("div", { children: entry.children.map((child, i) => /* @__PURE__ */ jsx11(
3092
+ hasChildren && expanded && /* @__PURE__ */ jsx14("div", { children: entry.children.map((child, i) => /* @__PURE__ */ jsx14(
2476
3093
  TreeNode2,
2477
3094
  {
2478
3095
  entry: child,
@@ -2486,7 +3103,7 @@ var TreeNode = memo3(function TreeNode2({
2486
3103
  ] });
2487
3104
  });
2488
3105
  var SectionLabel = memo3(function SectionLabel2({ children }) {
2489
- return /* @__PURE__ */ jsx11(
3106
+ return /* @__PURE__ */ jsx14(
2490
3107
  "div",
2491
3108
  {
2492
3109
  style: {
@@ -2512,7 +3129,7 @@ var SubflowTree = memo3(function SubflowTree2({
2512
3129
  }) {
2513
3130
  const subflowStages = useMemo7(() => graphToSubflowEntries(graph), [graph]);
2514
3131
  if (subflowStages.length === 0) return null;
2515
- return /* @__PURE__ */ jsxs10(
3132
+ return /* @__PURE__ */ jsxs11(
2516
3133
  "div",
2517
3134
  {
2518
3135
  className,
@@ -2530,8 +3147,8 @@ var SubflowTree = memo3(function SubflowTree2({
2530
3147
  ...style
2531
3148
  },
2532
3149
  children: [
2533
- !unstyled && /* @__PURE__ */ jsx11(SectionLabel, { children: "Subflows" }),
2534
- subflowStages.map((entry, i) => /* @__PURE__ */ jsx11(
3150
+ !unstyled && /* @__PURE__ */ jsx14(SectionLabel, { children: "Subflows" }),
3151
+ subflowStages.map((entry, i) => /* @__PURE__ */ jsx14(
2535
3152
  TreeNode,
2536
3153
  {
2537
3154
  entry,
@@ -2559,9 +3176,13 @@ function asRuntimeStageId(s) {
2559
3176
  function walkSubflowSpecInto(spec, subflowPath, sink) {
2560
3177
  walkNode(spec, subflowPath, sink, /* @__PURE__ */ new Set());
2561
3178
  }
3179
+ function qid(subflowPath, localId) {
3180
+ return `${subflowPath}/${localId}`;
3181
+ }
2562
3182
  function walkNode(node, subflowPath, sink, visited) {
2563
- if (visited.has(node.id)) return;
2564
- visited.add(node.id);
3183
+ const fullId = qid(subflowPath, node.id);
3184
+ if (visited.has(fullId)) return;
3185
+ visited.add(fullId);
2565
3186
  if (node.isLoopReference) return;
2566
3187
  if (node.isSubflowRoot && node.subflowId !== void 0 && node.subflowStructure) {
2567
3188
  const nestedPath = `${subflowPath}/${node.subflowId}`;
@@ -2572,7 +3193,6 @@ function walkNode(node, subflowPath, sink, visited) {
2572
3193
  const isFork = type === "fork";
2573
3194
  const isStreaming = type === "streaming";
2574
3195
  const isSubflow = !!node.isSubflowRoot;
2575
- const stageId = asStageId(node.id);
2576
3196
  const data = {
2577
3197
  label: node.name,
2578
3198
  isDecider,
@@ -2589,7 +3209,7 @@ function walkNode(node, subflowPath, sink, visited) {
2589
3209
  if (node.isLazy === true) data.isLazy = true;
2590
3210
  if (node.isPausable === true) data.isPausable = true;
2591
3211
  sink.upsertNode({
2592
- id: node.id,
3212
+ id: asStageId(fullId),
2593
3213
  type: "stage",
2594
3214
  position: { x: 0, y: 0 },
2595
3215
  data
@@ -2597,13 +3217,14 @@ function walkNode(node, subflowPath, sink, visited) {
2597
3217
  if (node.children && node.children.length > 0) {
2598
3218
  const edgeKind = type === "fork" ? "fork-branch" : "decision-branch";
2599
3219
  for (const child of node.children) {
2600
- const edgeId = `${node.id}->${child.id}:${edgeKind}${edgeKind === "decision-branch" ? `:${child.id}` : ""}`;
3220
+ const childFullId = qid(subflowPath, child.id);
3221
+ const edgeId = `${fullId}->${childFullId}:${edgeKind}${edgeKind === "decision-branch" ? `:${child.id}` : ""}`;
2601
3222
  const edgeData = { kind: edgeKind };
2602
3223
  if (edgeKind === "decision-branch") edgeData.label = child.id;
2603
3224
  const edge = {
2604
3225
  id: edgeId,
2605
- source: node.id,
2606
- target: child.id,
3226
+ source: fullId,
3227
+ target: childFullId,
2607
3228
  data: edgeData
2608
3229
  };
2609
3230
  if (edgeKind === "decision-branch") edge.label = child.id;
@@ -2613,24 +3234,25 @@ function walkNode(node, subflowPath, sink, visited) {
2613
3234
  }
2614
3235
  if (node.next) {
2615
3236
  if (node.next.isLoopReference && node.loopTarget) {
3237
+ const loopFullId = qid(subflowPath, node.loopTarget);
2616
3238
  sink.pushEdge({
2617
- id: `${node.id}->${node.loopTarget}:loop`,
2618
- source: node.id,
2619
- target: node.loopTarget,
3239
+ id: `${fullId}->${loopFullId}:loop`,
3240
+ source: fullId,
3241
+ target: loopFullId,
2620
3242
  data: { kind: "loop" }
2621
3243
  });
2622
3244
  } else {
2623
- const edgeId = `${node.id}->${node.next.id}:next`;
3245
+ const nextFullId = qid(subflowPath, node.next.id);
3246
+ const edgeId = `${fullId}->${nextFullId}:next`;
2624
3247
  sink.pushEdge({
2625
3248
  id: edgeId,
2626
- source: node.id,
2627
- target: node.next.id,
3249
+ source: fullId,
3250
+ target: nextFullId,
2628
3251
  data: { kind: "next" }
2629
3252
  });
2630
3253
  walkNode(node.next, subflowPath, sink, visited);
2631
3254
  }
2632
3255
  }
2633
- void stageId;
2634
3256
  }
2635
3257
 
2636
3258
  // src/components/FlowchartView/traceStructureRecorder.ts
@@ -2826,6 +3448,361 @@ function createTraceStructureRecorder(options = {}) {
2826
3448
  };
2827
3449
  }
2828
3450
 
3451
+ // src/components/SlotPillNode/SlotPillNode.tsx
3452
+ import { Handle as Handle3, Position as Position4 } from "@xyflow/react";
3453
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
3454
+ var C2 = rawDefaults.colors;
3455
+ function SlotPillNode({ data }) {
3456
+ const d = data;
3457
+ const lit = !!(d.active || d.selected);
3458
+ const accent = lit ? C2.primary : d.done ? C2.success : C2.textMuted;
3459
+ const opacity = d.dimmed && !lit ? 0.45 : 1;
3460
+ return /* @__PURE__ */ jsxs12(
3461
+ "div",
3462
+ {
3463
+ style: {
3464
+ width: "100%",
3465
+ height: "100%",
3466
+ boxSizing: "border-box",
3467
+ display: "flex",
3468
+ alignItems: "center",
3469
+ gap: 8,
3470
+ padding: "0 12px",
3471
+ borderRadius: 999,
3472
+ // full pill
3473
+ border: `1.5px solid ${lit ? C2.primary : C2.border}`,
3474
+ background: lit ? "rgba(99, 102, 241, 0.14)" : "rgba(148, 163, 184, 0.06)",
3475
+ boxShadow: lit ? `0 0 0 2px rgba(99,102,241,0.25)` : "none",
3476
+ opacity,
3477
+ fontSize: 12,
3478
+ fontWeight: 600,
3479
+ color: lit ? C2.textPrimary : C2.textSecondary,
3480
+ whiteSpace: "nowrap",
3481
+ overflow: "hidden",
3482
+ transition: "opacity 120ms, box-shadow 120ms, border-color 120ms"
3483
+ },
3484
+ title: d.label,
3485
+ children: [
3486
+ /* @__PURE__ */ jsx15(
3487
+ "span",
3488
+ {
3489
+ "aria-hidden": true,
3490
+ style: {
3491
+ flexShrink: 0,
3492
+ width: 8,
3493
+ height: 8,
3494
+ borderRadius: "50%",
3495
+ background: accent
3496
+ }
3497
+ }
3498
+ ),
3499
+ d.icon ? /* @__PURE__ */ jsx15("span", { "aria-hidden": true, style: { flexShrink: 0 }, children: d.icon }) : null,
3500
+ /* @__PURE__ */ jsx15("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: d.label }),
3501
+ /* @__PURE__ */ jsx15(Handle3, { type: "target", position: Position4.Top, style: { opacity: 0 } }),
3502
+ /* @__PURE__ */ jsx15(Handle3, { type: "source", position: Position4.Bottom, style: { opacity: 0 } })
3503
+ ]
3504
+ }
3505
+ );
3506
+ }
3507
+
3508
+ // src/components/FlowchartView/_internal/snapLinearSuccessors.ts
3509
+ function snapLinearSuccessors(graph, options = {}) {
3510
+ if (graph.nodes.length === 0) return graph;
3511
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
3512
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
3513
+ const byId = /* @__PURE__ */ new Map();
3514
+ const width = /* @__PURE__ */ new Map();
3515
+ for (const n of graph.nodes) {
3516
+ byId.set(n.id, n);
3517
+ width.set(n.id, sizeOf(n, fallbackW, fallbackH, options.nodeSize).width);
3518
+ }
3519
+ const preds = /* @__PURE__ */ new Map();
3520
+ const outDegree = /* @__PURE__ */ new Map();
3521
+ const seenEdge = /* @__PURE__ */ new Set();
3522
+ for (const e of graph.edges) {
3523
+ if (e.data?.kind === "loop") continue;
3524
+ if (!byId.has(e.source) || !byId.has(e.target)) continue;
3525
+ const key = `${e.source}\0${e.target}`;
3526
+ if (seenEdge.has(key)) continue;
3527
+ seenEdge.add(key);
3528
+ const list = preds.get(e.target);
3529
+ if (list) list.push(e.source);
3530
+ else preds.set(e.target, [e.source]);
3531
+ outDegree.set(e.source, (outDegree.get(e.source) ?? 0) + 1);
3532
+ }
3533
+ const workingX = /* @__PURE__ */ new Map();
3534
+ for (const n of graph.nodes) workingX.set(n.id, n.position.x);
3535
+ const centerX = (id) => workingX.get(id) + width.get(id) / 2;
3536
+ const order = [...graph.nodes].sort(
3537
+ (a, b) => a.position.y - b.position.y || a.position.x - b.position.x || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)
3538
+ );
3539
+ for (const n of order) {
3540
+ const p = preds.get(n.id);
3541
+ if (!p || p.length !== 1) continue;
3542
+ const pid = p[0];
3543
+ if ((outDegree.get(pid) ?? 0) !== 1) continue;
3544
+ const P = byId.get(pid);
3545
+ if ((n.parentId ?? void 0) !== (P.parentId ?? void 0)) continue;
3546
+ workingX.set(n.id, centerX(pid) - width.get(n.id) / 2);
3547
+ }
3548
+ const nodes = graph.nodes.map((n) => {
3549
+ const nx = workingX.get(n.id);
3550
+ return nx === n.position.x ? n : { ...n, position: { x: nx, y: n.position.y } };
3551
+ });
3552
+ return { nodes, edges: graph.edges };
3553
+ }
3554
+ function createSnappedDagreLayout(base, options = {}) {
3555
+ return (graph) => snapLinearSuccessors(base(graph), options);
3556
+ }
3557
+
3558
+ // src/components/FlowchartView/_internal/traceGroupLayout.ts
3559
+ function buildAdjacency(graph, fallbackW, fallbackH, nodeSize) {
3560
+ const preds = /* @__PURE__ */ new Map();
3561
+ const branchSuccs = /* @__PURE__ */ new Map();
3562
+ const width = /* @__PURE__ */ new Map();
3563
+ const height = /* @__PURE__ */ new Map();
3564
+ const resolvedStyle = /* @__PURE__ */ new Map();
3565
+ const ids = /* @__PURE__ */ new Set();
3566
+ for (const n of graph.nodes) {
3567
+ ids.add(n.id);
3568
+ const s = sizeOf(n, fallbackW, fallbackH, nodeSize);
3569
+ width.set(n.id, s.width);
3570
+ height.set(n.id, s.height);
3571
+ const resolved = nodeSize?.(n);
3572
+ if (resolved && resolved.width === s.width && resolved.height === s.height) {
3573
+ resolvedStyle.set(n.id, resolved);
3574
+ }
3575
+ preds.set(n.id, []);
3576
+ branchSuccs.set(n.id, []);
3577
+ }
3578
+ const seen = /* @__PURE__ */ new Set();
3579
+ for (const e of graph.edges) {
3580
+ if (e.data?.kind === "loop") continue;
3581
+ if (!ids.has(e.source) || !ids.has(e.target)) continue;
3582
+ const key = `${e.source}\0${e.target}`;
3583
+ if (seen.has(key)) continue;
3584
+ seen.add(key);
3585
+ preds.get(e.target).push(e.source);
3586
+ if (e.data?.kind === "fork-branch" || e.data?.kind === "decision-branch") {
3587
+ branchSuccs.get(e.source).push(e.target);
3588
+ }
3589
+ }
3590
+ return { preds, branchSuccs, width, height, resolvedStyle };
3591
+ }
3592
+ function assignRanks(preds, ids) {
3593
+ const rank = /* @__PURE__ */ new Map();
3594
+ const inProgress = /* @__PURE__ */ new Set();
3595
+ const visit = (id) => {
3596
+ const memo4 = rank.get(id);
3597
+ if (memo4 !== void 0) return memo4;
3598
+ if (inProgress.has(id)) return 0;
3599
+ inProgress.add(id);
3600
+ const ps = preds.get(id) ?? [];
3601
+ let r = 0;
3602
+ for (const p of ps) {
3603
+ const pr = visit(p);
3604
+ if (pr + 1 > r) r = pr + 1;
3605
+ }
3606
+ inProgress.delete(id);
3607
+ rank.set(id, r);
3608
+ return r;
3609
+ };
3610
+ for (const id of ids) visit(id);
3611
+ return rank;
3612
+ }
3613
+ function spanCenter(ids, center, width) {
3614
+ let left = Infinity;
3615
+ let right = -Infinity;
3616
+ for (const id of ids) {
3617
+ const c = center.get(id);
3618
+ if (c === void 0) continue;
3619
+ const w = width.get(id) ?? 0;
3620
+ if (c - w / 2 < left) left = c - w / 2;
3621
+ if (c + w / 2 > right) right = c + w / 2;
3622
+ }
3623
+ if (!Number.isFinite(left)) return 0;
3624
+ return (left + right) / 2;
3625
+ }
3626
+ function ancestorsOf(start, preds) {
3627
+ const seen = /* @__PURE__ */ new Set();
3628
+ const stack = [start];
3629
+ while (stack.length) {
3630
+ const n = stack.pop();
3631
+ if (seen.has(n)) continue;
3632
+ seen.add(n);
3633
+ for (const p of preds.get(n) ?? []) if (!seen.has(p)) stack.push(p);
3634
+ }
3635
+ return seen;
3636
+ }
3637
+ function lowestCommonAncestor(inputs, preds, rank) {
3638
+ if (inputs.length === 0) return void 0;
3639
+ let common = ancestorsOf(inputs[0], preds);
3640
+ for (let i = 1; i < inputs.length && common.size > 0; i++) {
3641
+ const a = ancestorsOf(inputs[i], preds);
3642
+ common = new Set([...common].filter((x) => a.has(x)));
3643
+ }
3644
+ let best;
3645
+ let bestRank = -Infinity;
3646
+ for (const id of common) {
3647
+ const r = rank.get(id) ?? -Infinity;
3648
+ if (r > bestRank) bestRank = r, best = id;
3649
+ }
3650
+ return best;
3651
+ }
3652
+ function orderBand(ids, preds, center, insertionIndex, siblingOrder) {
3653
+ if (siblingOrder && ids.length > 1) {
3654
+ const parents = new Set(ids.map((id) => preds.get(id)?.[0]));
3655
+ if (parents.size === 1) {
3656
+ const parent = [...parents][0];
3657
+ if (parent !== void 0) {
3658
+ const ordered = siblingOrder(parent, ids);
3659
+ const used = /* @__PURE__ */ new Set();
3660
+ const out = [];
3661
+ for (const id of ordered) if (ids.includes(id) && !used.has(id)) out.push(id), used.add(id);
3662
+ for (const id of ids) if (!used.has(id)) out.push(id);
3663
+ return out;
3664
+ }
3665
+ }
3666
+ }
3667
+ return [...ids].sort((a, b) => {
3668
+ const pa = preds.get(a)?.[0];
3669
+ const pb = preds.get(b)?.[0];
3670
+ const ca = pa !== void 0 ? center.get(pa) : void 0;
3671
+ const cb = pb !== void 0 ? center.get(pb) : void 0;
3672
+ if (ca !== void 0 && cb !== void 0 && ca !== cb) return ca - cb;
3673
+ return (insertionIndex.get(a) ?? 0) - (insertionIndex.get(b) ?? 0);
3674
+ });
3675
+ }
3676
+ function traceGroupLayout(graph, options = {}) {
3677
+ if (graph.nodes.length === 0) return { nodes: graph.nodes, edges: graph.edges };
3678
+ if (graph.nodes.length === 1) {
3679
+ const only = graph.nodes[0];
3680
+ return { nodes: [{ ...only, position: { x: 0, y: 0 } }], edges: graph.edges };
3681
+ }
3682
+ const rankSep = options.rankSep ?? 80;
3683
+ const nodeSep = options.nodeSep ?? 60;
3684
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
3685
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
3686
+ const mergeCentering = options.enableMergeCentering ?? true;
3687
+ const mergeAlign = options.mergeAlign ?? "span";
3688
+ const ids = graph.nodes.map((n) => n.id);
3689
+ const insertionIndex = new Map(ids.map((id, i) => [id, i]));
3690
+ const { preds, branchSuccs, width, height, resolvedStyle } = buildAdjacency(
3691
+ graph,
3692
+ fallbackW,
3693
+ fallbackH,
3694
+ options.nodeSize
3695
+ );
3696
+ const rank = assignRanks(preds, ids);
3697
+ let maxRank = 0;
3698
+ for (const r of rank.values()) if (r > maxRank) maxRank = r;
3699
+ for (const id of ids) if (!rank.has(id)) rank.set(id, maxRank + 1);
3700
+ maxRank = 0;
3701
+ for (const r of rank.values()) if (r > maxRank) maxRank = r;
3702
+ const byRank = /* @__PURE__ */ new Map();
3703
+ const bandMaxH = /* @__PURE__ */ new Map();
3704
+ for (const id of ids) {
3705
+ const r = rank.get(id);
3706
+ (byRank.get(r) ?? byRank.set(r, []).get(r)).push(id);
3707
+ bandMaxH.set(r, Math.max(bandMaxH.get(r) ?? 0, height.get(id)));
3708
+ }
3709
+ const bandTop = /* @__PURE__ */ new Map();
3710
+ let yAcc = 0;
3711
+ for (let r = 0; r <= maxRank; r++) {
3712
+ bandTop.set(r, yAcc);
3713
+ yAcc += (bandMaxH.get(r) ?? fallbackH) + rankSep;
3714
+ }
3715
+ const center = /* @__PURE__ */ new Map();
3716
+ const mergeCenterX = (ps) => {
3717
+ if (mergeAlign === "fork-origin") {
3718
+ const lca = lowestCommonAncestor(ps, preds, rank);
3719
+ const lcaC = lca !== void 0 ? center.get(lca) : void 0;
3720
+ if (lcaC !== void 0) return lcaC;
3721
+ }
3722
+ return spanCenter(ps, center, width);
3723
+ };
3724
+ for (let r = 0; r <= maxRank; r++) {
3725
+ const band = orderBand(byRank.get(r) ?? [], preds, center, insertionIndex, options.siblingOrder);
3726
+ let cursor = -Infinity;
3727
+ let i = 0;
3728
+ while (i < band.length) {
3729
+ const id = band[i];
3730
+ const ps = preds.get(id) ?? [];
3731
+ const parent = ps.length === 1 ? ps[0] : void 0;
3732
+ const parentBranches = parent !== void 0 ? branchSuccs.get(parent) ?? [] : [];
3733
+ const isForkChild = parent !== void 0 && parentBranches.length >= 2 && parentBranches.includes(id);
3734
+ if (isForkChild) {
3735
+ const run = [];
3736
+ let j = i;
3737
+ while (j < band.length) {
3738
+ const cand = band[j];
3739
+ const cps = preds.get(cand) ?? [];
3740
+ if (cps.length === 1 && cps[0] === parent && parentBranches.includes(cand)) run.push(cand), j++;
3741
+ else break;
3742
+ }
3743
+ const totalW = run.reduce((s, rid) => s + width.get(rid), 0) + (run.length - 1) * nodeSep;
3744
+ let left = (center.get(parent) ?? 0) - totalW / 2;
3745
+ if (cursor !== -Infinity && left < cursor) left = cursor;
3746
+ let x = left;
3747
+ for (const rid of run) {
3748
+ const w = width.get(rid);
3749
+ center.set(rid, x + w / 2);
3750
+ x += w + nodeSep;
3751
+ }
3752
+ cursor = x;
3753
+ i = j;
3754
+ } else {
3755
+ const w = width.get(id);
3756
+ let desired;
3757
+ if (ps.length === 0) desired = (cursor === -Infinity ? 0 : cursor) + w / 2;
3758
+ else if (ps.length === 1) desired = center.get(ps[0]) ?? 0;
3759
+ else desired = mergeCenterX(ps);
3760
+ const cursorCenter = cursor === -Infinity ? -Infinity : cursor + w / 2;
3761
+ const c = Math.max(cursorCenter, desired);
3762
+ center.set(id, c);
3763
+ cursor = c + w / 2 + nodeSep;
3764
+ i++;
3765
+ }
3766
+ }
3767
+ }
3768
+ if (mergeCentering) {
3769
+ for (let r = maxRank; r >= 1; r--) {
3770
+ for (const id of byRank.get(r) ?? []) {
3771
+ const ps = preds.get(id) ?? [];
3772
+ if (ps.length > 1) center.set(id, mergeCenterX(ps));
3773
+ }
3774
+ }
3775
+ }
3776
+ const centerById = center;
3777
+ const positioned = graph.nodes.map((n) => {
3778
+ const r = rank.get(n.id);
3779
+ const w = width.get(n.id);
3780
+ const h = height.get(n.id);
3781
+ let x = (centerById.get(n.id) ?? 0) - w / 2;
3782
+ let y = (bandTop.get(r) ?? 0) + ((bandMaxH.get(r) ?? h) - h) / 2;
3783
+ if (n.parentId) {
3784
+ const pr = rank.get(n.parentId);
3785
+ const pw = width.get(n.parentId);
3786
+ const ph = height.get(n.parentId);
3787
+ if (pr !== void 0 && pw !== void 0 && ph !== void 0) {
3788
+ const parentX = (centerById.get(n.parentId) ?? 0) - pw / 2;
3789
+ const parentY = (bandTop.get(pr) ?? 0) + ((bandMaxH.get(pr) ?? ph) - ph) / 2;
3790
+ x -= parentX;
3791
+ y -= parentY;
3792
+ }
3793
+ }
3794
+ const styleSize = resolvedStyle.get(n.id);
3795
+ if (styleSize) {
3796
+ return { ...n, position: { x, y }, style: { ...n.style ?? {}, width: styleSize.width, height: styleSize.height } };
3797
+ }
3798
+ return { ...n, position: { x, y } };
3799
+ });
3800
+ return { nodes: positioned, edges: graph.edges };
3801
+ }
3802
+ function createTraceGroupLayout(options = {}) {
3803
+ return (graph) => traceGroupLayout(graph, options);
3804
+ }
3805
+
2829
3806
  // src/components/FlowchartView/createNodeViewRecorder.ts
2830
3807
  function baseStageIdOf(runtimeStageId) {
2831
3808
  const hashIdx = runtimeStageId.indexOf("#");
@@ -3336,7 +4313,7 @@ function bfsWalk(index, startId, neighborsOf, options) {
3336
4313
 
3337
4314
  // src/components/FlowchartView/NodeInspector.tsx
3338
4315
  import { useMemo as useMemo9 } from "react";
3339
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
4316
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
3340
4317
  function NodeInspector({
3341
4318
  index,
3342
4319
  selectedId,
@@ -3355,7 +4332,7 @@ function NodeInspector({
3355
4332
  [index, view, onlyVisited]
3356
4333
  );
3357
4334
  if (!view) {
3358
- return /* @__PURE__ */ jsx12(
4335
+ return /* @__PURE__ */ jsx16(
3359
4336
  "div",
3360
4337
  {
3361
4338
  className,
@@ -3369,7 +4346,7 @@ function NodeInspector({
3369
4346
  }
3370
4347
  );
3371
4348
  }
3372
- return /* @__PURE__ */ jsxs11(
4349
+ return /* @__PURE__ */ jsxs13(
3373
4350
  "div",
3374
4351
  {
3375
4352
  className,
@@ -3381,9 +4358,9 @@ function NodeInspector({
3381
4358
  ...style
3382
4359
  },
3383
4360
  children: [
3384
- /* @__PURE__ */ jsxs11("div", { style: { marginBottom: 16 }, children: [
3385
- /* @__PURE__ */ jsx12("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.label }),
3386
- /* @__PURE__ */ jsxs11("div", { style: { fontSize: 11, fontFamily: "monospace", color: theme.textMuted, marginTop: 2 }, children: [
4361
+ /* @__PURE__ */ jsxs13("div", { style: { marginBottom: 16 }, children: [
4362
+ /* @__PURE__ */ jsx16("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.label }),
4363
+ /* @__PURE__ */ jsxs13("div", { style: { fontSize: 11, fontFamily: "monospace", color: theme.textMuted, marginTop: 2 }, children: [
3387
4364
  view.stageId,
3388
4365
  " \xB7 ",
3389
4366
  view.type,
@@ -3393,42 +4370,42 @@ function NodeInspector({
3393
4370
  view.isStreaming && " \xB7 streaming",
3394
4371
  view.isPausable && " \xB7 pausable"
3395
4372
  ] }),
3396
- view.description && /* @__PURE__ */ jsx12("div", { style: { fontSize: 12, color: theme.textSecondary, marginTop: 6 }, children: view.description })
4373
+ view.description && /* @__PURE__ */ jsx16("div", { style: { fontSize: 12, color: theme.textSecondary, marginTop: 6 }, children: view.description })
3397
4374
  ] }),
3398
- /* @__PURE__ */ jsxs11(Section, { title: "Runtime", children: [
3399
- /* @__PURE__ */ jsx12(Row, { label: "Visited", value: view.visitedInRun ? "yes" : "no" }),
3400
- view.visitedInRun && /* @__PURE__ */ jsxs11(Fragment3, { children: [
3401
- /* @__PURE__ */ jsx12(Row, { label: "Executions", value: String(view.executionCount) }),
3402
- view.firstExecutedAt !== null && /* @__PURE__ */ jsx12(Row, { label: "First at", value: `${view.firstExecutedAt.toFixed(1)}ms` }),
3403
- view.lastExecutedAt !== null && /* @__PURE__ */ jsx12(Row, { label: "Last at", value: `${view.lastExecutedAt.toFixed(1)}ms` }),
3404
- view.totalDurationMs > 0 && /* @__PURE__ */ jsx12(Row, { label: "Total", value: `${view.totalDurationMs.toFixed(1)}ms` }),
3405
- view.errorCount > 0 && /* @__PURE__ */ jsx12(Row, { label: "Errors", value: String(view.errorCount), valueColor: theme.error })
4375
+ /* @__PURE__ */ jsxs13(Section, { title: "Runtime", children: [
4376
+ /* @__PURE__ */ jsx16(Row, { label: "Visited", value: view.visitedInRun ? "yes" : "no" }),
4377
+ view.visitedInRun && /* @__PURE__ */ jsxs13(Fragment3, { children: [
4378
+ /* @__PURE__ */ jsx16(Row, { label: "Executions", value: String(view.executionCount) }),
4379
+ view.firstExecutedAt !== null && /* @__PURE__ */ jsx16(Row, { label: "First at", value: `${view.firstExecutedAt.toFixed(1)}ms` }),
4380
+ view.lastExecutedAt !== null && /* @__PURE__ */ jsx16(Row, { label: "Last at", value: `${view.lastExecutedAt.toFixed(1)}ms` }),
4381
+ view.totalDurationMs > 0 && /* @__PURE__ */ jsx16(Row, { label: "Total", value: `${view.totalDurationMs.toFixed(1)}ms` }),
4382
+ view.errorCount > 0 && /* @__PURE__ */ jsx16(Row, { label: "Errors", value: String(view.errorCount), valueColor: theme.error })
3406
4383
  ] })
3407
4384
  ] }),
3408
- prevChain.length > 1 && /* @__PURE__ */ jsx12(Section, { title: `Prev chain (${prevChain.length - 1} hops)`, children: /* @__PURE__ */ jsx12(Crumbs, { nodes: prevChain.slice(0, -1), onClick: onNavigate }) }),
3409
- view.prevIds.length > 1 && /* @__PURE__ */ jsx12(Section, { title: "Multiple prev (convergence)", children: /* @__PURE__ */ jsx12(
4385
+ prevChain.length > 1 && /* @__PURE__ */ jsx16(Section, { title: `Prev chain (${prevChain.length - 1} hops)`, children: /* @__PURE__ */ jsx16(Crumbs, { nodes: prevChain.slice(0, -1), onClick: onNavigate }) }),
4386
+ view.prevIds.length > 1 && /* @__PURE__ */ jsx16(Section, { title: "Multiple prev (convergence)", children: /* @__PURE__ */ jsx16(
3410
4387
  Crumbs,
3411
4388
  {
3412
4389
  nodes: view.prevIds.map((id) => index.byStageId.get(id)).filter((n) => n !== void 0),
3413
4390
  onClick: onNavigate
3414
4391
  }
3415
4392
  ) }),
3416
- nextChain.length > 1 && /* @__PURE__ */ jsx12(Section, { title: `Next chain (${nextChain.length - 1} hops)`, children: /* @__PURE__ */ jsx12(Crumbs, { nodes: nextChain.slice(1), onClick: onNavigate }) }),
3417
- view.nextIds.length > 1 && /* @__PURE__ */ jsx12(Section, { title: "Multiple next (fork/decider)", children: /* @__PURE__ */ jsx12(
4393
+ nextChain.length > 1 && /* @__PURE__ */ jsx16(Section, { title: `Next chain (${nextChain.length - 1} hops)`, children: /* @__PURE__ */ jsx16(Crumbs, { nodes: nextChain.slice(1), onClick: onNavigate }) }),
4394
+ view.nextIds.length > 1 && /* @__PURE__ */ jsx16(Section, { title: "Multiple next (fork/decider)", children: /* @__PURE__ */ jsx16(
3418
4395
  Crumbs,
3419
4396
  {
3420
4397
  nodes: view.nextIds.map((id) => index.byStageId.get(id)).filter((n) => n !== void 0),
3421
4398
  onClick: onNavigate
3422
4399
  }
3423
4400
  ) }),
3424
- view.commitRuntimeStageIds.length > 0 && /* @__PURE__ */ jsx12(Section, { title: `Commits (${view.commitRuntimeStageIds.length})`, children: /* @__PURE__ */ jsx12("div", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: view.commitRuntimeStageIds.map((rsid) => /* @__PURE__ */ jsx12("div", { children: rsid }, rsid)) }) })
4401
+ view.commitRuntimeStageIds.length > 0 && /* @__PURE__ */ jsx16(Section, { title: `Commits (${view.commitRuntimeStageIds.length})`, children: /* @__PURE__ */ jsx16("div", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: view.commitRuntimeStageIds.map((rsid) => /* @__PURE__ */ jsx16("div", { children: rsid }, rsid)) }) })
3425
4402
  ]
3426
4403
  }
3427
4404
  );
3428
4405
  }
3429
4406
  function Section({ title, children }) {
3430
- return /* @__PURE__ */ jsxs11("div", { style: { marginBottom: 14 }, children: [
3431
- /* @__PURE__ */ jsx12(
4407
+ return /* @__PURE__ */ jsxs13("div", { style: { marginBottom: 14 }, children: [
4408
+ /* @__PURE__ */ jsx16(
3432
4409
  "div",
3433
4410
  {
3434
4411
  style: {
@@ -3446,15 +4423,15 @@ function Section({ title, children }) {
3446
4423
  ] });
3447
4424
  }
3448
4425
  function Row({ label, value, valueColor }) {
3449
- return /* @__PURE__ */ jsxs11("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 12, padding: "2px 0" }, children: [
3450
- /* @__PURE__ */ jsx12("span", { style: { color: theme.textMuted }, children: label }),
3451
- /* @__PURE__ */ jsx12("span", { style: { color: valueColor ?? theme.textSecondary, fontFamily: "monospace" }, children: value })
4426
+ return /* @__PURE__ */ jsxs13("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 12, padding: "2px 0" }, children: [
4427
+ /* @__PURE__ */ jsx16("span", { style: { color: theme.textMuted }, children: label }),
4428
+ /* @__PURE__ */ jsx16("span", { style: { color: valueColor ?? theme.textSecondary, fontFamily: "monospace" }, children: value })
3452
4429
  ] });
3453
4430
  }
3454
4431
  function Crumbs({ nodes, onClick }) {
3455
4432
  if (nodes.length === 0) return null;
3456
- return /* @__PURE__ */ jsx12("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: nodes.map((n, i) => /* @__PURE__ */ jsxs11("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
3457
- /* @__PURE__ */ jsx12(
4433
+ return /* @__PURE__ */ jsx16("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: nodes.map((n, i) => /* @__PURE__ */ jsxs13("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
4434
+ /* @__PURE__ */ jsx16(
3458
4435
  "button",
3459
4436
  {
3460
4437
  onClick: onClick ? () => onClick(n.stageId) : void 0,
@@ -3471,13 +4448,13 @@ function Crumbs({ nodes, onClick }) {
3471
4448
  children: n.label
3472
4449
  }
3473
4450
  ),
3474
- i < nodes.length - 1 && /* @__PURE__ */ jsx12("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" })
4451
+ i < nodes.length - 1 && /* @__PURE__ */ jsx16("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" })
3475
4452
  ] }, n.stageId)) });
3476
4453
  }
3477
4454
 
3478
4455
  // src/components/FlowchartView/CommitInspector.tsx
3479
4456
  import { useMemo as useMemo10 } from "react";
3480
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
4457
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
3481
4458
  function CommitInspector({
3482
4459
  index,
3483
4460
  selectedRuntimeStageId,
@@ -3491,7 +4468,7 @@ function CommitInspector({
3491
4468
  [index, view]
3492
4469
  );
3493
4470
  if (!view) {
3494
- return /* @__PURE__ */ jsx13(
4471
+ return /* @__PURE__ */ jsx17(
3495
4472
  "div",
3496
4473
  {
3497
4474
  className,
@@ -3505,7 +4482,7 @@ function CommitInspector({
3505
4482
  }
3506
4483
  );
3507
4484
  }
3508
- return /* @__PURE__ */ jsxs12(
4485
+ return /* @__PURE__ */ jsxs14(
3509
4486
  "div",
3510
4487
  {
3511
4488
  className,
@@ -3517,9 +4494,9 @@ function CommitInspector({
3517
4494
  ...style
3518
4495
  },
3519
4496
  children: [
3520
- /* @__PURE__ */ jsxs12("div", { style: { marginBottom: 16 }, children: [
3521
- /* @__PURE__ */ jsx13("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.stageId }),
3522
- /* @__PURE__ */ jsxs12(
4497
+ /* @__PURE__ */ jsxs14("div", { style: { marginBottom: 16 }, children: [
4498
+ /* @__PURE__ */ jsx17("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.stageId }),
4499
+ /* @__PURE__ */ jsxs14(
3523
4500
  "div",
3524
4501
  {
3525
4502
  style: {
@@ -3536,15 +4513,15 @@ function CommitInspector({
3536
4513
  }
3537
4514
  )
3538
4515
  ] }),
3539
- view.structuralPrevIds.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: "Structural prev (chart shape)", children: /* @__PURE__ */ jsx13(PlainTags, { labels: view.structuralPrevIds }) }),
3540
- view.structuralNextIds.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: "Structural next (chart shape)", children: /* @__PURE__ */ jsx13(PlainTags, { labels: view.structuralNextIds }) }),
3541
- view.runtimePrevIds.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: "Runtime prev (this execution)", children: /* @__PURE__ */ jsx13(RuntimeRefs, { refs: view.runtimePrevIds, onClick: onNavigate }) }),
3542
- view.runtimeNextIds.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: "Runtime next (this execution)", children: /* @__PURE__ */ jsx13(RuntimeRefs, { refs: view.runtimeNextIds, onClick: onNavigate }) }),
3543
- Object.keys(view.updates).length > 0 && /* @__PURE__ */ jsx13(Section2, { title: `Updates (${Object.keys(view.updates).length})`, children: /* @__PURE__ */ jsx13(KeyValueGrid, { entries: Object.entries(view.updates) }) }),
3544
- view.reads.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: `Reads (${view.reads.length})`, children: /* @__PURE__ */ jsx13(PlainTags, { labels: view.reads }) }),
3545
- view.dataDependencies.length > 0 && /* @__PURE__ */ jsx13(Section2, { title: `Data dependencies (${view.dataDependencies.length})`, children: /* @__PURE__ */ jsx13("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ jsx13("tbody", { children: view.dataDependencies.map((dep) => /* @__PURE__ */ jsxs12("tr", { children: [
3546
- /* @__PURE__ */ jsx13("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0" }, children: dep.key }),
3547
- /* @__PURE__ */ jsx13("td", { style: { color: dep.sourceRuntimeStageId ? theme.textPrimary : theme.textMuted }, children: dep.sourceRuntimeStageId ? /* @__PURE__ */ jsxs12(
4516
+ view.structuralPrevIds.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: "Structural prev (chart shape)", children: /* @__PURE__ */ jsx17(PlainTags, { labels: view.structuralPrevIds }) }),
4517
+ view.structuralNextIds.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: "Structural next (chart shape)", children: /* @__PURE__ */ jsx17(PlainTags, { labels: view.structuralNextIds }) }),
4518
+ view.runtimePrevIds.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: "Runtime prev (this execution)", children: /* @__PURE__ */ jsx17(RuntimeRefs, { refs: view.runtimePrevIds, onClick: onNavigate }) }),
4519
+ view.runtimeNextIds.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: "Runtime next (this execution)", children: /* @__PURE__ */ jsx17(RuntimeRefs, { refs: view.runtimeNextIds, onClick: onNavigate }) }),
4520
+ Object.keys(view.updates).length > 0 && /* @__PURE__ */ jsx17(Section2, { title: `Updates (${Object.keys(view.updates).length})`, children: /* @__PURE__ */ jsx17(KeyValueGrid, { entries: Object.entries(view.updates) }) }),
4521
+ view.reads.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: `Reads (${view.reads.length})`, children: /* @__PURE__ */ jsx17(PlainTags, { labels: view.reads }) }),
4522
+ view.dataDependencies.length > 0 && /* @__PURE__ */ jsx17(Section2, { title: `Data dependencies (${view.dataDependencies.length})`, children: /* @__PURE__ */ jsx17("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ jsx17("tbody", { children: view.dataDependencies.map((dep) => /* @__PURE__ */ jsxs14("tr", { children: [
4523
+ /* @__PURE__ */ jsx17("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0" }, children: dep.key }),
4524
+ /* @__PURE__ */ jsx17("td", { style: { color: dep.sourceRuntimeStageId ? theme.textPrimary : theme.textMuted }, children: dep.sourceRuntimeStageId ? /* @__PURE__ */ jsxs14(
3548
4525
  "button",
3549
4526
  {
3550
4527
  onClick: onNavigate ? () => onNavigate(dep.sourceRuntimeStageId) : void 0,
@@ -3554,10 +4531,10 @@ function CommitInspector({
3554
4531
  dep.sourceRuntimeStageId
3555
4532
  ]
3556
4533
  }
3557
- ) : /* @__PURE__ */ jsx13("em", { children: "(no prior writer \u2014 default or external)" }) })
4534
+ ) : /* @__PURE__ */ jsx17("em", { children: "(no prior writer \u2014 default or external)" }) })
3558
4535
  ] }, dep.key)) }) }) }),
3559
- lineage.length > 1 && /* @__PURE__ */ jsx13(Section2, { title: `Lineage chain (${lineage.length - 1} ancestor commits)`, children: /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: lineage.slice(0, -1).map((c, i) => /* @__PURE__ */ jsxs12("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
3560
- /* @__PURE__ */ jsx13(
4536
+ lineage.length > 1 && /* @__PURE__ */ jsx17(Section2, { title: `Lineage chain (${lineage.length - 1} ancestor commits)`, children: /* @__PURE__ */ jsx17("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: lineage.slice(0, -1).map((c, i) => /* @__PURE__ */ jsxs14("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
4537
+ /* @__PURE__ */ jsx17(
3561
4538
  "button",
3562
4539
  {
3563
4540
  onClick: onNavigate ? () => onNavigate(c.runtimeStageId) : void 0,
@@ -3565,15 +4542,15 @@ function CommitInspector({
3565
4542
  children: c.runtimeStageId
3566
4543
  }
3567
4544
  ),
3568
- i < lineage.length - 2 && /* @__PURE__ */ jsx13("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u2192" })
4545
+ i < lineage.length - 2 && /* @__PURE__ */ jsx17("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u2192" })
3569
4546
  ] }, c.runtimeStageId)) }) })
3570
4547
  ]
3571
4548
  }
3572
4549
  );
3573
4550
  }
3574
4551
  function Section2({ title, children }) {
3575
- return /* @__PURE__ */ jsxs12("div", { style: { marginBottom: 14 }, children: [
3576
- /* @__PURE__ */ jsx13(
4552
+ return /* @__PURE__ */ jsxs14("div", { style: { marginBottom: 14 }, children: [
4553
+ /* @__PURE__ */ jsx17(
3577
4554
  "div",
3578
4555
  {
3579
4556
  style: {
@@ -3591,7 +4568,7 @@ function Section2({ title, children }) {
3591
4568
  ] });
3592
4569
  }
3593
4570
  function PlainTags({ labels }) {
3594
- return /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: labels.map((l) => /* @__PURE__ */ jsx13(
4571
+ return /* @__PURE__ */ jsx17("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: labels.map((l) => /* @__PURE__ */ jsx17(
3595
4572
  "span",
3596
4573
  {
3597
4574
  style: {
@@ -3611,7 +4588,7 @@ function RuntimeRefs({
3611
4588
  refs,
3612
4589
  onClick
3613
4590
  }) {
3614
- return /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: refs.map((r) => /* @__PURE__ */ jsx13(
4591
+ return /* @__PURE__ */ jsx17("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: refs.map((r) => /* @__PURE__ */ jsx17(
3615
4592
  "button",
3616
4593
  {
3617
4594
  onClick: onClick ? () => onClick(r) : void 0,
@@ -3622,9 +4599,9 @@ function RuntimeRefs({
3622
4599
  )) });
3623
4600
  }
3624
4601
  function KeyValueGrid({ entries }) {
3625
- return /* @__PURE__ */ jsx13("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ jsx13("tbody", { children: entries.map(([k, v2]) => /* @__PURE__ */ jsxs12("tr", { children: [
3626
- /* @__PURE__ */ jsx13("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0", verticalAlign: "top" }, children: k }),
3627
- /* @__PURE__ */ jsx13("td", { style: { color: theme.textPrimary, wordBreak: "break-word" }, children: typeof v2 === "object" ? JSON.stringify(v2) : String(v2) })
4602
+ return /* @__PURE__ */ jsx17("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ jsx17("tbody", { children: entries.map(([k, v2]) => /* @__PURE__ */ jsxs14("tr", { children: [
4603
+ /* @__PURE__ */ jsx17("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0", verticalAlign: "top" }, children: k }),
4604
+ /* @__PURE__ */ jsx17("td", { style: { color: theme.textPrimary, wordBreak: "break-word" }, children: typeof v2 === "object" ? JSON.stringify(v2) : String(v2) })
3628
4605
  ] }, k)) }) });
3629
4606
  }
3630
4607
  function crumbButtonStyle(clickable) {
@@ -3791,7 +4768,7 @@ function decorate(node, commitsByStageId) {
3791
4768
  }
3792
4769
 
3793
4770
  // src/components/FlowchartView/CommitChainView.tsx
3794
- import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
4771
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
3795
4772
  function CommitChainView({
3796
4773
  chain,
3797
4774
  selectedRuntimeStageId = null,
@@ -3802,7 +4779,7 @@ function CommitChainView({
3802
4779
  style
3803
4780
  }) {
3804
4781
  if (!chain) {
3805
- return /* @__PURE__ */ jsx14(
4782
+ return /* @__PURE__ */ jsx18(
3806
4783
  "div",
3807
4784
  {
3808
4785
  className,
@@ -3816,7 +4793,7 @@ function CommitChainView({
3816
4793
  }
3817
4794
  );
3818
4795
  }
3819
- return /* @__PURE__ */ jsx14(
4796
+ return /* @__PURE__ */ jsx18(
3820
4797
  "div",
3821
4798
  {
3822
4799
  className,
@@ -3827,11 +4804,11 @@ function CommitChainView({
3827
4804
  overflow: "auto",
3828
4805
  ...style
3829
4806
  },
3830
- children: /* @__PURE__ */ jsx14(
4807
+ children: /* @__PURE__ */ jsx18(
3831
4808
  ChainShell,
3832
4809
  {
3833
4810
  node: chain,
3834
- renderLeaf: (leaf) => /* @__PURE__ */ jsx14(
4811
+ renderLeaf: (leaf) => /* @__PURE__ */ jsx18(
3835
4812
  Leaf,
3836
4813
  {
3837
4814
  leaf,
@@ -3848,10 +4825,10 @@ function CommitChainView({
3848
4825
  }
3849
4826
  function ChainShell({ node, renderLeaf }) {
3850
4827
  if (node.kind === "leaf") {
3851
- return /* @__PURE__ */ jsx14(Fragment4, { children: renderLeaf(node) });
4828
+ return /* @__PURE__ */ jsx18(Fragment4, { children: renderLeaf(node) });
3852
4829
  }
3853
4830
  if (node.kind === "serial") {
3854
- return /* @__PURE__ */ jsx14(
4831
+ return /* @__PURE__ */ jsx18(
3855
4832
  "div",
3856
4833
  {
3857
4834
  style: {
@@ -3860,13 +4837,13 @@ function ChainShell({ node, renderLeaf }) {
3860
4837
  alignItems: "center",
3861
4838
  gap: 0
3862
4839
  },
3863
- children: node.items.map((child, i) => /* @__PURE__ */ jsxs13(
4840
+ children: node.items.map((child, i) => /* @__PURE__ */ jsxs15(
3864
4841
  "div",
3865
4842
  {
3866
4843
  style: { display: "flex", flexDirection: "column", alignItems: "center" },
3867
4844
  children: [
3868
- /* @__PURE__ */ jsx14(ChainShell, { node: child, renderLeaf }),
3869
- i < node.items.length - 1 && /* @__PURE__ */ jsx14(Connector, { orientation: "vertical" })
4845
+ /* @__PURE__ */ jsx18(ChainShell, { node: child, renderLeaf }),
4846
+ i < node.items.length - 1 && /* @__PURE__ */ jsx18(Connector, { orientation: "vertical" })
3870
4847
  ]
3871
4848
  },
3872
4849
  chainKey(child, i)
@@ -3874,7 +4851,7 @@ function ChainShell({ node, renderLeaf }) {
3874
4851
  }
3875
4852
  );
3876
4853
  }
3877
- return /* @__PURE__ */ jsxs13(
4854
+ return /* @__PURE__ */ jsxs15(
3878
4855
  "div",
3879
4856
  {
3880
4857
  style: {
@@ -3884,8 +4861,8 @@ function ChainShell({ node, renderLeaf }) {
3884
4861
  gap: 0
3885
4862
  },
3886
4863
  children: [
3887
- /* @__PURE__ */ jsx14(ForkMarker, {}),
3888
- /* @__PURE__ */ jsx14(
4864
+ /* @__PURE__ */ jsx18(ForkMarker, {}),
4865
+ /* @__PURE__ */ jsx18(
3889
4866
  "div",
3890
4867
  {
3891
4868
  style: {
@@ -3899,7 +4876,7 @@ function ChainShell({ node, renderLeaf }) {
3899
4876
  paddingLeft: 12,
3900
4877
  paddingRight: 12
3901
4878
  },
3902
- children: node.branches.map((branch, i) => /* @__PURE__ */ jsx14(
4879
+ children: node.branches.map((branch, i) => /* @__PURE__ */ jsx18(
3903
4880
  "div",
3904
4881
  {
3905
4882
  style: {
@@ -3908,13 +4885,13 @@ function ChainShell({ node, renderLeaf }) {
3908
4885
  alignItems: "center",
3909
4886
  minWidth: 120
3910
4887
  },
3911
- children: /* @__PURE__ */ jsx14(ChainShell, { node: branch, renderLeaf })
4888
+ children: /* @__PURE__ */ jsx18(ChainShell, { node: branch, renderLeaf })
3912
4889
  },
3913
4890
  chainKey(branch, i)
3914
4891
  ))
3915
4892
  }
3916
4893
  ),
3917
- /* @__PURE__ */ jsx14(ForkMarker, {})
4894
+ /* @__PURE__ */ jsx18(ForkMarker, {})
3918
4895
  ]
3919
4896
  }
3920
4897
  );
@@ -3948,7 +4925,7 @@ function Leaf({
3948
4925
  const label = resolveLabel ? resolveLabel(leaf.stageId) : leaf.stageId;
3949
4926
  const commits = "commits" in leaf ? leaf.commits : [];
3950
4927
  if (commits.length === 0) {
3951
- return /* @__PURE__ */ jsxs13(
4928
+ return /* @__PURE__ */ jsxs15(
3952
4929
  "div",
3953
4930
  {
3954
4931
  style: {
@@ -3959,17 +4936,17 @@ function Leaf({
3959
4936
  },
3960
4937
  title: `${leaf.stageId} \u2014 not executed in this run`,
3961
4938
  children: [
3962
- /* @__PURE__ */ jsx14("div", { style: { fontWeight: 600 }, children: label }),
3963
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 10, fontStyle: "italic" }, children: "not executed" })
4939
+ /* @__PURE__ */ jsx18("div", { style: { fontWeight: 600 }, children: label }),
4940
+ /* @__PURE__ */ jsx18("div", { style: { fontSize: 10, fontStyle: "italic" }, children: "not executed" })
3964
4941
  ]
3965
4942
  }
3966
4943
  );
3967
4944
  }
3968
- return /* @__PURE__ */ jsx14("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }, children: commits.map((c, i) => {
4945
+ return /* @__PURE__ */ jsx18("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }, children: commits.map((c, i) => {
3969
4946
  const isSelected = c.runtimeStageId === selectedRuntimeStageId;
3970
4947
  const clickable = onSelectCommit !== void 0;
3971
4948
  const isRevealed = revealedThroughCommitIdx === null || c.commitIdx <= revealedThroughCommitIdx;
3972
- return /* @__PURE__ */ jsxs13(
4949
+ return /* @__PURE__ */ jsxs15(
3973
4950
  "button",
3974
4951
  {
3975
4952
  type: "button",
@@ -3990,16 +4967,16 @@ function Leaf({
3990
4967
  "aria-current": isSelected ? "true" : void 0,
3991
4968
  title: c.runtimeStageId,
3992
4969
  children: [
3993
- /* @__PURE__ */ jsxs13("div", { style: { fontWeight: 600 }, children: [
4970
+ /* @__PURE__ */ jsxs15("div", { style: { fontWeight: 600 }, children: [
3994
4971
  label,
3995
- commits.length > 1 && /* @__PURE__ */ jsxs13("span", { style: { color: theme.textMuted, fontWeight: 400, marginLeft: 6 }, children: [
4972
+ commits.length > 1 && /* @__PURE__ */ jsxs15("span", { style: { color: theme.textMuted, fontWeight: 400, marginLeft: 6 }, children: [
3996
4973
  "iter ",
3997
4974
  i + 1,
3998
4975
  "/",
3999
4976
  commits.length
4000
4977
  ] })
4001
4978
  ] }),
4002
- /* @__PURE__ */ jsxs13(
4979
+ /* @__PURE__ */ jsxs15(
4003
4980
  "div",
4004
4981
  {
4005
4982
  style: {
@@ -4023,7 +5000,7 @@ function Leaf({
4023
5000
  }) });
4024
5001
  }
4025
5002
  function Connector({ orientation }) {
4026
- return orientation === "vertical" ? /* @__PURE__ */ jsx14(
5003
+ return orientation === "vertical" ? /* @__PURE__ */ jsx18(
4027
5004
  "div",
4028
5005
  {
4029
5006
  "aria-hidden": true,
@@ -4033,7 +5010,7 @@ function Connector({ orientation }) {
4033
5010
  background: theme.border
4034
5011
  }
4035
5012
  }
4036
- ) : /* @__PURE__ */ jsx14(
5013
+ ) : /* @__PURE__ */ jsx18(
4037
5014
  "div",
4038
5015
  {
4039
5016
  "aria-hidden": true,
@@ -4046,7 +5023,7 @@ function Connector({ orientation }) {
4046
5023
  );
4047
5024
  }
4048
5025
  function ForkMarker() {
4049
- return /* @__PURE__ */ jsx14(
5026
+ return /* @__PURE__ */ jsx18(
4050
5027
  "div",
4051
5028
  {
4052
5029
  "aria-hidden": true,
@@ -4076,7 +5053,7 @@ import { useMemo as useMemo12, useState as useState8, useCallback as useCallback
4076
5053
 
4077
5054
  // src/components/FlowchartView/RunSlider.tsx
4078
5055
  import { useCallback as useCallback6, useMemo as useMemo11 } from "react";
4079
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
5056
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
4080
5057
  function RunSlider({
4081
5058
  index,
4082
5059
  cursorRuntimeStageId,
@@ -4110,8 +5087,8 @@ function RunSlider({
4110
5087
  commit,
4111
5088
  index
4112
5089
  });
4113
- if (total === 0) return /* @__PURE__ */ jsx15("span", { style: { color: theme.textMuted }, children: "No commits yet" });
4114
- return /* @__PURE__ */ jsxs14("span", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: [
5090
+ if (total === 0) return /* @__PURE__ */ jsx19("span", { style: { color: theme.textMuted }, children: "No commits yet" });
5091
+ return /* @__PURE__ */ jsxs16("span", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: [
4115
5092
  "#",
4116
5093
  cursorCommitIdx + 1,
4117
5094
  " / ",
@@ -4121,7 +5098,7 @@ function RunSlider({
4121
5098
  ] });
4122
5099
  }, [renderLabel, cursorCommitIdx, total, index, cursorRuntimeStageId]);
4123
5100
  const disabled = total < 2;
4124
- return /* @__PURE__ */ jsxs14(
5101
+ return /* @__PURE__ */ jsxs16(
4125
5102
  "div",
4126
5103
  {
4127
5104
  className,
@@ -4136,7 +5113,7 @@ function RunSlider({
4136
5113
  ...style
4137
5114
  },
4138
5115
  children: [
4139
- /* @__PURE__ */ jsx15(
5116
+ /* @__PURE__ */ jsx19(
4140
5117
  "span",
4141
5118
  {
4142
5119
  style: {
@@ -4149,7 +5126,7 @@ function RunSlider({
4149
5126
  children: "Time"
4150
5127
  }
4151
5128
  ),
4152
- /* @__PURE__ */ jsx15(
5129
+ /* @__PURE__ */ jsx19(
4153
5130
  "input",
4154
5131
  {
4155
5132
  type: "range",
@@ -4167,14 +5144,14 @@ function RunSlider({
4167
5144
  style: { flex: 1, accentColor: theme.success }
4168
5145
  }
4169
5146
  ),
4170
- /* @__PURE__ */ jsx15("div", { style: { minWidth: 200, textAlign: "right" }, children: label })
5147
+ /* @__PURE__ */ jsx19("div", { style: { minWidth: 200, textAlign: "right" }, children: label })
4171
5148
  ]
4172
5149
  }
4173
5150
  );
4174
5151
  }
4175
5152
 
4176
5153
  // src/components/FlowchartView/TraceExplorerShell.tsx
4177
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
5154
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
4178
5155
  function TraceExplorerShell({
4179
5156
  bundle,
4180
5157
  selectedRuntimeStageId: controlledSel,
@@ -4247,8 +5224,8 @@ function TraceExplorerShell({
4247
5224
  () => SliderPane ? SHELL_STYLE_WITH_SLIDER : SHELL_STYLE_NO_SLIDER,
4248
5225
  [SliderPane]
4249
5226
  );
4250
- return /* @__PURE__ */ jsxs15("div", { className, style: { ...layoutStyle, ...style }, children: [
4251
- SliderPane && /* @__PURE__ */ jsx16(Pane, { area: "slider", children: /* @__PURE__ */ jsx16(
5227
+ return /* @__PURE__ */ jsxs17("div", { className, style: { ...layoutStyle, ...style }, children: [
5228
+ SliderPane && /* @__PURE__ */ jsx20(Pane, { area: "slider", children: /* @__PURE__ */ jsx20(
4252
5229
  SliderPane,
4253
5230
  {
4254
5231
  index: commitIndex,
@@ -4256,7 +5233,7 @@ function TraceExplorerShell({
4256
5233
  onCursorChange: handleSelect
4257
5234
  }
4258
5235
  ) }),
4259
- /* @__PURE__ */ jsx16(Pane, { area: "chain", children: /* @__PURE__ */ jsx16(
5236
+ /* @__PURE__ */ jsx20(Pane, { area: "chain", children: /* @__PURE__ */ jsx20(
4260
5237
  ChainPane,
4261
5238
  {
4262
5239
  chain,
@@ -4265,7 +5242,7 @@ function TraceExplorerShell({
4265
5242
  revealedThroughCommitIdx
4266
5243
  }
4267
5244
  ) }),
4268
- /* @__PURE__ */ jsx16(Pane, { area: "commit", children: /* @__PURE__ */ jsx16(
5245
+ /* @__PURE__ */ jsx20(Pane, { area: "commit", children: /* @__PURE__ */ jsx20(
4269
5246
  CommitPane,
4270
5247
  {
4271
5248
  index: commitIndex,
@@ -4273,7 +5250,7 @@ function TraceExplorerShell({
4273
5250
  onNavigate: handleSelectCommit
4274
5251
  }
4275
5252
  ) }),
4276
- /* @__PURE__ */ jsx16(Pane, { area: "node", children: /* @__PURE__ */ jsx16(
5253
+ /* @__PURE__ */ jsx20(Pane, { area: "node", children: /* @__PURE__ */ jsx20(
4277
5254
  NodePane,
4278
5255
  {
4279
5256
  index: nodeIndex,
@@ -4289,7 +5266,7 @@ function DefaultChainPane({
4289
5266
  onSelectCommit,
4290
5267
  revealedThroughCommitIdx
4291
5268
  }) {
4292
- return /* @__PURE__ */ jsx16(
5269
+ return /* @__PURE__ */ jsx20(
4293
5270
  CommitChainView,
4294
5271
  {
4295
5272
  chain,
@@ -4304,7 +5281,7 @@ function DefaultCommitPane({
4304
5281
  selectedRuntimeStageId,
4305
5282
  onNavigate
4306
5283
  }) {
4307
- return /* @__PURE__ */ jsx16(
5284
+ return /* @__PURE__ */ jsx20(
4308
5285
  CommitInspector,
4309
5286
  {
4310
5287
  index,
@@ -4314,14 +5291,14 @@ function DefaultCommitPane({
4314
5291
  );
4315
5292
  }
4316
5293
  function DefaultNodePane({ index, selectedStageId, onNavigate }) {
4317
- return /* @__PURE__ */ jsx16(NodeInspector, { index, selectedId: selectedStageId, onNavigate });
5294
+ return /* @__PURE__ */ jsx20(NodeInspector, { index, selectedId: selectedStageId, onNavigate });
4318
5295
  }
4319
5296
  function DefaultSliderPane({
4320
5297
  index,
4321
5298
  cursorRuntimeStageId,
4322
5299
  onCursorChange
4323
5300
  }) {
4324
- return /* @__PURE__ */ jsx16(
5301
+ return /* @__PURE__ */ jsx20(
4325
5302
  RunSlider,
4326
5303
  {
4327
5304
  index,
@@ -4359,13 +5336,19 @@ var PANE_BASE_STYLE = {
4359
5336
  // permit shrinking inside grid
4360
5337
  };
4361
5338
  function Pane({ area, children }) {
4362
- return /* @__PURE__ */ jsx16("div", { role: "region", "aria-label": area, style: { ...PANE_BASE_STYLE, gridArea: area }, children });
5339
+ return /* @__PURE__ */ jsx20("div", { role: "region", "aria-label": area, style: { ...PANE_BASE_STYLE, gridArea: area }, children });
4363
5340
  }
4364
5341
  export {
4365
5342
  CommitChainView,
4366
5343
  CommitInspector,
5344
+ GROUP_CONTAINER_NODE_TYPE,
5345
+ GroupContainerNode,
5346
+ LoopBackEdge,
5347
+ MAIN_CHART_BOX_ID,
4367
5348
  NodeInspector,
4368
5349
  RunSlider,
5350
+ SlotPillNode,
5351
+ SmartStepEdge,
4369
5352
  StageNode,
4370
5353
  SubflowBreadcrumb,
4371
5354
  SubflowTree,
@@ -4373,23 +5356,35 @@ export {
4373
5356
  TraceExplorerShell,
4374
5357
  TraceFlow,
4375
5358
  TracedFlow,
5359
+ applyGroupLayout,
4376
5360
  asRuntimeStageId,
4377
5361
  asStageId,
4378
5362
  backtraceDataFlow,
4379
5363
  backtraceStructural,
4380
5364
  buildCommitChainTree,
5365
+ buildSubflowBreadcrumb,
4381
5366
  createCommitFlowRecorder,
5367
+ createDagreTraceLayout,
5368
+ createGroupedLayout,
5369
+ createMainChartBoxLayout,
4382
5370
  createNodeViewRecorder,
5371
+ createSnappedDagreLayout,
4383
5372
  createTraceBundle,
5373
+ createTraceGroupLayout,
4384
5374
  createTraceRuntimeOverlay,
4385
5375
  createTraceStructureRecorder,
5376
+ dagreTraceLayout,
4386
5377
  defaultTraceFlowLayout,
5378
+ filterGraphForDrill,
4387
5379
  forwardtraceStructural,
4388
5380
  sliceOverlay,
5381
+ snapLinearSuccessors,
4389
5382
  structureAsChainTree,
5383
+ traceGroupLayout,
4390
5384
  useSubflowNavigation,
4391
5385
  useTranslator,
4392
5386
  walkBackward,
4393
- walkForward
5387
+ walkForward,
5388
+ wrapInMainChartBox
4394
5389
  };
4395
5390
  //# sourceMappingURL=flowchart.js.map