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
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/flowchart.ts
@@ -22,8 +32,14 @@ var flowchart_exports = {};
22
32
  __export(flowchart_exports, {
23
33
  CommitChainView: () => CommitChainView,
24
34
  CommitInspector: () => CommitInspector,
35
+ GROUP_CONTAINER_NODE_TYPE: () => GROUP_CONTAINER_NODE_TYPE,
36
+ GroupContainerNode: () => GroupContainerNode,
37
+ LoopBackEdge: () => LoopBackEdge,
38
+ MAIN_CHART_BOX_ID: () => MAIN_CHART_BOX_ID,
25
39
  NodeInspector: () => NodeInspector,
26
40
  RunSlider: () => RunSlider,
41
+ SlotPillNode: () => SlotPillNode,
42
+ SmartStepEdge: () => SmartStepEdge,
27
43
  StageNode: () => StageNode,
28
44
  SubflowBreadcrumb: () => SubflowBreadcrumb,
29
45
  SubflowTree: () => SubflowTree,
@@ -31,24 +47,36 @@ __export(flowchart_exports, {
31
47
  TraceExplorerShell: () => TraceExplorerShell,
32
48
  TraceFlow: () => TraceFlow,
33
49
  TracedFlow: () => TracedFlow,
50
+ applyGroupLayout: () => applyGroupLayout,
34
51
  asRuntimeStageId: () => asRuntimeStageId,
35
52
  asStageId: () => asStageId,
36
53
  backtraceDataFlow: () => backtraceDataFlow,
37
54
  backtraceStructural: () => backtraceStructural,
38
55
  buildCommitChainTree: () => buildCommitChainTree,
56
+ buildSubflowBreadcrumb: () => buildSubflowBreadcrumb,
39
57
  createCommitFlowRecorder: () => createCommitFlowRecorder,
58
+ createDagreTraceLayout: () => createDagreTraceLayout,
59
+ createGroupedLayout: () => createGroupedLayout,
60
+ createMainChartBoxLayout: () => createMainChartBoxLayout,
40
61
  createNodeViewRecorder: () => createNodeViewRecorder,
62
+ createSnappedDagreLayout: () => createSnappedDagreLayout,
41
63
  createTraceBundle: () => createTraceBundle,
64
+ createTraceGroupLayout: () => createTraceGroupLayout,
42
65
  createTraceRuntimeOverlay: () => createTraceRuntimeOverlay,
43
66
  createTraceStructureRecorder: () => createTraceStructureRecorder,
67
+ dagreTraceLayout: () => dagreTraceLayout,
44
68
  defaultTraceFlowLayout: () => defaultTraceFlowLayout,
69
+ filterGraphForDrill: () => filterGraphForDrill,
45
70
  forwardtraceStructural: () => forwardtraceStructural,
46
71
  sliceOverlay: () => sliceOverlay,
72
+ snapLinearSuccessors: () => snapLinearSuccessors,
47
73
  structureAsChainTree: () => structureAsChainTree,
74
+ traceGroupLayout: () => traceGroupLayout,
48
75
  useSubflowNavigation: () => useSubflowNavigation,
49
76
  useTranslator: () => useTranslator,
50
77
  walkBackward: () => walkBackward,
51
- walkForward: () => walkForward
78
+ walkForward: () => walkForward,
79
+ wrapInMainChartBox: () => wrapInMainChartBox
52
80
  });
53
81
  module.exports = __toCommonJS(flowchart_exports);
54
82
 
@@ -255,6 +283,27 @@ function StageIcon({ type, color }) {
255
283
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
256
284
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
257
285
  ] });
286
+ // System prompt — document with lines
287
+ case "system-prompt":
288
+ case "prompt":
289
+ case "instructions":
290
+ case "document":
291
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
292
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3.5", y: "2", width: "9", height: "12", rx: "1.5", stroke: color, strokeWidth: "1.3", fill: "none" }),
293
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "5", x2: "10.5", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
294
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "7.5", x2: "10.5", y2: "7.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
295
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "10", x2: "8.5", y2: "10", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
296
+ ] });
297
+ // Messages / conversation — chat bubble
298
+ case "messages":
299
+ case "chat":
300
+ case "conversation":
301
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
302
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2.5", y: "3", width: "11", height: "8", rx: "2", stroke: color, strokeWidth: "1.3", fill: "none" }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.5 11L5.5 13.5L8.5 11", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5", y1: "6", x2: "11", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
305
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5", y1: "8.5", x2: "9", y2: "8.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
306
+ ] });
258
307
  // Loop — circular arrow
259
308
  case "loop":
260
309
  case "retry":
@@ -305,20 +354,29 @@ var StageNode = (0, import_react3.memo)(function StageNode2({
305
354
  injectedRef.current = true;
306
355
  }, []);
307
356
  const isOnPath = active || done;
308
- const bg = active ? theme.primary : done ? theme.success : error ? theme.error : theme.bgSecondary;
309
- const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : theme.border;
310
- 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)`;
357
+ const isHero = data.emphasis === "hero";
358
+ const isMuted = data.emphasis === "muted";
359
+ const sizeScale = data.size === "lg" ? 1.3 : data.size === "sm" ? 0.85 : 1;
360
+ const restingBg = isHero ? `color-mix(in srgb, ${theme.primary} 12%, ${theme.bgSecondary})` : theme.bgSecondary;
361
+ const restingBorder = isHero ? theme.primary : theme.border;
362
+ const restingShadow = isHero ? `0 0 10px color-mix(in srgb, ${theme.primary} 22%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
363
+ const bg = active ? theme.primary : done ? theme.success : error ? theme.error : restingBg;
364
+ const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : restingBorder;
365
+ 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;
311
366
  const textColor = active || done || error ? "#fff" : theme.textPrimary;
312
367
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
313
368
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Top, style: { opacity: 0 } }),
314
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
369
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
315
370
  "div",
316
371
  {
317
372
  style: {
318
373
  position: "relative",
319
374
  display: "flex",
320
375
  alignItems: "center",
321
- gap: 6
376
+ gap: 6,
377
+ // Plumbing recedes. Layers with the run-overlay `dimmed` (not-yet-run)
378
+ // — a muted AND not-run node is faintest, which is correct.
379
+ opacity: isMuted ? 0.5 : void 0
322
380
  },
323
381
  children: [
324
382
  stepNumbers && stepNumbers.length > 0 && isOnPath && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -387,6 +445,26 @@ var StageNode = (0, import_react3.memo)(function StageNode2({
387
445
  }
388
446
  }
389
447
  ),
448
+ active && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
449
+ "div",
450
+ {
451
+ style: {
452
+ position: "absolute",
453
+ top: -9,
454
+ right: -8,
455
+ zIndex: 11,
456
+ background: theme.warning,
457
+ color: "#1a1a1a",
458
+ fontSize: 9,
459
+ fontWeight: 800,
460
+ letterSpacing: 0.6,
461
+ padding: "2px 6px",
462
+ borderRadius: 10,
463
+ boxShadow: `0 0 10px color-mix(in srgb, ${theme.warning} 60%, transparent)`
464
+ },
465
+ children: "NOW"
466
+ }
467
+ ),
390
468
  isDecider ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative", width: 120, height: 72 }, children: [
391
469
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
392
470
  "div",
@@ -492,9 +570,9 @@ var StageNode = (0, import_react3.memo)(function StageNode2({
492
570
  {
493
571
  style: {
494
572
  background: bg,
495
- border: `2px ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
573
+ border: `${isHero ? "2.5px" : isMuted ? "1px" : "2px"} ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
496
574
  borderRadius: theme.radius,
497
- padding: description ? "8px 16px" : "10px 20px",
575
+ padding: description ? `${Math.round(8 * sizeScale)}px ${Math.round(16 * sizeScale)}px` : `${Math.round(10 * sizeScale)}px ${Math.round(20 * sizeScale)}px`,
498
576
  display: "flex",
499
577
  flexDirection: "column",
500
578
  alignItems: "center",
@@ -527,8 +605,8 @@ var StageNode = (0, import_react3.memo)(function StageNode2({
527
605
  "span",
528
606
  {
529
607
  style: {
530
- fontSize: 13,
531
- fontWeight: 500,
608
+ fontSize: Math.round(13 * sizeScale),
609
+ fontWeight: isHero ? 700 : 500,
532
610
  color: textColor,
533
611
  whiteSpace: "nowrap"
534
612
  },
@@ -603,31 +681,13 @@ var StageNode = (0, import_react3.memo)(function StageNode2({
603
681
  )
604
682
  ]
605
683
  }
606
- ),
607
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Bottom, style: { opacity: 0 } }),
608
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
609
- import_react4.Handle,
610
- {
611
- id: "loop-source",
612
- type: "source",
613
- position: import_react4.Position.Bottom,
614
- style: { background: "transparent", border: "none", width: 6, height: 6, left: "75%" }
615
- }
616
- ),
617
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
618
- import_react4.Handle,
619
- {
620
- id: "loop-target",
621
- type: "target",
622
- position: import_react4.Position.Right,
623
- style: { background: "transparent", border: "none", width: 6, height: 6 }
624
- }
625
- )
684
+ ) }),
685
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Bottom, style: { opacity: 0 } })
626
686
  ] });
627
687
  });
628
688
 
629
689
  // src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
630
- var import_react14 = require("react");
690
+ var import_react18 = require("react");
631
691
 
632
692
  // src/components/MemoryInspector/MemoryInspector.tsx
633
693
  var import_react5 = require("react");
@@ -1185,9 +1245,463 @@ function GanttTimeline({
1185
1245
  }
1186
1246
 
1187
1247
  // src/components/FlowchartView/TraceFlow.tsx
1188
- var import_react8 = require("react");
1189
- var import_react9 = require("@xyflow/react");
1248
+ var import_react11 = require("react");
1249
+ var import_react12 = require("@xyflow/react");
1250
+
1251
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
1252
+ var import_react8 = require("@xyflow/react");
1253
+
1254
+ // src/components/FlowchartView/_internal/loopRouting.ts
1255
+ var LOOP_LANE_GAP = 56;
1256
+ function loopLaneX(contentRights, gap = LOOP_LANE_GAP) {
1257
+ let max = -Infinity;
1258
+ for (const r of contentRights) if (r > max) max = r;
1259
+ if (!Number.isFinite(max)) max = 0;
1260
+ return max + gap;
1261
+ }
1262
+ function loopBackPath(source, target, laneX, radius = 22) {
1263
+ const { right: sx, centerY: sy } = source;
1264
+ const { right: tx, centerY: ty } = target;
1265
+ const r = Math.max(
1266
+ 0,
1267
+ Math.min(radius, Math.abs(sy - ty) / 2, laneX - sx, laneX - tx)
1268
+ );
1269
+ const up = ty <= sy;
1270
+ const vy1 = up ? sy - r : sy + r;
1271
+ const vy2 = up ? ty + r : ty - r;
1272
+ return [
1273
+ `M ${sx},${sy}`,
1274
+ `L ${laneX - r},${sy}`,
1275
+ `Q ${laneX},${sy} ${laneX},${vy1}`,
1276
+ `L ${laneX},${vy2}`,
1277
+ `Q ${laneX},${ty} ${laneX - r},${ty}`,
1278
+ `L ${tx},${ty}`
1279
+ ].join(" ");
1280
+ }
1281
+
1282
+ // src/components/FlowchartView/_internal/groupLayout.ts
1283
+ var GROUP_CONTAINER_NODE_TYPE = "groupContainer";
1284
+ var DEFAULT_PADDING = 16;
1285
+ var DEFAULT_HEADER = 44;
1286
+ var DEFAULT_NODE_W = 200;
1287
+ var DEFAULT_NODE_H = 80;
1288
+ function footprintOf(node, fallbackW, fallbackH) {
1289
+ const style = node.style ?? {};
1290
+ const w = typeof style.width === "number" ? style.width : fallbackW;
1291
+ const h = typeof style.height === "number" ? style.height : fallbackH;
1292
+ return { width: w, height: h };
1293
+ }
1294
+ function applyGroupLayout(graph, opts) {
1295
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
1296
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
1297
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;
1298
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;
1299
+ const baseLayout = opts.baseLayout;
1300
+ const requested = new Set(opts.groupedSubflowIds);
1301
+ const membersBySubflow = /* @__PURE__ */ new Map();
1302
+ for (const n of graph.nodes) {
1303
+ const of = n.data?.subflowOf;
1304
+ if (of !== void 0 && requested.has(of)) {
1305
+ const arr = membersBySubflow.get(of) ?? [];
1306
+ arr.push(n);
1307
+ membersBySubflow.set(of, arr);
1308
+ }
1309
+ }
1310
+ const mountBySubflow = /* @__PURE__ */ new Map();
1311
+ for (const n of graph.nodes) {
1312
+ const sfId = n.data?.subflowId;
1313
+ if (n.data?.isSubflow && sfId !== void 0 && requested.has(sfId) && membersBySubflow.has(sfId)) {
1314
+ mountBySubflow.set(sfId, n);
1315
+ }
1316
+ }
1317
+ const activeGroups = /* @__PURE__ */ new Set();
1318
+ for (const sfId of mountBySubflow.keys()) activeGroups.add(sfId);
1319
+ if (activeGroups.size === 0) {
1320
+ return graph;
1321
+ }
1322
+ const memberIds = /* @__PURE__ */ new Set();
1323
+ for (const sfId of activeGroups) {
1324
+ for (const m of membersBySubflow.get(sfId) ?? []) memberIds.add(m.id);
1325
+ }
1326
+ const containerNodes = [];
1327
+ const nestedMembers = [];
1328
+ const groupBox = /* @__PURE__ */ new Map();
1329
+ for (const sfId of activeGroups) {
1330
+ const members = membersBySubflow.get(sfId);
1331
+ const innerOnlyEdges = graph.edges.filter((e) => {
1332
+ const s = members.some((m) => m.id === e.source);
1333
+ const t = members.some((m) => m.id === e.target);
1334
+ return s && t;
1335
+ });
1336
+ const innerPositioned = baseLayout({ nodes: members, edges: innerOnlyEdges });
1337
+ let minX = Infinity;
1338
+ let minY = Infinity;
1339
+ let maxX = -Infinity;
1340
+ let maxY = -Infinity;
1341
+ for (const m of innerPositioned.nodes) {
1342
+ const p = m.position;
1343
+ const { width, height } = footprintOf(m, nodeW, nodeH);
1344
+ if (p.x < minX) minX = p.x;
1345
+ if (p.y < minY) minY = p.y;
1346
+ if (p.x + width > maxX) maxX = p.x + width;
1347
+ if (p.y + height > maxY) maxY = p.y + height;
1348
+ }
1349
+ if (!Number.isFinite(minX)) {
1350
+ minX = 0;
1351
+ minY = 0;
1352
+ maxX = 0;
1353
+ maxY = 0;
1354
+ }
1355
+ const boxWidth = maxX - minX + padding2 * 2;
1356
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
1357
+ groupBox.set(sfId, { width: boxWidth, height: boxHeight, minX, minY, members: innerPositioned.nodes });
1358
+ }
1359
+ const outerNodes = graph.nodes.filter((n) => !memberIds.has(n.id)).map((n) => {
1360
+ const box = n.data?.subflowId ? groupBox.get(n.data.subflowId) : void 0;
1361
+ return box ? {
1362
+ ...n,
1363
+ style: { ...n.style ?? {}, width: box.width, height: box.height },
1364
+ data: { ...n.data, isGroupContainer: true }
1365
+ } : n;
1366
+ });
1367
+ const outerEdges = graph.edges.filter(
1368
+ (e) => !memberIds.has(e.source) && !memberIds.has(e.target)
1369
+ );
1370
+ const outerPositioned = baseLayout({ nodes: outerNodes, edges: outerEdges });
1371
+ const outerPosById = new Map(outerPositioned.nodes.map((n) => [n.id, n.position]));
1372
+ for (const sfId of activeGroups) {
1373
+ const mount = mountBySubflow.get(sfId);
1374
+ const box = groupBox.get(sfId);
1375
+ const { width: boxWidth, height: boxHeight, minX, minY } = box;
1376
+ const mountPos = outerPosById.get(mount.id) ?? mount.position ?? { x: 0, y: 0 };
1377
+ containerNodes.push({
1378
+ ...mount,
1379
+ type: GROUP_CONTAINER_NODE_TYPE,
1380
+ position: mountPos,
1381
+ style: { ...mount.style ?? {}, width: boxWidth, height: boxHeight },
1382
+ data: { ...mount.data, isGroupContainer: true }
1383
+ });
1384
+ for (const m of box.members) {
1385
+ const relX = m.position.x - minX + padding2;
1386
+ const relY = m.position.y - minY + headerHeight + padding2;
1387
+ nestedMembers.push({
1388
+ ...m,
1389
+ parentId: mount.id,
1390
+ extent: "parent",
1391
+ position: { x: relX, y: relY }
1392
+ });
1393
+ }
1394
+ }
1395
+ const containerById = new Map(containerNodes.map((c) => [c.id, c]));
1396
+ const outerOut = outerPositioned.nodes.map(
1397
+ (n) => containerById.get(n.id) ?? n
1398
+ );
1399
+ return {
1400
+ nodes: [...outerOut, ...nestedMembers],
1401
+ edges: graph.edges
1402
+ };
1403
+ }
1404
+ function createGroupedLayout(opts) {
1405
+ return (graph) => applyGroupLayout(graph, opts);
1406
+ }
1407
+ var MAIN_CHART_BOX_ID = "__main_chart__";
1408
+ function wrapInMainChartBox(graph, opts) {
1409
+ if (graph.nodes.length === 0) return graph;
1410
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
1411
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
1412
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W;
1413
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H;
1414
+ const mainId = opts.id ?? MAIN_CHART_BOX_ID;
1415
+ const positioned = opts.baseLayout(graph);
1416
+ const topLevel = positioned.nodes.filter((n) => n.parentId === void 0);
1417
+ let minX = Infinity;
1418
+ let minY = Infinity;
1419
+ let maxX = -Infinity;
1420
+ let maxY = -Infinity;
1421
+ for (const n of topLevel) {
1422
+ const p = n.position;
1423
+ const { width, height } = footprintOf(n, nodeW, nodeH);
1424
+ if (p.x < minX) minX = p.x;
1425
+ if (p.y < minY) minY = p.y;
1426
+ if (p.x + width > maxX) maxX = p.x + width;
1427
+ if (p.y + height > maxY) maxY = p.y + height;
1428
+ }
1429
+ if (!Number.isFinite(minX)) {
1430
+ minX = 0;
1431
+ minY = 0;
1432
+ maxX = 0;
1433
+ maxY = 0;
1434
+ }
1435
+ const hasLoopEdge = graph.edges.some((e) => e.data?.kind === "loop");
1436
+ const loopReserve = hasLoopEdge ? LOOP_LANE_GAP : 0;
1437
+ const boxWidth = maxX - minX + padding2 * 2 + loopReserve;
1438
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
1439
+ const container = {
1440
+ id: mainId,
1441
+ type: GROUP_CONTAINER_NODE_TYPE,
1442
+ position: { x: 0, y: 0 },
1443
+ style: { width: boxWidth, height: boxHeight },
1444
+ data: {
1445
+ label: opts.label ?? "Chart",
1446
+ isDecider: false,
1447
+ isFork: false,
1448
+ isStreaming: false,
1449
+ isSubflow: false,
1450
+ isGroupContainer: true,
1451
+ isMainChart: true,
1452
+ ...opts.kind !== void 0 && { kind: opts.kind },
1453
+ prevIds: [],
1454
+ nextIds: []
1455
+ }
1456
+ };
1457
+ const topLevelIds = new Set(topLevel.map((n) => n.id));
1458
+ const reparented = positioned.nodes.map((n) => {
1459
+ if (!topLevelIds.has(n.id)) return n;
1460
+ return {
1461
+ ...n,
1462
+ parentId: mainId,
1463
+ extent: "parent",
1464
+ position: {
1465
+ x: n.position.x - minX + padding2,
1466
+ y: n.position.y - minY + headerHeight + padding2
1467
+ }
1468
+ };
1469
+ });
1470
+ return { nodes: [container, ...reparented], edges: graph.edges };
1471
+ }
1472
+ function createMainChartBoxLayout(opts) {
1473
+ return (graph) => wrapInMainChartBox(graph, opts);
1474
+ }
1475
+
1476
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
1190
1477
  var import_jsx_runtime6 = require("react/jsx-runtime");
1478
+ var LOOP_DASH = "5 5";
1479
+ var LOOP_STROKE_OPACITY_CAP = 0.55;
1480
+ var LOOP_STROKE_WIDTH = 1.5;
1481
+ function softenLoopStyle(style) {
1482
+ const passedStrokeOpacity = typeof style?.strokeOpacity === "number" ? style.strokeOpacity : 1;
1483
+ return {
1484
+ ...style,
1485
+ strokeDasharray: style?.strokeDasharray ?? LOOP_DASH,
1486
+ strokeOpacity: Math.min(passedStrokeOpacity, LOOP_STROKE_OPACITY_CAP),
1487
+ strokeWidth: LOOP_STROKE_WIDTH
1488
+ };
1489
+ }
1490
+ var LOOP_CORNER_RADIUS = 28;
1491
+ function rightEdge(node) {
1492
+ return node.internals.positionAbsolute.x + (node.measured.width ?? 0);
1493
+ }
1494
+ function centerY(node) {
1495
+ return node.internals.positionAbsolute.y + (node.measured.height ?? 0) / 2;
1496
+ }
1497
+ function LoopBackEdge({ id, source, target, markerEnd, style }) {
1498
+ const path = (0, import_react8.useStore)((s) => {
1499
+ const src = s.nodeLookup.get(source);
1500
+ const tgt = s.nodeLookup.get(target);
1501
+ if (!src || !tgt) return "";
1502
+ const contentRights = [];
1503
+ for (const n of s.nodeLookup.values()) {
1504
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
1505
+ contentRights.push(rightEdge(n));
1506
+ }
1507
+ const laneX = loopLaneX([...contentRights, rightEdge(src), rightEdge(tgt)], LOOP_LANE_GAP);
1508
+ return loopBackPath(
1509
+ { right: rightEdge(src), centerY: centerY(src) },
1510
+ { right: rightEdge(tgt), centerY: centerY(tgt) },
1511
+ laneX,
1512
+ LOOP_CORNER_RADIUS
1513
+ );
1514
+ });
1515
+ if (!path) return null;
1516
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1517
+ import_react8.BaseEdge,
1518
+ {
1519
+ id,
1520
+ path,
1521
+ markerEnd,
1522
+ style: softenLoopStyle(style),
1523
+ "aria-label": "Loop back"
1524
+ }
1525
+ );
1526
+ }
1527
+
1528
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
1529
+ var import_react9 = require("@xyflow/react");
1530
+ var import_react10 = require("@xyflow/react");
1531
+
1532
+ // src/components/FlowchartView/_internal/stepRouting.ts
1533
+ function staggeredBendY(sourceBottom, targetTop, others, minGapFromTarget = 8) {
1534
+ let lowestSkippedBottom = -Infinity;
1535
+ for (const n of others) {
1536
+ const cy = (n.top + n.bottom) / 2;
1537
+ if (cy > sourceBottom && cy < targetTop && n.bottom > lowestSkippedBottom) {
1538
+ lowestSkippedBottom = n.bottom;
1539
+ }
1540
+ }
1541
+ if (lowestSkippedBottom === -Infinity) return null;
1542
+ return Math.min((lowestSkippedBottom + targetTop) / 2, targetTop - minGapFromTarget);
1543
+ }
1544
+
1545
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
1546
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1547
+ function SmartStepEdge({
1548
+ id,
1549
+ source,
1550
+ target,
1551
+ sourceX,
1552
+ sourceY,
1553
+ targetX,
1554
+ targetY,
1555
+ sourcePosition,
1556
+ targetPosition,
1557
+ markerEnd,
1558
+ style
1559
+ }) {
1560
+ const bendY = (0, import_react9.useStore)((s) => {
1561
+ const src = s.nodeLookup.get(source);
1562
+ const tgt = s.nodeLookup.get(target);
1563
+ if (!src || !tgt) return null;
1564
+ const sourceBottom = src.internals.positionAbsolute.y + (src.measured.height ?? 0);
1565
+ const targetTop = tgt.internals.positionAbsolute.y;
1566
+ const others = [];
1567
+ for (const n of s.nodeLookup.values()) {
1568
+ if (n.id === source || n.id === target) continue;
1569
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
1570
+ const top = n.internals.positionAbsolute.y;
1571
+ others.push({ top, bottom: top + (n.measured.height ?? 0) });
1572
+ }
1573
+ return staggeredBendY(sourceBottom, targetTop, others);
1574
+ });
1575
+ const [path] = (0, import_react9.getSmoothStepPath)({
1576
+ sourceX,
1577
+ sourceY,
1578
+ sourcePosition: sourcePosition ?? import_react10.Position.Bottom,
1579
+ targetX,
1580
+ targetY,
1581
+ targetPosition: targetPosition ?? import_react10.Position.Top,
1582
+ // Override the bend only for a staggered edge; otherwise let getSmoothStepPath
1583
+ // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).
1584
+ ...bendY !== null ? { centerY: bendY } : {}
1585
+ });
1586
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react9.BaseEdge, { id, path, markerEnd, style });
1587
+ }
1588
+
1589
+ // src/components/FlowchartView/_internal/dagreTraceLayout.ts
1590
+ var import_dagre = __toESM(require("dagre"), 1);
1591
+ var DEFAULT_NODE_W2 = 200;
1592
+ var DEFAULT_NODE_H2 = 80;
1593
+ function sizeOf(node, fallbackW, fallbackH, resolver) {
1594
+ const style = node.style ?? {};
1595
+ const styleW = typeof style.width === "number" ? style.width : void 0;
1596
+ const styleH = typeof style.height === "number" ? style.height : void 0;
1597
+ if (node.data?.isGroupContainer && styleW !== void 0 && styleH !== void 0) {
1598
+ return { width: styleW, height: styleH };
1599
+ }
1600
+ const resolved = resolver?.(node);
1601
+ if (resolved) return { width: resolved.width, height: resolved.height };
1602
+ return {
1603
+ width: styleW ?? fallbackW,
1604
+ height: styleH ?? fallbackH
1605
+ };
1606
+ }
1607
+ function reorderSiblingEdges(edges, siblingOrder) {
1608
+ const bySource = /* @__PURE__ */ new Map();
1609
+ for (const e of edges) {
1610
+ if (e.data?.kind === "loop") continue;
1611
+ const arr = bySource.get(e.source);
1612
+ if (arr) arr.push(e);
1613
+ else bySource.set(e.source, [e]);
1614
+ }
1615
+ const out = [];
1616
+ for (const [src, group] of bySource) {
1617
+ if (group.length < 2) {
1618
+ out.push(...group);
1619
+ continue;
1620
+ }
1621
+ const ordered = siblingOrder(src, group.map((e) => e.target));
1622
+ const byTarget = new Map(group.map((e) => [e.target, e]));
1623
+ const used = /* @__PURE__ */ new Set();
1624
+ for (const t of ordered) {
1625
+ const e = byTarget.get(t);
1626
+ if (e && !used.has(t)) {
1627
+ out.push(e);
1628
+ used.add(t);
1629
+ }
1630
+ }
1631
+ for (const e of group) if (!used.has(e.target)) out.push(e);
1632
+ }
1633
+ return out;
1634
+ }
1635
+ function dagreTraceLayout(graph, options = {}) {
1636
+ if (graph.nodes.length === 0) return graph;
1637
+ const direction = options.direction ?? "TB";
1638
+ const rankSep = options.rankSep ?? 80;
1639
+ const nodeSep = options.nodeSep ?? 60;
1640
+ const edgeSep = options.edgeSep ?? 20;
1641
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
1642
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
1643
+ const g = new import_dagre.default.graphlib.Graph({ compound: true });
1644
+ g.setGraph({ rankdir: direction, ranksep: rankSep, nodesep: nodeSep, edgesep: edgeSep });
1645
+ g.setDefaultEdgeLabel(() => ({}));
1646
+ const sizes = /* @__PURE__ */ new Map();
1647
+ const resolvedStyleSizes = /* @__PURE__ */ new Map();
1648
+ for (const node of graph.nodes) {
1649
+ const resolved = options.nodeSize?.(node);
1650
+ const size = sizeOf(node, fallbackW, fallbackH, options.nodeSize);
1651
+ sizes.set(node.id, size);
1652
+ if (resolved && resolved.width === size.width && resolved.height === size.height) {
1653
+ resolvedStyleSizes.set(node.id, resolved);
1654
+ }
1655
+ g.setNode(node.id, { width: size.width, height: size.height });
1656
+ if (node.parentId) {
1657
+ g.setParent(node.id, node.parentId);
1658
+ }
1659
+ }
1660
+ const layoutEdges = options.siblingOrder ? reorderSiblingEdges(graph.edges, options.siblingOrder) : graph.edges;
1661
+ for (const e of layoutEdges) {
1662
+ if (e.data?.kind === "loop") continue;
1663
+ if (g.hasNode(e.source) && g.hasNode(e.target)) {
1664
+ const label = {};
1665
+ const weight = options.edgeWeight?.(e);
1666
+ const minlen = options.edgeMinLen?.(e);
1667
+ if (typeof weight === "number") label.weight = weight;
1668
+ if (typeof minlen === "number") label.minlen = minlen;
1669
+ g.setEdge(e.source, e.target, label);
1670
+ }
1671
+ }
1672
+ import_dagre.default.layout(g);
1673
+ const positioned = graph.nodes.map((node) => {
1674
+ const laidOut = g.node(node.id);
1675
+ if (!laidOut) return node;
1676
+ const size = sizes.get(node.id);
1677
+ let x = laidOut.x - size.width / 2;
1678
+ let y = laidOut.y - size.height / 2;
1679
+ if (node.parentId) {
1680
+ const parent = g.node(node.parentId);
1681
+ const parentSize = sizes.get(node.parentId);
1682
+ if (parent && parentSize) {
1683
+ x -= parent.x - parentSize.width / 2;
1684
+ y -= parent.y - parentSize.height / 2;
1685
+ }
1686
+ }
1687
+ const styleSize = resolvedStyleSizes.get(node.id);
1688
+ if (styleSize) {
1689
+ return {
1690
+ ...node,
1691
+ position: { x, y },
1692
+ style: { ...node.style ?? {}, width: styleSize.width, height: styleSize.height }
1693
+ };
1694
+ }
1695
+ return { ...node, position: { x, y } };
1696
+ });
1697
+ return { nodes: positioned, edges: graph.edges };
1698
+ }
1699
+ function createDagreTraceLayout(options = {}) {
1700
+ return (graph) => dagreTraceLayout(graph, options);
1701
+ }
1702
+
1703
+ // src/components/FlowchartView/TraceFlow.tsx
1704
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1191
1705
  var Y_STEP = 100;
1192
1706
  var X_SPREAD = 200;
1193
1707
  var defaultTraceFlowLayout = (graph) => {
@@ -1276,10 +1790,14 @@ function styleEdge(edge, colors) {
1276
1790
  const color = kind === "loop" ? colors.loop : kind === "fork-branch" ? colors.forkBranch : kind === "decision-branch" ? colors.decisionBranch : colors.next;
1277
1791
  const styled = {
1278
1792
  ...edge,
1279
- type: kind === "loop" ? "step" : "smoothstep",
1793
+ // Loop back-edges use the custom `loopBack` edge — a curve routed along the
1794
+ // right margin (clear of the spine) instead of a straight/step center line.
1795
+ // Every other edge uses `smartStep`: a smoothstep superset that routes a
1796
+ // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).
1797
+ type: kind === "loop" ? "loopBack" : "smartStep",
1280
1798
  animated: false,
1281
1799
  style: { stroke: color, strokeWidth: 1.5 },
1282
- markerEnd: { type: import_react9.MarkerType.ArrowClosed, color, width: 16, height: 16 }
1800
+ markerEnd: { type: import_react12.MarkerType.ArrowClosed, color, width: 16, height: 16 }
1283
1801
  };
1284
1802
  if (kind === "loop") {
1285
1803
  styled.style = { ...styled.style, strokeDasharray: "4 3" };
@@ -1287,6 +1805,7 @@ function styleEdge(edge, colors) {
1287
1805
  return styled;
1288
1806
  }
1289
1807
  var DEFAULT_NODE_TYPES = { stageNode: StageNode };
1808
+ var DEFAULT_EDGE_TYPES = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };
1290
1809
  function toStageNode(node) {
1291
1810
  if (node.type !== void 0 && node.type !== "stage") {
1292
1811
  return node;
@@ -1303,7 +1822,9 @@ function toStageNode(node) {
1303
1822
  ...data.description !== void 0 && { description: data.description },
1304
1823
  ...data.icon !== void 0 && { icon: data.icon },
1305
1824
  ...data.subflowId !== void 0 && { subflowId: data.subflowId },
1306
- ...data.isLazy === true && { isLazy: true }
1825
+ ...data.isLazy === true && { isLazy: true },
1826
+ ...data.emphasis !== void 0 && { emphasis: data.emphasis },
1827
+ ...data.size !== void 0 && { size: data.size }
1307
1828
  };
1308
1829
  return {
1309
1830
  ...node,
@@ -1333,51 +1854,55 @@ function TraceFlow(props) {
1333
1854
  "[TraceFlow] neither `recorder` nor `graph` prop was provided \u2014 rendering an empty chart. Pass one of: <TraceFlow recorder={handle} /> OR <TraceFlow graph={{nodes, edges}} />."
1334
1855
  );
1335
1856
  }
1336
- const layout = props.layout ?? defaultTraceFlowLayout;
1337
- const edgeColors = (0, import_react8.useMemo)(
1857
+ const layout = props.layout ?? dagreTraceLayout;
1858
+ const edgeColors = (0, import_react11.useMemo)(
1338
1859
  () => ({ ...DEFAULT_EDGE_COLORS, ...props.edgeColors ?? {} }),
1339
1860
  [props.edgeColors]
1340
1861
  );
1341
- const subscribe = (0, import_react8.useMemo)(
1862
+ const subscribe = (0, import_react11.useMemo)(
1342
1863
  () => subscribeToRecorder(props.recorder),
1343
1864
  [props.recorder]
1344
1865
  );
1345
- const getVersion = (0, import_react8.useMemo)(
1866
+ const getVersion = (0, import_react11.useMemo)(
1346
1867
  () => getRecorderVersion(props.recorder),
1347
1868
  [props.recorder]
1348
1869
  );
1349
- const version = (0, import_react8.useSyncExternalStore)(subscribe, getVersion, getVersion);
1870
+ const version = (0, import_react11.useSyncExternalStore)(subscribe, getVersion, getVersion);
1350
1871
  const { recorder, graph: graphProp } = props;
1351
- const graph = (0, import_react8.useMemo)(() => {
1872
+ const graph = (0, import_react11.useMemo)(() => {
1352
1873
  if (recorder) return recorder.getGraph();
1353
1874
  if (graphProp) return graphProp;
1354
1875
  return EMPTY_GRAPH;
1355
1876
  }, [recorder, graphProp, version]);
1356
- const positioned = (0, import_react8.useMemo)(() => {
1877
+ const positioned = (0, import_react11.useMemo)(() => {
1357
1878
  if (layout === "passthrough") return graph;
1358
1879
  return layout(graph);
1359
1880
  }, [graph, layout]);
1360
- const reactFlowNodes = (0, import_react8.useMemo)(
1881
+ const reactFlowNodes = (0, import_react11.useMemo)(
1361
1882
  () => positioned.nodes.map(toStageNode),
1362
1883
  [positioned.nodes]
1363
1884
  );
1364
- const reactFlowEdges = (0, import_react8.useMemo)(
1885
+ const reactFlowEdges = (0, import_react11.useMemo)(
1365
1886
  () => positioned.edges.map((e) => styleEdge(e, edgeColors)),
1366
1887
  [positioned.edges, edgeColors]
1367
1888
  );
1368
1889
  const onNodeClickRef = props.onNodeClick;
1369
- const handleNodeClick = (0, import_react8.useCallback)(
1890
+ const handleNodeClick = (0, import_react11.useCallback)(
1370
1891
  (_, node) => {
1371
1892
  onNodeClickRef?.(node.id);
1372
1893
  },
1373
1894
  [onNodeClickRef]
1374
1895
  );
1375
1896
  const { nodeTypes: userNodeTypes, edgeTypes: userEdgeTypes } = props;
1376
- const mergedNodeTypes = (0, import_react8.useMemo)(
1897
+ const mergedNodeTypes = (0, import_react11.useMemo)(
1377
1898
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES,
1378
1899
  [userNodeTypes]
1379
1900
  );
1380
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1901
+ const mergedEdgeTypes = (0, import_react11.useMemo)(
1902
+ () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES,
1903
+ [userEdgeTypes]
1904
+ );
1905
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1381
1906
  "div",
1382
1907
  {
1383
1908
  className: props.className,
@@ -1387,18 +1912,18 @@ function TraceFlow(props) {
1387
1912
  minHeight: 300,
1388
1913
  ...props.style
1389
1914
  },
1390
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1391
- import_react9.ReactFlow,
1915
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1916
+ import_react12.ReactFlow,
1392
1917
  {
1393
1918
  nodes: reactFlowNodes,
1394
1919
  edges: reactFlowEdges,
1395
1920
  nodeTypes: mergedNodeTypes,
1396
- ...userEdgeTypes && { edgeTypes: userEdgeTypes },
1921
+ edgeTypes: mergedEdgeTypes,
1397
1922
  onNodeClick: handleNodeClick,
1398
1923
  fitView: true,
1399
1924
  proOptions: { hideAttribution: true },
1400
1925
  children: [
1401
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react9.Background, { variant: import_react9.BackgroundVariant.Dots, gap: 20, size: 1 }),
1926
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react12.Background, { variant: import_react12.BackgroundVariant.Dots, gap: 20, size: 1 }),
1402
1927
  props.children
1403
1928
  ]
1404
1929
  }
@@ -1408,8 +1933,8 @@ function TraceFlow(props) {
1408
1933
  }
1409
1934
 
1410
1935
  // src/components/FlowchartView/TracedFlow.tsx
1411
- var import_react12 = require("react");
1412
- var import_react13 = require("@xyflow/react");
1936
+ var import_react16 = require("react");
1937
+ var import_react17 = require("@xyflow/react");
1413
1938
 
1414
1939
  // src/components/FlowchartView/_internal/devWarn.ts
1415
1940
  function isDevModeEnv() {
@@ -1585,19 +2110,6 @@ function buildSubflowBreadcrumb(graph, currentSubflowId) {
1585
2110
  }
1586
2111
 
1587
2112
  // src/components/FlowchartView/_internal/overlayProjection.ts
1588
- function leafId(id) {
1589
- const i = id.lastIndexOf("/");
1590
- return i >= 0 ? id.slice(i + 1) : id;
1591
- }
1592
- function normalizeSliceLeafIds(slice) {
1593
- return {
1594
- doneStageIds: new Set(Array.from(slice.doneStageIds).map(leafId)),
1595
- activeStageId: slice.activeStageId ? leafId(slice.activeStageId) : null,
1596
- executedStageIds: new Set(Array.from(slice.executedStageIds).map(leafId)),
1597
- executedOrderIds: slice.executedOrderIds.map(leafId),
1598
- errors: new Map(Array.from(slice.errors).map(([k, v2]) => [leafId(k), v2]))
1599
- };
1600
- }
1601
2113
  function aggregateMountStatus(slice, graph, currentSubflowId) {
1602
2114
  if (graph.nodes.length === 0) return slice;
1603
2115
  const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);
@@ -1609,10 +2121,9 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
1609
2121
  const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);
1610
2122
  if (members.length === 0) continue;
1611
2123
  const anyActive = members.some((m) => m.id === slice.activeStageId);
1612
- const anyDone = members.some((m) => slice.doneStageIds.has(m.id));
1613
2124
  const allDone = members.every((m) => slice.doneStageIds.has(m.id));
1614
2125
  if (allDone) doneIds.add(mount.id);
1615
- else if ((anyActive || anyDone) && currentSubflowId === null) {
2126
+ else if (anyActive && currentSubflowId === null) {
1616
2127
  activeId = mount.id;
1617
2128
  }
1618
2129
  }
@@ -1620,18 +2131,18 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
1620
2131
  }
1621
2132
 
1622
2133
  // src/components/FlowchartView/_internal/useSubflowDrill.ts
1623
- var import_react10 = require("react");
2134
+ var import_react13 = require("react");
1624
2135
  function useSubflowDrill(graph, onSubflowChange) {
1625
- const [currentSubflowId, setCurrentSubflowId] = (0, import_react10.useState)(null);
1626
- const lastGraphRef = (0, import_react10.useRef)(null);
2136
+ const [currentSubflowId, setCurrentSubflowId] = (0, import_react13.useState)(null);
2137
+ const lastGraphRef = (0, import_react13.useRef)(null);
1627
2138
  if (lastGraphRef.current !== graph) {
1628
2139
  lastGraphRef.current = graph;
1629
2140
  if (currentSubflowId !== null && !graph.nodes.some((n) => n.data?.subflowId === currentSubflowId)) {
1630
2141
  queueMicrotask(() => setCurrentSubflowId(null));
1631
2142
  }
1632
2143
  }
1633
- const lastNotifiedRef = (0, import_react10.useRef)(void 0);
1634
- (0, import_react10.useEffect)(() => {
2144
+ const lastNotifiedRef = (0, import_react13.useRef)(void 0);
2145
+ (0, import_react13.useEffect)(() => {
1635
2146
  if (lastNotifiedRef.current === currentSubflowId) return;
1636
2147
  lastNotifiedRef.current = currentSubflowId;
1637
2148
  if (currentSubflowId === null) {
@@ -1641,21 +2152,22 @@ function useSubflowDrill(graph, onSubflowChange) {
1641
2152
  if (mount) onSubflowChange?.(mount.id);
1642
2153
  }
1643
2154
  }, [currentSubflowId, graph, onSubflowChange]);
1644
- const drillInto = (0, import_react10.useCallback)((subflowId) => {
2155
+ const drillInto = (0, import_react13.useCallback)((subflowId) => {
1645
2156
  setCurrentSubflowId(subflowId);
1646
2157
  }, []);
1647
- const drillUp = (0, import_react10.useCallback)(() => {
2158
+ const drillUp = (0, import_react13.useCallback)(() => {
1648
2159
  setCurrentSubflowId(null);
1649
2160
  }, []);
1650
2161
  return { currentSubflowId, drillInto, drillUp, setCurrentSubflowId };
1651
2162
  }
1652
2163
 
1653
2164
  // src/components/FlowchartView/_internal/useChartAutoRefit.ts
1654
- var import_react11 = require("react");
2165
+ var import_react14 = require("react");
1655
2166
  function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
1656
2167
  const duration = options.duration ?? 200;
1657
2168
  const padding2 = options.padding ?? 0.1;
1658
- (0, import_react11.useEffect)(() => {
2169
+ const refitKey = options.refitKey;
2170
+ (0, import_react14.useEffect)(() => {
1659
2171
  const el = wrapperRef.current;
1660
2172
  if (!el || !rfInstance) return;
1661
2173
  let raf = 0;
@@ -1674,12 +2186,25 @@ function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
1674
2186
  cancelAnimationFrame(raf);
1675
2187
  };
1676
2188
  }, [rfInstance, wrapperRef, duration, padding2]);
2189
+ (0, import_react14.useEffect)(() => {
2190
+ if (!rfInstance) return;
2191
+ let raf2 = 0;
2192
+ const raf1 = requestAnimationFrame(() => {
2193
+ raf2 = requestAnimationFrame(() => {
2194
+ rfInstance.fitView({ duration, padding: padding2 });
2195
+ });
2196
+ });
2197
+ return () => {
2198
+ cancelAnimationFrame(raf1);
2199
+ cancelAnimationFrame(raf2);
2200
+ };
2201
+ }, [rfInstance, refitKey, duration, padding2]);
1677
2202
  }
1678
2203
 
1679
2204
  // src/components/FlowchartView/SubflowBreadcrumbBar.tsx
1680
- var import_jsx_runtime7 = require("react/jsx-runtime");
2205
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1681
2206
  function SubflowBreadcrumbBar({ entries, onNavigate }) {
1682
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2207
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1683
2208
  "div",
1684
2209
  {
1685
2210
  style: {
@@ -1695,12 +2220,12 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1695
2220
  "aria-label": "Subflow breadcrumb",
1696
2221
  children: entries.map((entry, i) => {
1697
2222
  const isLast = i === entries.length - 1;
1698
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2223
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1699
2224
  "span",
1700
2225
  {
1701
2226
  style: { display: "inline-flex", alignItems: "center", gap: 6 },
1702
2227
  children: [
1703
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2228
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1704
2229
  "button",
1705
2230
  {
1706
2231
  type: "button",
@@ -1720,7 +2245,7 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1720
2245
  children: entry.label
1721
2246
  }
1722
2247
  ),
1723
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
2248
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
1724
2249
  ]
1725
2250
  },
1726
2251
  entry.subflowId ?? "__top__"
@@ -1730,8 +2255,56 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
1730
2255
  );
1731
2256
  }
1732
2257
 
2258
+ // src/components/GroupContainerNode/GroupContainerNode.tsx
2259
+ var import_react15 = require("@xyflow/react");
2260
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2261
+ var C = rawDefaults.colors;
2262
+ function GroupContainerNode({ data }) {
2263
+ const d = data;
2264
+ const borderColor = d.error ? C.error : d.active ? C.primary : d.done ? C.success : C.border;
2265
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2266
+ "div",
2267
+ {
2268
+ style: {
2269
+ width: "100%",
2270
+ height: "100%",
2271
+ boxSizing: "border-box",
2272
+ border: `1.5px ${d.active || d.done || d.error ? "solid" : "dashed"} ${borderColor}`,
2273
+ borderRadius: 12,
2274
+ // Translucent so the dotted background + nested children read clearly.
2275
+ background: "rgba(148, 163, 184, 0.06)",
2276
+ opacity: d.dimmed ? 0.4 : 1,
2277
+ position: "relative"
2278
+ },
2279
+ children: [
2280
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2281
+ "div",
2282
+ {
2283
+ style: {
2284
+ display: "flex",
2285
+ alignItems: "center",
2286
+ gap: 6,
2287
+ padding: "8px 12px",
2288
+ fontSize: 12,
2289
+ fontWeight: 600,
2290
+ color: C.textMuted,
2291
+ letterSpacing: 0.2
2292
+ },
2293
+ children: [
2294
+ d.icon ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "aria-hidden": true, children: d.icon }) : null,
2295
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: d.label })
2296
+ ]
2297
+ }
2298
+ ),
2299
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react15.Handle, { type: "target", position: import_react15.Position.Top, style: { opacity: 0 } }),
2300
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react15.Handle, { type: "source", position: import_react15.Position.Bottom, style: { opacity: 0 } })
2301
+ ]
2302
+ }
2303
+ );
2304
+ }
2305
+
1733
2306
  // src/components/FlowchartView/TracedFlow.tsx
1734
- var import_jsx_runtime8 = require("react/jsx-runtime");
2307
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1735
2308
  var DEFAULT_COLORS = {
1736
2309
  default: rawDefaults.colors.textMuted,
1737
2310
  done: rawDefaults.colors.success,
@@ -1739,12 +2312,10 @@ var DEFAULT_COLORS = {
1739
2312
  error: rawDefaults.colors.error,
1740
2313
  loop: rawDefaults.colors.warning
1741
2314
  };
1742
- function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds) {
1743
- if (node.type !== void 0 && node.type !== "stage") {
1744
- return node;
1745
- }
2315
+ var EMPTY_SET = /* @__PURE__ */ new Set();
2316
+ function deriveOverlayFields(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
1746
2317
  const isDone = doneStageIds.has(node.id);
1747
- const isActive = activeStageId === node.id;
2318
+ const isActive = activeStageId === node.id || coActiveStageIds.has(node.id);
1748
2319
  const wasExecuted = isDone || isActive;
1749
2320
  const hasError = !!errorMessage;
1750
2321
  const dimmed = !wasExecuted && executedOrderIds.length > 0;
@@ -1756,21 +2327,62 @@ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage,
1756
2327
  }
1757
2328
  if (nums.length > 0) stepNumbers = nums;
1758
2329
  }
2330
+ return {
2331
+ active: isActive,
2332
+ done: isDone,
2333
+ error: hasError,
2334
+ dimmed,
2335
+ ...errorMessage && { errorMessage },
2336
+ ...stepNumbers && { stepNumbers }
2337
+ };
2338
+ }
2339
+ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
2340
+ const overlayFields = deriveOverlayFields(
2341
+ node,
2342
+ doneStageIds,
2343
+ activeStageId,
2344
+ errorMessage,
2345
+ executedOrderIds,
2346
+ coActiveStageIds
2347
+ );
2348
+ const { dimmed } = overlayFields;
2349
+ if (node.type !== void 0 && node.type !== "stage") {
2350
+ const consumerData = node.data ?? {};
2351
+ const consumerActive = consumerData.active === true;
2352
+ const consumerDone = consumerData.done === true;
2353
+ const consumerError = consumerData.error === true;
2354
+ const finalActive = consumerActive || overlayFields.active;
2355
+ const finalDone = consumerDone || overlayFields.done;
2356
+ const finalError = consumerError || overlayFields.error;
2357
+ const finalDimmed = !finalActive && !finalDone && dimmed;
2358
+ return {
2359
+ ...node,
2360
+ data: {
2361
+ ...node.data,
2362
+ active: finalActive,
2363
+ done: finalDone,
2364
+ error: finalError,
2365
+ ...overlayFields.errorMessage !== void 0 && consumerData.errorMessage === void 0 && {
2366
+ errorMessage: overlayFields.errorMessage
2367
+ },
2368
+ ...finalDimmed && { dimmed: true },
2369
+ ...overlayFields.stepNumbers && { stepNumbers: overlayFields.stepNumbers }
2370
+ },
2371
+ ...finalDimmed && { style: { ...node.style ?? {}, opacity: 0.35 } }
2372
+ };
2373
+ }
1759
2374
  const stageData = {
1760
2375
  label: node.data.label,
1761
2376
  isDecider: node.data.isDecider,
1762
2377
  isFork: node.data.isFork,
1763
2378
  isSubflow: node.data.isSubflow,
1764
- active: isActive,
1765
- done: isDone,
1766
- error: hasError,
2379
+ ...overlayFields,
1767
2380
  ...node.data.description !== void 0 && { description: node.data.description },
1768
2381
  ...node.data.icon !== void 0 && { icon: node.data.icon },
1769
2382
  ...node.data.subflowId !== void 0 && { subflowId: node.data.subflowId },
1770
2383
  ...node.data.isLazy === true && { isLazy: true },
1771
- ...dimmed && { dimmed: true },
1772
- ...stepNumbers && { stepNumbers },
1773
- ...errorMessage && { errorMessage }
2384
+ ...node.data.emphasis !== void 0 && { emphasis: node.data.emphasis },
2385
+ ...node.data.size !== void 0 && { size: node.data.size }
1774
2386
  };
1775
2387
  return {
1776
2388
  ...node,
@@ -1791,23 +2403,27 @@ function styleEdgeWithOverlay(edge, doneStageIds, activeStageId, colors) {
1791
2403
  else if (traversed) color = colors.done;
1792
2404
  const styled = {
1793
2405
  ...edge,
1794
- type: "smoothstep",
2406
+ // Loop back-edges use the custom `loopBack` edge — a curve routed along the
2407
+ // right margin (clear of the spine). It reads node bounds from the store
2408
+ // and anchors on right edges itself, so it needs NO dedicated loop handles
2409
+ // on the node (the old approach broke for any node missing them).
2410
+ // Every other edge uses `smartStep`: a smoothstep superset that routes a
2411
+ // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).
2412
+ type: kind === "loop" ? "loopBack" : "smartStep",
1795
2413
  animated: isLeadingEdge,
1796
2414
  style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },
1797
- markerEnd: { type: import_react13.MarkerType.ArrowClosed, color, width: 16, height: 16 }
2415
+ markerEnd: { type: import_react17.MarkerType.ArrowClosed, color, width: 16, height: 16 }
1798
2416
  };
1799
2417
  if (kind === "loop") {
1800
2418
  styled.style = { ...styled.style, strokeDasharray: "4 3" };
1801
- styled.data = {
1802
- ...styled.data ?? {},
1803
- pathOptions: { borderRadius: 14, offset: 36 }
1804
- };
1805
- styled.sourceHandle = "loop-source";
1806
- styled.targetHandle = "loop-target";
1807
2419
  }
1808
2420
  return styled;
1809
2421
  }
1810
- var DEFAULT_NODE_TYPES2 = { stageNode: StageNode };
2422
+ var DEFAULT_NODE_TYPES2 = {
2423
+ stageNode: StageNode,
2424
+ groupContainer: GroupContainerNode
2425
+ };
2426
+ var DEFAULT_EDGE_TYPES2 = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };
1811
2427
  function TracedFlow({
1812
2428
  graph,
1813
2429
  overlay,
@@ -1816,35 +2432,64 @@ function TracedFlow({
1816
2432
  colors: colorOverrides,
1817
2433
  onNodeClick,
1818
2434
  onSubflowChange,
2435
+ groupedSubflows,
2436
+ mainChartBox,
1819
2437
  nodeTypes: userNodeTypes,
1820
2438
  edgeTypes: userEdgeTypes,
2439
+ coActiveStageIds,
1821
2440
  children,
1822
2441
  className,
1823
2442
  style
1824
2443
  }) {
1825
- const layout = layoutProp ?? defaultTraceFlowLayout;
1826
- const colors = (0, import_react12.useMemo)(
2444
+ const layout = layoutProp ?? dagreTraceLayout;
2445
+ const colors = (0, import_react16.useMemo)(
1827
2446
  () => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
1828
2447
  [colorOverrides]
1829
2448
  );
1830
- const mergedNodeTypes = (0, import_react12.useMemo)(
2449
+ const mergedNodeTypes = (0, import_react16.useMemo)(
1831
2450
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES2, ...userNodeTypes } : DEFAULT_NODE_TYPES2,
1832
2451
  [userNodeTypes]
1833
2452
  );
1834
- const drill = useSubflowDrill(graph, onSubflowChange);
1835
- const filteredGraph = (0, import_react12.useMemo)(
1836
- () => filterGraphForDrill(graph, drill.currentSubflowId),
1837
- [graph, drill.currentSubflowId]
2453
+ const mergedEdgeTypes = (0, import_react16.useMemo)(
2454
+ () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES2, ...userEdgeTypes } : DEFAULT_EDGE_TYPES2,
2455
+ [userEdgeTypes]
1838
2456
  );
1839
- const breadcrumb = (0, import_react12.useMemo)(
2457
+ const drill = useSubflowDrill(graph, onSubflowChange);
2458
+ const groupedSet = (0, import_react16.useMemo)(() => new Set(groupedSubflows ?? []), [groupedSubflows]);
2459
+ const filteredGraph = (0, import_react16.useMemo)(() => {
2460
+ const base = filterGraphForDrill(graph, drill.currentSubflowId);
2461
+ if (groupedSet.size === 0) return base;
2462
+ const baseIds = new Set(base.nodes.map((n) => n.id));
2463
+ const extraNodes = graph.nodes.filter(
2464
+ (n) => n.data?.subflowOf !== void 0 && groupedSet.has(n.data.subflowOf) && !baseIds.has(n.id)
2465
+ );
2466
+ if (extraNodes.length === 0) return base;
2467
+ const allIds = /* @__PURE__ */ new Set([...baseIds, ...extraNodes.map((n) => n.id)]);
2468
+ const baseEdgeIds = new Set(base.edges.map((e) => e.id));
2469
+ const extraEdges = graph.edges.filter(
2470
+ (e) => !baseEdgeIds.has(e.id) && allIds.has(e.source) && allIds.has(e.target)
2471
+ );
2472
+ return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };
2473
+ }, [graph, drill.currentSubflowId, groupedSet]);
2474
+ const breadcrumb = (0, import_react16.useMemo)(
1840
2475
  () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),
1841
2476
  [graph, drill.currentSubflowId]
1842
2477
  );
1843
- const positioned = (0, import_react12.useMemo)(
1844
- () => layout === "passthrough" ? filteredGraph : layout(filteredGraph),
1845
- [filteredGraph, layout]
1846
- );
1847
- const slice = (0, import_react12.useMemo)(() => {
2478
+ const positioned = (0, import_react16.useMemo)(() => {
2479
+ const realBase = layout === "passthrough" ? (g) => g : layout;
2480
+ if (groupedSet.size > 0) {
2481
+ const grouped = applyGroupLayout(filteredGraph, {
2482
+ groupedSubflowIds: [...groupedSet],
2483
+ baseLayout: realBase
2484
+ });
2485
+ return mainChartBox ? wrapInMainChartBox(grouped, { baseLayout: (g) => g, ...mainChartBox }) : grouped;
2486
+ }
2487
+ if (mainChartBox) {
2488
+ return wrapInMainChartBox(filteredGraph, { baseLayout: realBase, ...mainChartBox });
2489
+ }
2490
+ return layout === "passthrough" ? filteredGraph : layout(filteredGraph);
2491
+ }, [filteredGraph, layout, groupedSet, mainChartBox]);
2492
+ const slice = (0, import_react16.useMemo)(() => {
1848
2493
  const empty = {
1849
2494
  doneStageIds: /* @__PURE__ */ new Set(),
1850
2495
  activeStageId: null,
@@ -1854,41 +2499,41 @@ function TracedFlow({
1854
2499
  };
1855
2500
  if (!overlay) return empty;
1856
2501
  const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);
1857
- const normalized = normalizeSliceLeafIds(sliceOverlay(overlay, idx));
1858
- return aggregateMountStatus(normalized, graph, drill.currentSubflowId);
2502
+ return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);
1859
2503
  }, [overlay, scrubIndex, graph, drill.currentSubflowId]);
1860
- const reactFlowNodes = (0, import_react12.useMemo)(
2504
+ const reactFlowNodes = (0, import_react16.useMemo)(
1861
2505
  () => positioned.nodes.map(
1862
2506
  (n) => toStageNodeWithOverlay(
1863
2507
  n,
1864
2508
  slice.doneStageIds,
1865
2509
  slice.activeStageId,
1866
2510
  slice.errors.get(n.id),
1867
- slice.executedOrderIds
2511
+ slice.executedOrderIds,
2512
+ coActiveStageIds ?? EMPTY_SET
1868
2513
  )
1869
2514
  ),
1870
- [positioned.nodes, slice]
2515
+ [positioned.nodes, slice, coActiveStageIds]
1871
2516
  );
1872
- const reactFlowEdges = (0, import_react12.useMemo)(
2517
+ const reactFlowEdges = (0, import_react16.useMemo)(
1873
2518
  () => positioned.edges.map(
1874
2519
  (e) => styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors)
1875
2520
  ),
1876
2521
  [positioned.edges, slice, colors]
1877
2522
  );
1878
- const handleNodeClick = (0, import_react12.useCallback)(
2523
+ const handleNodeClick = (0, import_react16.useCallback)(
1879
2524
  (_, node) => {
1880
2525
  const data = node.data ?? {};
1881
- if (data.isSubflow && data.subflowId) {
2526
+ if (data.isSubflow && data.subflowId && !groupedSet.has(data.subflowId)) {
1882
2527
  drill.drillInto(data.subflowId);
1883
2528
  }
1884
2529
  onNodeClick?.(node.id);
1885
2530
  },
1886
- [drill, onNodeClick]
2531
+ [drill, onNodeClick, groupedSet]
1887
2532
  );
1888
- const wrapperRef = (0, import_react12.useRef)(null);
1889
- const [rfInstance, setRfInstance] = (0, import_react12.useState)(null);
1890
- useChartAutoRefit(wrapperRef, rfInstance);
1891
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2533
+ const wrapperRef = (0, import_react16.useRef)(null);
2534
+ const [rfInstance, setRfInstance] = (0, import_react16.useState)(null);
2535
+ useChartAutoRefit(wrapperRef, rfInstance, { refitKey: drill.currentSubflowId });
2536
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1892
2537
  "div",
1893
2538
  {
1894
2539
  ref: wrapperRef,
@@ -1902,26 +2547,26 @@ function TracedFlow({
1902
2547
  ...style
1903
2548
  },
1904
2549
  children: [
1905
- breadcrumb.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2550
+ breadcrumb.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1906
2551
  SubflowBreadcrumbBar,
1907
2552
  {
1908
2553
  entries: breadcrumb,
1909
2554
  onNavigate: drill.setCurrentSubflowId
1910
2555
  }
1911
2556
  ),
1912
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1913
- import_react13.ReactFlow,
2557
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2558
+ import_react17.ReactFlow,
1914
2559
  {
1915
2560
  nodes: reactFlowNodes,
1916
2561
  edges: reactFlowEdges,
1917
2562
  nodeTypes: mergedNodeTypes,
1918
- ...userEdgeTypes && { edgeTypes: userEdgeTypes },
2563
+ edgeTypes: mergedEdgeTypes,
1919
2564
  onNodeClick: handleNodeClick,
1920
2565
  onInit: setRfInstance,
1921
2566
  fitView: true,
1922
2567
  proOptions: { hideAttribution: true },
1923
2568
  children: [
1924
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react13.Background, { variant: import_react13.BackgroundVariant.Dots, gap: 20, size: 1 }),
2569
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react17.Background, { variant: import_react17.BackgroundVariant.Dots, gap: 20, size: 1 }),
1925
2570
  children
1926
2571
  ]
1927
2572
  }
@@ -1932,7 +2577,7 @@ function TracedFlow({
1932
2577
  }
1933
2578
 
1934
2579
  // src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
1935
- var import_jsx_runtime9 = require("react/jsx-runtime");
2580
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1936
2581
  function TimeTravelDebugger({
1937
2582
  snapshots,
1938
2583
  graph,
@@ -1945,11 +2590,11 @@ function TimeTravelDebugger({
1945
2590
  className,
1946
2591
  style
1947
2592
  }) {
1948
- const [selectedIndex, setSelectedIndex] = (0, import_react14.useState)(0);
2593
+ const [selectedIndex, setSelectedIndex] = (0, import_react18.useState)(0);
1949
2594
  const fs = fontSize[size];
1950
2595
  const pad = padding[size];
1951
2596
  if (snapshots.length === 0) {
1952
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2597
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1953
2598
  "div",
1954
2599
  {
1955
2600
  className,
@@ -1970,7 +2615,7 @@ function TimeTravelDebugger({
1970
2615
  );
1971
2616
  if (idx >= 0) setSelectedIndex(idx);
1972
2617
  };
1973
- const chart = runtimeOverlay ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2618
+ const chart = runtimeOverlay ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1974
2619
  TracedFlow,
1975
2620
  {
1976
2621
  graph,
@@ -1978,11 +2623,11 @@ function TimeTravelDebugger({
1978
2623
  scrubIndex: selectedIndex,
1979
2624
  onNodeClick: handleNodeClick
1980
2625
  }
1981
- ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TraceFlow, { graph, onNodeClick: handleNodeClick });
2626
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TraceFlow, { graph, onNodeClick: handleNodeClick });
1982
2627
  if (unstyled) {
1983
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, style, "data-fp": "time-travel-debugger", children: [
1984
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { children: title }),
1985
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2628
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className, style, "data-fp": "time-travel-debugger", children: [
2629
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { children: title }),
2630
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1986
2631
  "input",
1987
2632
  {
1988
2633
  type: "range",
@@ -1993,7 +2638,7 @@ function TimeTravelDebugger({
1993
2638
  }
1994
2639
  ),
1995
2640
  chart,
1996
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2641
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1997
2642
  MemoryInspector,
1998
2643
  {
1999
2644
  snapshots,
@@ -2001,7 +2646,7 @@ function TimeTravelDebugger({
2001
2646
  unstyled: true
2002
2647
  }
2003
2648
  ),
2004
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2649
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2005
2650
  NarrativeLog,
2006
2651
  {
2007
2652
  snapshots,
@@ -2009,7 +2654,7 @@ function TimeTravelDebugger({
2009
2654
  unstyled: true
2010
2655
  }
2011
2656
  ),
2012
- showGantt && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2657
+ showGantt && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2013
2658
  GanttTimeline,
2014
2659
  {
2015
2660
  snapshots,
@@ -2020,7 +2665,7 @@ function TimeTravelDebugger({
2020
2665
  )
2021
2666
  ] });
2022
2667
  }
2023
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2668
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2024
2669
  "div",
2025
2670
  {
2026
2671
  className,
@@ -2035,7 +2680,7 @@ function TimeTravelDebugger({
2035
2680
  },
2036
2681
  "data-fp": "time-travel-debugger",
2037
2682
  children: [
2038
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2683
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2039
2684
  "div",
2040
2685
  {
2041
2686
  style: {
@@ -2045,7 +2690,7 @@ function TimeTravelDebugger({
2045
2690
  flexShrink: 0
2046
2691
  },
2047
2692
  children: [
2048
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2693
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2049
2694
  "div",
2050
2695
  {
2051
2696
  style: {
@@ -2055,7 +2700,7 @@ function TimeTravelDebugger({
2055
2700
  marginBottom: 8
2056
2701
  },
2057
2702
  children: [
2058
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2703
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2059
2704
  "span",
2060
2705
  {
2061
2706
  style: {
@@ -2066,7 +2711,7 @@ function TimeTravelDebugger({
2066
2711
  children: title
2067
2712
  }
2068
2713
  ),
2069
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2714
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2070
2715
  "span",
2071
2716
  {
2072
2717
  style: {
@@ -2079,8 +2724,8 @@ function TimeTravelDebugger({
2079
2724
  ]
2080
2725
  }
2081
2726
  ),
2082
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2083
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2727
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2728
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2084
2729
  ScrubButton,
2085
2730
  {
2086
2731
  label: "\u25C0",
@@ -2088,7 +2733,7 @@ function TimeTravelDebugger({
2088
2733
  onClick: () => setSelectedIndex((i) => Math.max(0, i - 1))
2089
2734
  }
2090
2735
  ),
2091
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2736
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2092
2737
  "input",
2093
2738
  {
2094
2739
  type: "range",
@@ -2104,7 +2749,7 @@ function TimeTravelDebugger({
2104
2749
  }
2105
2750
  }
2106
2751
  ),
2107
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2752
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2108
2753
  ScrubButton,
2109
2754
  {
2110
2755
  label: "\u25B6",
@@ -2112,7 +2757,7 @@ function TimeTravelDebugger({
2112
2757
  onClick: () => setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))
2113
2758
  }
2114
2759
  ),
2115
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2760
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2116
2761
  "span",
2117
2762
  {
2118
2763
  style: {
@@ -2132,7 +2777,7 @@ function TimeTravelDebugger({
2132
2777
  ]
2133
2778
  }
2134
2779
  ),
2135
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2780
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2136
2781
  "div",
2137
2782
  {
2138
2783
  style: {
@@ -2142,7 +2787,7 @@ function TimeTravelDebugger({
2142
2787
  overflow: "hidden"
2143
2788
  },
2144
2789
  children: [
2145
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2790
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2146
2791
  "div",
2147
2792
  {
2148
2793
  style: {
@@ -2154,8 +2799,8 @@ function TimeTravelDebugger({
2154
2799
  children: chart
2155
2800
  }
2156
2801
  ),
2157
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
2158
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2802
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
2803
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2159
2804
  MemoryInspector,
2160
2805
  {
2161
2806
  snapshots,
@@ -2163,7 +2808,7 @@ function TimeTravelDebugger({
2163
2808
  size
2164
2809
  }
2165
2810
  ),
2166
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2811
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2167
2812
  "div",
2168
2813
  {
2169
2814
  style: {
@@ -2173,7 +2818,7 @@ function TimeTravelDebugger({
2173
2818
  }
2174
2819
  }
2175
2820
  ),
2176
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2821
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2177
2822
  NarrativeLog,
2178
2823
  {
2179
2824
  snapshots,
@@ -2185,7 +2830,7 @@ function TimeTravelDebugger({
2185
2830
  ]
2186
2831
  }
2187
2832
  ),
2188
- showGantt && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2833
+ showGantt && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2189
2834
  "div",
2190
2835
  {
2191
2836
  style: {
@@ -2193,7 +2838,7 @@ function TimeTravelDebugger({
2193
2838
  background: theme.bgSecondary,
2194
2839
  flexShrink: 0
2195
2840
  },
2196
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2841
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2197
2842
  GanttTimeline,
2198
2843
  {
2199
2844
  snapshots,
@@ -2213,7 +2858,7 @@ function ScrubButton({
2213
2858
  disabled,
2214
2859
  onClick
2215
2860
  }) {
2216
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2861
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2217
2862
  "button",
2218
2863
  {
2219
2864
  onClick,
@@ -2239,14 +2884,14 @@ function ScrubButton({
2239
2884
  }
2240
2885
 
2241
2886
  // src/components/FlowchartView/SubflowBreadcrumb.tsx
2242
- var import_react15 = require("react");
2243
- var import_jsx_runtime10 = require("react/jsx-runtime");
2244
- var SubflowBreadcrumb = (0, import_react15.memo)(function SubflowBreadcrumb2({
2887
+ var import_react19 = require("react");
2888
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2889
+ var SubflowBreadcrumb = (0, import_react19.memo)(function SubflowBreadcrumb2({
2245
2890
  breadcrumbs,
2246
2891
  onNavigate
2247
2892
  }) {
2248
2893
  if (breadcrumbs.length <= 1) return null;
2249
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2894
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2250
2895
  "div",
2251
2896
  {
2252
2897
  style: {
@@ -2263,10 +2908,10 @@ var SubflowBreadcrumb = (0, import_react15.memo)(function SubflowBreadcrumb2({
2263
2908
  },
2264
2909
  children: breadcrumbs.map((crumb, i) => {
2265
2910
  const isLast = i === breadcrumbs.length - 1;
2266
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2267
- i > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
2268
- isLast ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2269
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2911
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2912
+ i > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
2913
+ isLast ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
2914
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2270
2915
  "span",
2271
2916
  {
2272
2917
  style: {
@@ -2276,7 +2921,7 @@ var SubflowBreadcrumb = (0, import_react15.memo)(function SubflowBreadcrumb2({
2276
2921
  children: crumb.label
2277
2922
  }
2278
2923
  ),
2279
- crumb.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2924
+ crumb.description && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2280
2925
  "span",
2281
2926
  {
2282
2927
  style: {
@@ -2290,7 +2935,7 @@ var SubflowBreadcrumb = (0, import_react15.memo)(function SubflowBreadcrumb2({
2290
2935
  ]
2291
2936
  }
2292
2937
  )
2293
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2938
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2294
2939
  "button",
2295
2940
  {
2296
2941
  onClick: () => onNavigate(i),
@@ -2322,12 +2967,12 @@ var SubflowBreadcrumb = (0, import_react15.memo)(function SubflowBreadcrumb2({
2322
2967
  });
2323
2968
 
2324
2969
  // src/components/FlowchartView/useSubflowNavigation.ts
2325
- var import_react16 = require("react");
2970
+ var import_react20 = require("react");
2326
2971
  var EMPTY_GRAPH2 = { nodes: [], edges: [] };
2327
2972
  function useSubflowNavigation(rootGraph) {
2328
- const [stack, setStack] = (0, import_react16.useState)([]);
2973
+ const [stack, setStack] = (0, import_react20.useState)([]);
2329
2974
  const safeRootGraph = rootGraph ?? EMPTY_GRAPH2;
2330
- const subflowMounts = (0, import_react16.useMemo)(() => {
2975
+ const subflowMounts = (0, import_react20.useMemo)(() => {
2331
2976
  const map = /* @__PURE__ */ new Map();
2332
2977
  for (const node of safeRootGraph.nodes) {
2333
2978
  if (!node.data?.isSubflow) continue;
@@ -2345,12 +2990,12 @@ function useSubflowNavigation(rootGraph) {
2345
2990
  }
2346
2991
  return map;
2347
2992
  }, [safeRootGraph]);
2348
- const breadcrumbs = (0, import_react16.useMemo)(() => {
2993
+ const breadcrumbs = (0, import_react20.useMemo)(() => {
2349
2994
  const rootLabel = "Flowchart";
2350
2995
  const root = { label: rootLabel };
2351
2996
  return [root, ...stack];
2352
2997
  }, [stack]);
2353
- const handleNodeClick = (0, import_react16.useCallback)(
2998
+ const handleNodeClick = (0, import_react20.useCallback)(
2354
2999
  (nodeId) => {
2355
3000
  const mount = subflowMounts.get(nodeId);
2356
3001
  if (!mount) return false;
@@ -2366,7 +3011,7 @@ function useSubflowNavigation(rootGraph) {
2366
3011
  },
2367
3012
  [subflowMounts]
2368
3013
  );
2369
- const navigateTo = (0, import_react16.useCallback)((level) => {
3014
+ const navigateTo = (0, import_react20.useCallback)((level) => {
2370
3015
  if (level === 0) {
2371
3016
  setStack([]);
2372
3017
  } else {
@@ -2388,8 +3033,8 @@ function useSubflowNavigation(rootGraph) {
2388
3033
  }
2389
3034
 
2390
3035
  // src/components/FlowchartView/SubflowTree.tsx
2391
- var import_react17 = require("react");
2392
- var import_jsx_runtime11 = require("react/jsx-runtime");
3036
+ var import_react21 = require("react");
3037
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2393
3038
  function graphToSubflowEntries(graph) {
2394
3039
  if (!graph?.nodes?.length) return [];
2395
3040
  const entries = [];
@@ -2405,25 +3050,25 @@ function graphToSubflowEntries(graph) {
2405
3050
  }
2406
3051
  return entries;
2407
3052
  }
2408
- var TreeNode = (0, import_react17.memo)(function TreeNode2({
3053
+ var TreeNode = (0, import_react21.memo)(function TreeNode2({
2409
3054
  entry,
2410
3055
  depth,
2411
3056
  activeStage,
2412
3057
  doneStages,
2413
3058
  onNodeSelect
2414
3059
  }) {
2415
- const [expanded, setExpanded] = (0, import_react17.useState)(true);
3060
+ const [expanded, setExpanded] = (0, import_react21.useState)(true);
2416
3061
  const hasChildren = entry.children && entry.children.length > 0;
2417
3062
  const isActive = activeStage === entry.name;
2418
3063
  const isDone = doneStages?.has(entry.name);
2419
- const handleClick = (0, import_react17.useCallback)(() => {
3064
+ const handleClick = (0, import_react21.useCallback)(() => {
2420
3065
  if (hasChildren) {
2421
3066
  setExpanded((prev) => !prev);
2422
3067
  }
2423
3068
  onNodeSelect?.(entry.name, !!entry.isSubflow);
2424
3069
  }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
2425
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2426
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3070
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3071
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2427
3072
  "button",
2428
3073
  {
2429
3074
  onClick: handleClick,
@@ -2454,7 +3099,7 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2454
3099
  }
2455
3100
  },
2456
3101
  children: [
2457
- hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3102
+ hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2458
3103
  "span",
2459
3104
  {
2460
3105
  style: {
@@ -2469,8 +3114,8 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2469
3114
  },
2470
3115
  children: "\u25B6"
2471
3116
  }
2472
- ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { width: 12, flexShrink: 0 } }),
2473
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3117
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { width: 12, flexShrink: 0 } }),
3118
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2474
3119
  "span",
2475
3120
  {
2476
3121
  style: {
@@ -2482,8 +3127,8 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2482
3127
  }
2483
3128
  }
2484
3129
  ),
2485
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
2486
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3130
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
3131
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2487
3132
  "span",
2488
3133
  {
2489
3134
  style: {
@@ -2495,11 +3140,11 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2495
3140
  },
2496
3141
  children: [
2497
3142
  entry.name,
2498
- entry.isSubflow && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
3143
+ entry.isSubflow && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
2499
3144
  ]
2500
3145
  }
2501
3146
  ),
2502
- entry.description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3147
+ entry.description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2503
3148
  "span",
2504
3149
  {
2505
3150
  style: {
@@ -2516,7 +3161,7 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2516
3161
  ]
2517
3162
  }
2518
3163
  ),
2519
- hasChildren && expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: entry.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3164
+ hasChildren && expanded && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: entry.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2520
3165
  TreeNode2,
2521
3166
  {
2522
3167
  entry: child,
@@ -2529,8 +3174,8 @@ var TreeNode = (0, import_react17.memo)(function TreeNode2({
2529
3174
  )) })
2530
3175
  ] });
2531
3176
  });
2532
- var SectionLabel = (0, import_react17.memo)(function SectionLabel2({ children }) {
2533
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3177
+ var SectionLabel = (0, import_react21.memo)(function SectionLabel2({ children }) {
3178
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2534
3179
  "div",
2535
3180
  {
2536
3181
  style: {
@@ -2545,7 +3190,7 @@ var SectionLabel = (0, import_react17.memo)(function SectionLabel2({ children })
2545
3190
  }
2546
3191
  );
2547
3192
  });
2548
- var SubflowTree = (0, import_react17.memo)(function SubflowTree2({
3193
+ var SubflowTree = (0, import_react21.memo)(function SubflowTree2({
2549
3194
  graph,
2550
3195
  activeStage,
2551
3196
  doneStages,
@@ -2554,9 +3199,9 @@ var SubflowTree = (0, import_react17.memo)(function SubflowTree2({
2554
3199
  className,
2555
3200
  style
2556
3201
  }) {
2557
- const subflowStages = (0, import_react17.useMemo)(() => graphToSubflowEntries(graph), [graph]);
3202
+ const subflowStages = (0, import_react21.useMemo)(() => graphToSubflowEntries(graph), [graph]);
2558
3203
  if (subflowStages.length === 0) return null;
2559
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3204
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2560
3205
  "div",
2561
3206
  {
2562
3207
  className,
@@ -2574,8 +3219,8 @@ var SubflowTree = (0, import_react17.memo)(function SubflowTree2({
2574
3219
  ...style
2575
3220
  },
2576
3221
  children: [
2577
- !unstyled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SectionLabel, { children: "Subflows" }),
2578
- subflowStages.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3222
+ !unstyled && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionLabel, { children: "Subflows" }),
3223
+ subflowStages.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2579
3224
  TreeNode,
2580
3225
  {
2581
3226
  entry,
@@ -2603,9 +3248,13 @@ function asRuntimeStageId(s) {
2603
3248
  function walkSubflowSpecInto(spec, subflowPath, sink) {
2604
3249
  walkNode(spec, subflowPath, sink, /* @__PURE__ */ new Set());
2605
3250
  }
3251
+ function qid(subflowPath, localId) {
3252
+ return `${subflowPath}/${localId}`;
3253
+ }
2606
3254
  function walkNode(node, subflowPath, sink, visited) {
2607
- if (visited.has(node.id)) return;
2608
- visited.add(node.id);
3255
+ const fullId = qid(subflowPath, node.id);
3256
+ if (visited.has(fullId)) return;
3257
+ visited.add(fullId);
2609
3258
  if (node.isLoopReference) return;
2610
3259
  if (node.isSubflowRoot && node.subflowId !== void 0 && node.subflowStructure) {
2611
3260
  const nestedPath = `${subflowPath}/${node.subflowId}`;
@@ -2616,7 +3265,6 @@ function walkNode(node, subflowPath, sink, visited) {
2616
3265
  const isFork = type === "fork";
2617
3266
  const isStreaming = type === "streaming";
2618
3267
  const isSubflow = !!node.isSubflowRoot;
2619
- const stageId = asStageId(node.id);
2620
3268
  const data = {
2621
3269
  label: node.name,
2622
3270
  isDecider,
@@ -2633,7 +3281,7 @@ function walkNode(node, subflowPath, sink, visited) {
2633
3281
  if (node.isLazy === true) data.isLazy = true;
2634
3282
  if (node.isPausable === true) data.isPausable = true;
2635
3283
  sink.upsertNode({
2636
- id: node.id,
3284
+ id: asStageId(fullId),
2637
3285
  type: "stage",
2638
3286
  position: { x: 0, y: 0 },
2639
3287
  data
@@ -2641,13 +3289,14 @@ function walkNode(node, subflowPath, sink, visited) {
2641
3289
  if (node.children && node.children.length > 0) {
2642
3290
  const edgeKind = type === "fork" ? "fork-branch" : "decision-branch";
2643
3291
  for (const child of node.children) {
2644
- const edgeId = `${node.id}->${child.id}:${edgeKind}${edgeKind === "decision-branch" ? `:${child.id}` : ""}`;
3292
+ const childFullId = qid(subflowPath, child.id);
3293
+ const edgeId = `${fullId}->${childFullId}:${edgeKind}${edgeKind === "decision-branch" ? `:${child.id}` : ""}`;
2645
3294
  const edgeData = { kind: edgeKind };
2646
3295
  if (edgeKind === "decision-branch") edgeData.label = child.id;
2647
3296
  const edge = {
2648
3297
  id: edgeId,
2649
- source: node.id,
2650
- target: child.id,
3298
+ source: fullId,
3299
+ target: childFullId,
2651
3300
  data: edgeData
2652
3301
  };
2653
3302
  if (edgeKind === "decision-branch") edge.label = child.id;
@@ -2657,24 +3306,25 @@ function walkNode(node, subflowPath, sink, visited) {
2657
3306
  }
2658
3307
  if (node.next) {
2659
3308
  if (node.next.isLoopReference && node.loopTarget) {
3309
+ const loopFullId = qid(subflowPath, node.loopTarget);
2660
3310
  sink.pushEdge({
2661
- id: `${node.id}->${node.loopTarget}:loop`,
2662
- source: node.id,
2663
- target: node.loopTarget,
3311
+ id: `${fullId}->${loopFullId}:loop`,
3312
+ source: fullId,
3313
+ target: loopFullId,
2664
3314
  data: { kind: "loop" }
2665
3315
  });
2666
3316
  } else {
2667
- const edgeId = `${node.id}->${node.next.id}:next`;
3317
+ const nextFullId = qid(subflowPath, node.next.id);
3318
+ const edgeId = `${fullId}->${nextFullId}:next`;
2668
3319
  sink.pushEdge({
2669
3320
  id: edgeId,
2670
- source: node.id,
2671
- target: node.next.id,
3321
+ source: fullId,
3322
+ target: nextFullId,
2672
3323
  data: { kind: "next" }
2673
3324
  });
2674
3325
  walkNode(node.next, subflowPath, sink, visited);
2675
3326
  }
2676
3327
  }
2677
- void stageId;
2678
3328
  }
2679
3329
 
2680
3330
  // src/components/FlowchartView/traceStructureRecorder.ts
@@ -2870,6 +3520,361 @@ function createTraceStructureRecorder(options = {}) {
2870
3520
  };
2871
3521
  }
2872
3522
 
3523
+ // src/components/SlotPillNode/SlotPillNode.tsx
3524
+ var import_react22 = require("@xyflow/react");
3525
+ var import_jsx_runtime15 = require("react/jsx-runtime");
3526
+ var C2 = rawDefaults.colors;
3527
+ function SlotPillNode({ data }) {
3528
+ const d = data;
3529
+ const lit = !!(d.active || d.selected);
3530
+ const accent = lit ? C2.primary : d.done ? C2.success : C2.textMuted;
3531
+ const opacity = d.dimmed && !lit ? 0.45 : 1;
3532
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3533
+ "div",
3534
+ {
3535
+ style: {
3536
+ width: "100%",
3537
+ height: "100%",
3538
+ boxSizing: "border-box",
3539
+ display: "flex",
3540
+ alignItems: "center",
3541
+ gap: 8,
3542
+ padding: "0 12px",
3543
+ borderRadius: 999,
3544
+ // full pill
3545
+ border: `1.5px solid ${lit ? C2.primary : C2.border}`,
3546
+ background: lit ? "rgba(99, 102, 241, 0.14)" : "rgba(148, 163, 184, 0.06)",
3547
+ boxShadow: lit ? `0 0 0 2px rgba(99,102,241,0.25)` : "none",
3548
+ opacity,
3549
+ fontSize: 12,
3550
+ fontWeight: 600,
3551
+ color: lit ? C2.textPrimary : C2.textSecondary,
3552
+ whiteSpace: "nowrap",
3553
+ overflow: "hidden",
3554
+ transition: "opacity 120ms, box-shadow 120ms, border-color 120ms"
3555
+ },
3556
+ title: d.label,
3557
+ children: [
3558
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3559
+ "span",
3560
+ {
3561
+ "aria-hidden": true,
3562
+ style: {
3563
+ flexShrink: 0,
3564
+ width: 8,
3565
+ height: 8,
3566
+ borderRadius: "50%",
3567
+ background: accent
3568
+ }
3569
+ }
3570
+ ),
3571
+ d.icon ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { "aria-hidden": true, style: { flexShrink: 0 }, children: d.icon }) : null,
3572
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: d.label }),
3573
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react22.Handle, { type: "target", position: import_react22.Position.Top, style: { opacity: 0 } }),
3574
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react22.Handle, { type: "source", position: import_react22.Position.Bottom, style: { opacity: 0 } })
3575
+ ]
3576
+ }
3577
+ );
3578
+ }
3579
+
3580
+ // src/components/FlowchartView/_internal/snapLinearSuccessors.ts
3581
+ function snapLinearSuccessors(graph, options = {}) {
3582
+ if (graph.nodes.length === 0) return graph;
3583
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
3584
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
3585
+ const byId = /* @__PURE__ */ new Map();
3586
+ const width = /* @__PURE__ */ new Map();
3587
+ for (const n of graph.nodes) {
3588
+ byId.set(n.id, n);
3589
+ width.set(n.id, sizeOf(n, fallbackW, fallbackH, options.nodeSize).width);
3590
+ }
3591
+ const preds = /* @__PURE__ */ new Map();
3592
+ const outDegree = /* @__PURE__ */ new Map();
3593
+ const seenEdge = /* @__PURE__ */ new Set();
3594
+ for (const e of graph.edges) {
3595
+ if (e.data?.kind === "loop") continue;
3596
+ if (!byId.has(e.source) || !byId.has(e.target)) continue;
3597
+ const key = `${e.source}\0${e.target}`;
3598
+ if (seenEdge.has(key)) continue;
3599
+ seenEdge.add(key);
3600
+ const list = preds.get(e.target);
3601
+ if (list) list.push(e.source);
3602
+ else preds.set(e.target, [e.source]);
3603
+ outDegree.set(e.source, (outDegree.get(e.source) ?? 0) + 1);
3604
+ }
3605
+ const workingX = /* @__PURE__ */ new Map();
3606
+ for (const n of graph.nodes) workingX.set(n.id, n.position.x);
3607
+ const centerX = (id) => workingX.get(id) + width.get(id) / 2;
3608
+ const order = [...graph.nodes].sort(
3609
+ (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)
3610
+ );
3611
+ for (const n of order) {
3612
+ const p = preds.get(n.id);
3613
+ if (!p || p.length !== 1) continue;
3614
+ const pid = p[0];
3615
+ if ((outDegree.get(pid) ?? 0) !== 1) continue;
3616
+ const P = byId.get(pid);
3617
+ if ((n.parentId ?? void 0) !== (P.parentId ?? void 0)) continue;
3618
+ workingX.set(n.id, centerX(pid) - width.get(n.id) / 2);
3619
+ }
3620
+ const nodes = graph.nodes.map((n) => {
3621
+ const nx = workingX.get(n.id);
3622
+ return nx === n.position.x ? n : { ...n, position: { x: nx, y: n.position.y } };
3623
+ });
3624
+ return { nodes, edges: graph.edges };
3625
+ }
3626
+ function createSnappedDagreLayout(base, options = {}) {
3627
+ return (graph) => snapLinearSuccessors(base(graph), options);
3628
+ }
3629
+
3630
+ // src/components/FlowchartView/_internal/traceGroupLayout.ts
3631
+ function buildAdjacency(graph, fallbackW, fallbackH, nodeSize) {
3632
+ const preds = /* @__PURE__ */ new Map();
3633
+ const branchSuccs = /* @__PURE__ */ new Map();
3634
+ const width = /* @__PURE__ */ new Map();
3635
+ const height = /* @__PURE__ */ new Map();
3636
+ const resolvedStyle = /* @__PURE__ */ new Map();
3637
+ const ids = /* @__PURE__ */ new Set();
3638
+ for (const n of graph.nodes) {
3639
+ ids.add(n.id);
3640
+ const s = sizeOf(n, fallbackW, fallbackH, nodeSize);
3641
+ width.set(n.id, s.width);
3642
+ height.set(n.id, s.height);
3643
+ const resolved = nodeSize?.(n);
3644
+ if (resolved && resolved.width === s.width && resolved.height === s.height) {
3645
+ resolvedStyle.set(n.id, resolved);
3646
+ }
3647
+ preds.set(n.id, []);
3648
+ branchSuccs.set(n.id, []);
3649
+ }
3650
+ const seen = /* @__PURE__ */ new Set();
3651
+ for (const e of graph.edges) {
3652
+ if (e.data?.kind === "loop") continue;
3653
+ if (!ids.has(e.source) || !ids.has(e.target)) continue;
3654
+ const key = `${e.source}\0${e.target}`;
3655
+ if (seen.has(key)) continue;
3656
+ seen.add(key);
3657
+ preds.get(e.target).push(e.source);
3658
+ if (e.data?.kind === "fork-branch" || e.data?.kind === "decision-branch") {
3659
+ branchSuccs.get(e.source).push(e.target);
3660
+ }
3661
+ }
3662
+ return { preds, branchSuccs, width, height, resolvedStyle };
3663
+ }
3664
+ function assignRanks(preds, ids) {
3665
+ const rank = /* @__PURE__ */ new Map();
3666
+ const inProgress = /* @__PURE__ */ new Set();
3667
+ const visit = (id) => {
3668
+ const memo4 = rank.get(id);
3669
+ if (memo4 !== void 0) return memo4;
3670
+ if (inProgress.has(id)) return 0;
3671
+ inProgress.add(id);
3672
+ const ps = preds.get(id) ?? [];
3673
+ let r = 0;
3674
+ for (const p of ps) {
3675
+ const pr = visit(p);
3676
+ if (pr + 1 > r) r = pr + 1;
3677
+ }
3678
+ inProgress.delete(id);
3679
+ rank.set(id, r);
3680
+ return r;
3681
+ };
3682
+ for (const id of ids) visit(id);
3683
+ return rank;
3684
+ }
3685
+ function spanCenter(ids, center, width) {
3686
+ let left = Infinity;
3687
+ let right = -Infinity;
3688
+ for (const id of ids) {
3689
+ const c = center.get(id);
3690
+ if (c === void 0) continue;
3691
+ const w = width.get(id) ?? 0;
3692
+ if (c - w / 2 < left) left = c - w / 2;
3693
+ if (c + w / 2 > right) right = c + w / 2;
3694
+ }
3695
+ if (!Number.isFinite(left)) return 0;
3696
+ return (left + right) / 2;
3697
+ }
3698
+ function ancestorsOf(start, preds) {
3699
+ const seen = /* @__PURE__ */ new Set();
3700
+ const stack = [start];
3701
+ while (stack.length) {
3702
+ const n = stack.pop();
3703
+ if (seen.has(n)) continue;
3704
+ seen.add(n);
3705
+ for (const p of preds.get(n) ?? []) if (!seen.has(p)) stack.push(p);
3706
+ }
3707
+ return seen;
3708
+ }
3709
+ function lowestCommonAncestor(inputs, preds, rank) {
3710
+ if (inputs.length === 0) return void 0;
3711
+ let common = ancestorsOf(inputs[0], preds);
3712
+ for (let i = 1; i < inputs.length && common.size > 0; i++) {
3713
+ const a = ancestorsOf(inputs[i], preds);
3714
+ common = new Set([...common].filter((x) => a.has(x)));
3715
+ }
3716
+ let best;
3717
+ let bestRank = -Infinity;
3718
+ for (const id of common) {
3719
+ const r = rank.get(id) ?? -Infinity;
3720
+ if (r > bestRank) bestRank = r, best = id;
3721
+ }
3722
+ return best;
3723
+ }
3724
+ function orderBand(ids, preds, center, insertionIndex, siblingOrder) {
3725
+ if (siblingOrder && ids.length > 1) {
3726
+ const parents = new Set(ids.map((id) => preds.get(id)?.[0]));
3727
+ if (parents.size === 1) {
3728
+ const parent = [...parents][0];
3729
+ if (parent !== void 0) {
3730
+ const ordered = siblingOrder(parent, ids);
3731
+ const used = /* @__PURE__ */ new Set();
3732
+ const out = [];
3733
+ for (const id of ordered) if (ids.includes(id) && !used.has(id)) out.push(id), used.add(id);
3734
+ for (const id of ids) if (!used.has(id)) out.push(id);
3735
+ return out;
3736
+ }
3737
+ }
3738
+ }
3739
+ return [...ids].sort((a, b) => {
3740
+ const pa = preds.get(a)?.[0];
3741
+ const pb = preds.get(b)?.[0];
3742
+ const ca = pa !== void 0 ? center.get(pa) : void 0;
3743
+ const cb = pb !== void 0 ? center.get(pb) : void 0;
3744
+ if (ca !== void 0 && cb !== void 0 && ca !== cb) return ca - cb;
3745
+ return (insertionIndex.get(a) ?? 0) - (insertionIndex.get(b) ?? 0);
3746
+ });
3747
+ }
3748
+ function traceGroupLayout(graph, options = {}) {
3749
+ if (graph.nodes.length === 0) return { nodes: graph.nodes, edges: graph.edges };
3750
+ if (graph.nodes.length === 1) {
3751
+ const only = graph.nodes[0];
3752
+ return { nodes: [{ ...only, position: { x: 0, y: 0 } }], edges: graph.edges };
3753
+ }
3754
+ const rankSep = options.rankSep ?? 80;
3755
+ const nodeSep = options.nodeSep ?? 60;
3756
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W2;
3757
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H2;
3758
+ const mergeCentering = options.enableMergeCentering ?? true;
3759
+ const mergeAlign = options.mergeAlign ?? "span";
3760
+ const ids = graph.nodes.map((n) => n.id);
3761
+ const insertionIndex = new Map(ids.map((id, i) => [id, i]));
3762
+ const { preds, branchSuccs, width, height, resolvedStyle } = buildAdjacency(
3763
+ graph,
3764
+ fallbackW,
3765
+ fallbackH,
3766
+ options.nodeSize
3767
+ );
3768
+ const rank = assignRanks(preds, ids);
3769
+ let maxRank = 0;
3770
+ for (const r of rank.values()) if (r > maxRank) maxRank = r;
3771
+ for (const id of ids) if (!rank.has(id)) rank.set(id, maxRank + 1);
3772
+ maxRank = 0;
3773
+ for (const r of rank.values()) if (r > maxRank) maxRank = r;
3774
+ const byRank = /* @__PURE__ */ new Map();
3775
+ const bandMaxH = /* @__PURE__ */ new Map();
3776
+ for (const id of ids) {
3777
+ const r = rank.get(id);
3778
+ (byRank.get(r) ?? byRank.set(r, []).get(r)).push(id);
3779
+ bandMaxH.set(r, Math.max(bandMaxH.get(r) ?? 0, height.get(id)));
3780
+ }
3781
+ const bandTop = /* @__PURE__ */ new Map();
3782
+ let yAcc = 0;
3783
+ for (let r = 0; r <= maxRank; r++) {
3784
+ bandTop.set(r, yAcc);
3785
+ yAcc += (bandMaxH.get(r) ?? fallbackH) + rankSep;
3786
+ }
3787
+ const center = /* @__PURE__ */ new Map();
3788
+ const mergeCenterX = (ps) => {
3789
+ if (mergeAlign === "fork-origin") {
3790
+ const lca = lowestCommonAncestor(ps, preds, rank);
3791
+ const lcaC = lca !== void 0 ? center.get(lca) : void 0;
3792
+ if (lcaC !== void 0) return lcaC;
3793
+ }
3794
+ return spanCenter(ps, center, width);
3795
+ };
3796
+ for (let r = 0; r <= maxRank; r++) {
3797
+ const band = orderBand(byRank.get(r) ?? [], preds, center, insertionIndex, options.siblingOrder);
3798
+ let cursor = -Infinity;
3799
+ let i = 0;
3800
+ while (i < band.length) {
3801
+ const id = band[i];
3802
+ const ps = preds.get(id) ?? [];
3803
+ const parent = ps.length === 1 ? ps[0] : void 0;
3804
+ const parentBranches = parent !== void 0 ? branchSuccs.get(parent) ?? [] : [];
3805
+ const isForkChild = parent !== void 0 && parentBranches.length >= 2 && parentBranches.includes(id);
3806
+ if (isForkChild) {
3807
+ const run = [];
3808
+ let j = i;
3809
+ while (j < band.length) {
3810
+ const cand = band[j];
3811
+ const cps = preds.get(cand) ?? [];
3812
+ if (cps.length === 1 && cps[0] === parent && parentBranches.includes(cand)) run.push(cand), j++;
3813
+ else break;
3814
+ }
3815
+ const totalW = run.reduce((s, rid) => s + width.get(rid), 0) + (run.length - 1) * nodeSep;
3816
+ let left = (center.get(parent) ?? 0) - totalW / 2;
3817
+ if (cursor !== -Infinity && left < cursor) left = cursor;
3818
+ let x = left;
3819
+ for (const rid of run) {
3820
+ const w = width.get(rid);
3821
+ center.set(rid, x + w / 2);
3822
+ x += w + nodeSep;
3823
+ }
3824
+ cursor = x;
3825
+ i = j;
3826
+ } else {
3827
+ const w = width.get(id);
3828
+ let desired;
3829
+ if (ps.length === 0) desired = (cursor === -Infinity ? 0 : cursor) + w / 2;
3830
+ else if (ps.length === 1) desired = center.get(ps[0]) ?? 0;
3831
+ else desired = mergeCenterX(ps);
3832
+ const cursorCenter = cursor === -Infinity ? -Infinity : cursor + w / 2;
3833
+ const c = Math.max(cursorCenter, desired);
3834
+ center.set(id, c);
3835
+ cursor = c + w / 2 + nodeSep;
3836
+ i++;
3837
+ }
3838
+ }
3839
+ }
3840
+ if (mergeCentering) {
3841
+ for (let r = maxRank; r >= 1; r--) {
3842
+ for (const id of byRank.get(r) ?? []) {
3843
+ const ps = preds.get(id) ?? [];
3844
+ if (ps.length > 1) center.set(id, mergeCenterX(ps));
3845
+ }
3846
+ }
3847
+ }
3848
+ const centerById = center;
3849
+ const positioned = graph.nodes.map((n) => {
3850
+ const r = rank.get(n.id);
3851
+ const w = width.get(n.id);
3852
+ const h = height.get(n.id);
3853
+ let x = (centerById.get(n.id) ?? 0) - w / 2;
3854
+ let y = (bandTop.get(r) ?? 0) + ((bandMaxH.get(r) ?? h) - h) / 2;
3855
+ if (n.parentId) {
3856
+ const pr = rank.get(n.parentId);
3857
+ const pw = width.get(n.parentId);
3858
+ const ph = height.get(n.parentId);
3859
+ if (pr !== void 0 && pw !== void 0 && ph !== void 0) {
3860
+ const parentX = (centerById.get(n.parentId) ?? 0) - pw / 2;
3861
+ const parentY = (bandTop.get(pr) ?? 0) + ((bandMaxH.get(pr) ?? ph) - ph) / 2;
3862
+ x -= parentX;
3863
+ y -= parentY;
3864
+ }
3865
+ }
3866
+ const styleSize = resolvedStyle.get(n.id);
3867
+ if (styleSize) {
3868
+ return { ...n, position: { x, y }, style: { ...n.style ?? {}, width: styleSize.width, height: styleSize.height } };
3869
+ }
3870
+ return { ...n, position: { x, y } };
3871
+ });
3872
+ return { nodes: positioned, edges: graph.edges };
3873
+ }
3874
+ function createTraceGroupLayout(options = {}) {
3875
+ return (graph) => traceGroupLayout(graph, options);
3876
+ }
3877
+
2873
3878
  // src/components/FlowchartView/createNodeViewRecorder.ts
2874
3879
  function baseStageIdOf(runtimeStageId) {
2875
3880
  const hashIdx = runtimeStageId.indexOf("#");
@@ -3291,12 +4296,12 @@ function createTraceBundle(options = {}) {
3291
4296
  }
3292
4297
 
3293
4298
  // src/components/FlowchartView/_internal/useTranslator.ts
3294
- var import_react18 = require("react");
4299
+ var import_react23 = require("react");
3295
4300
  function useTranslator(handle, getSnapshot) {
3296
- const subscribe = (0, import_react18.useMemo)(() => handle.subscribe.bind(handle), [handle]);
3297
- const getVersion = (0, import_react18.useMemo)(() => handle.version.bind(handle), [handle]);
3298
- const version = (0, import_react18.useSyncExternalStore)(subscribe, getVersion, getVersion);
3299
- return (0, import_react18.useMemo)(() => getSnapshot(), [version, getSnapshot]);
4301
+ const subscribe = (0, import_react23.useMemo)(() => handle.subscribe.bind(handle), [handle]);
4302
+ const getVersion = (0, import_react23.useMemo)(() => handle.version.bind(handle), [handle]);
4303
+ const version = (0, import_react23.useSyncExternalStore)(subscribe, getVersion, getVersion);
4304
+ return (0, import_react23.useMemo)(() => getSnapshot(), [version, getSnapshot]);
3300
4305
  }
3301
4306
 
3302
4307
  // src/components/FlowchartView/walkHelpers.ts
@@ -3379,8 +4384,8 @@ function bfsWalk(index, startId, neighborsOf, options) {
3379
4384
  }
3380
4385
 
3381
4386
  // src/components/FlowchartView/NodeInspector.tsx
3382
- var import_react19 = require("react");
3383
- var import_jsx_runtime12 = require("react/jsx-runtime");
4387
+ var import_react24 = require("react");
4388
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3384
4389
  function NodeInspector({
3385
4390
  index,
3386
4391
  selectedId,
@@ -3390,16 +4395,16 @@ function NodeInspector({
3390
4395
  style
3391
4396
  }) {
3392
4397
  const view = selectedId ? index.byStageId.get(selectedId) ?? null : null;
3393
- const prevChain = (0, import_react19.useMemo)(
4398
+ const prevChain = (0, import_react24.useMemo)(
3394
4399
  () => view ? backtraceStructural(index, view.stageId, { onlyVisited }) : [],
3395
4400
  [index, view, onlyVisited]
3396
4401
  );
3397
- const nextChain = (0, import_react19.useMemo)(
4402
+ const nextChain = (0, import_react24.useMemo)(
3398
4403
  () => view ? forwardtraceStructural(index, view.stageId, { onlyVisited }) : [],
3399
4404
  [index, view, onlyVisited]
3400
4405
  );
3401
4406
  if (!view) {
3402
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4407
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3403
4408
  "div",
3404
4409
  {
3405
4410
  className,
@@ -3413,7 +4418,7 @@ function NodeInspector({
3413
4418
  }
3414
4419
  );
3415
4420
  }
3416
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4421
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3417
4422
  "div",
3418
4423
  {
3419
4424
  className,
@@ -3425,9 +4430,9 @@ function NodeInspector({
3425
4430
  ...style
3426
4431
  },
3427
4432
  children: [
3428
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginBottom: 16 }, children: [
3429
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.label }),
3430
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { fontSize: 11, fontFamily: "monospace", color: theme.textMuted, marginTop: 2 }, children: [
4433
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { marginBottom: 16 }, children: [
4434
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.label }),
4435
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { fontSize: 11, fontFamily: "monospace", color: theme.textMuted, marginTop: 2 }, children: [
3431
4436
  view.stageId,
3432
4437
  " \xB7 ",
3433
4438
  view.type,
@@ -3437,42 +4442,42 @@ function NodeInspector({
3437
4442
  view.isStreaming && " \xB7 streaming",
3438
4443
  view.isPausable && " \xB7 pausable"
3439
4444
  ] }),
3440
- view.description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontSize: 12, color: theme.textSecondary, marginTop: 6 }, children: view.description })
4445
+ view.description && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontSize: 12, color: theme.textSecondary, marginTop: 6 }, children: view.description })
3441
4446
  ] }),
3442
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Section, { title: "Runtime", children: [
3443
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "Visited", value: view.visitedInRun ? "yes" : "no" }),
3444
- view.visitedInRun && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3445
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "Executions", value: String(view.executionCount) }),
3446
- view.firstExecutedAt !== null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "First at", value: `${view.firstExecutedAt.toFixed(1)}ms` }),
3447
- view.lastExecutedAt !== null && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "Last at", value: `${view.lastExecutedAt.toFixed(1)}ms` }),
3448
- view.totalDurationMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "Total", value: `${view.totalDurationMs.toFixed(1)}ms` }),
3449
- view.errorCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Row, { label: "Errors", value: String(view.errorCount), valueColor: theme.error })
4447
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Section, { title: "Runtime", children: [
4448
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Visited", value: view.visitedInRun ? "yes" : "no" }),
4449
+ view.visitedInRun && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
4450
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Executions", value: String(view.executionCount) }),
4451
+ view.firstExecutedAt !== null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "First at", value: `${view.firstExecutedAt.toFixed(1)}ms` }),
4452
+ view.lastExecutedAt !== null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Last at", value: `${view.lastExecutedAt.toFixed(1)}ms` }),
4453
+ view.totalDurationMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Total", value: `${view.totalDurationMs.toFixed(1)}ms` }),
4454
+ view.errorCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Errors", value: String(view.errorCount), valueColor: theme.error })
3450
4455
  ] })
3451
4456
  ] }),
3452
- prevChain.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { title: `Prev chain (${prevChain.length - 1} hops)`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crumbs, { nodes: prevChain.slice(0, -1), onClick: onNavigate }) }),
3453
- view.prevIds.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { title: "Multiple prev (convergence)", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4457
+ prevChain.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Section, { title: `Prev chain (${prevChain.length - 1} hops)`, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Crumbs, { nodes: prevChain.slice(0, -1), onClick: onNavigate }) }),
4458
+ view.prevIds.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Section, { title: "Multiple prev (convergence)", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3454
4459
  Crumbs,
3455
4460
  {
3456
4461
  nodes: view.prevIds.map((id) => index.byStageId.get(id)).filter((n) => n !== void 0),
3457
4462
  onClick: onNavigate
3458
4463
  }
3459
4464
  ) }),
3460
- nextChain.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { title: `Next chain (${nextChain.length - 1} hops)`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Crumbs, { nodes: nextChain.slice(1), onClick: onNavigate }) }),
3461
- view.nextIds.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { title: "Multiple next (fork/decider)", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4465
+ nextChain.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Section, { title: `Next chain (${nextChain.length - 1} hops)`, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Crumbs, { nodes: nextChain.slice(1), onClick: onNavigate }) }),
4466
+ view.nextIds.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Section, { title: "Multiple next (fork/decider)", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3462
4467
  Crumbs,
3463
4468
  {
3464
4469
  nodes: view.nextIds.map((id) => index.byStageId.get(id)).filter((n) => n !== void 0),
3465
4470
  onClick: onNavigate
3466
4471
  }
3467
4472
  ) }),
3468
- view.commitRuntimeStageIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { title: `Commits (${view.commitRuntimeStageIds.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: view.commitRuntimeStageIds.map((rsid) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: rsid }, rsid)) }) })
4473
+ view.commitRuntimeStageIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Section, { title: `Commits (${view.commitRuntimeStageIds.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: view.commitRuntimeStageIds.map((rsid) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: rsid }, rsid)) }) })
3469
4474
  ]
3470
4475
  }
3471
4476
  );
3472
4477
  }
3473
4478
  function Section({ title, children }) {
3474
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginBottom: 14 }, children: [
3475
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4479
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { marginBottom: 14 }, children: [
4480
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3476
4481
  "div",
3477
4482
  {
3478
4483
  style: {
@@ -3490,15 +4495,15 @@ function Section({ title, children }) {
3490
4495
  ] });
3491
4496
  }
3492
4497
  function Row({ label, value, valueColor }) {
3493
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 12, padding: "2px 0" }, children: [
3494
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { color: theme.textMuted }, children: label }),
3495
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { color: valueColor ?? theme.textSecondary, fontFamily: "monospace" }, children: value })
4498
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 12, padding: "2px 0" }, children: [
4499
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { color: theme.textMuted }, children: label }),
4500
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { color: valueColor ?? theme.textSecondary, fontFamily: "monospace" }, children: value })
3496
4501
  ] });
3497
4502
  }
3498
4503
  function Crumbs({ nodes, onClick }) {
3499
4504
  if (nodes.length === 0) return null;
3500
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: nodes.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
3501
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4505
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: nodes.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
4506
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3502
4507
  "button",
3503
4508
  {
3504
4509
  onClick: onClick ? () => onClick(n.stageId) : void 0,
@@ -3515,13 +4520,13 @@ function Crumbs({ nodes, onClick }) {
3515
4520
  children: n.label
3516
4521
  }
3517
4522
  ),
3518
- i < nodes.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" })
4523
+ i < nodes.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" })
3519
4524
  ] }, n.stageId)) });
3520
4525
  }
3521
4526
 
3522
4527
  // src/components/FlowchartView/CommitInspector.tsx
3523
- var import_react20 = require("react");
3524
- var import_jsx_runtime13 = require("react/jsx-runtime");
4528
+ var import_react25 = require("react");
4529
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3525
4530
  function CommitInspector({
3526
4531
  index,
3527
4532
  selectedRuntimeStageId,
@@ -3530,12 +4535,12 @@ function CommitInspector({
3530
4535
  style
3531
4536
  }) {
3532
4537
  const view = selectedRuntimeStageId ? index.byRuntimeStageId.get(selectedRuntimeStageId) ?? null : null;
3533
- const lineage = (0, import_react20.useMemo)(
4538
+ const lineage = (0, import_react25.useMemo)(
3534
4539
  () => view ? backtraceDataFlow(index, view.runtimeStageId) : [],
3535
4540
  [index, view]
3536
4541
  );
3537
4542
  if (!view) {
3538
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4543
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3539
4544
  "div",
3540
4545
  {
3541
4546
  className,
@@ -3549,7 +4554,7 @@ function CommitInspector({
3549
4554
  }
3550
4555
  );
3551
4556
  }
3552
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4557
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3553
4558
  "div",
3554
4559
  {
3555
4560
  className,
@@ -3561,9 +4566,9 @@ function CommitInspector({
3561
4566
  ...style
3562
4567
  },
3563
4568
  children: [
3564
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: 16 }, children: [
3565
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.stageId }),
3566
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4569
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { marginBottom: 16 }, children: [
4570
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { fontSize: 16, fontWeight: 700, color: theme.textPrimary }, children: view.stageId }),
4571
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3567
4572
  "div",
3568
4573
  {
3569
4574
  style: {
@@ -3580,15 +4585,15 @@ function CommitInspector({
3580
4585
  }
3581
4586
  )
3582
4587
  ] }),
3583
- view.structuralPrevIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: "Structural prev (chart shape)", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PlainTags, { labels: view.structuralPrevIds }) }),
3584
- view.structuralNextIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: "Structural next (chart shape)", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PlainTags, { labels: view.structuralNextIds }) }),
3585
- view.runtimePrevIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: "Runtime prev (this execution)", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RuntimeRefs, { refs: view.runtimePrevIds, onClick: onNavigate }) }),
3586
- view.runtimeNextIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: "Runtime next (this execution)", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RuntimeRefs, { refs: view.runtimeNextIds, onClick: onNavigate }) }),
3587
- Object.keys(view.updates).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: `Updates (${Object.keys(view.updates).length})`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KeyValueGrid, { entries: Object.entries(view.updates) }) }),
3588
- view.reads.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: `Reads (${view.reads.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PlainTags, { labels: view.reads }) }),
3589
- view.dataDependencies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: `Data dependencies (${view.dataDependencies.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: view.dataDependencies.map((dep) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
3590
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0" }, children: dep.key }),
3591
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: { color: dep.sourceRuntimeStageId ? theme.textPrimary : theme.textMuted }, children: dep.sourceRuntimeStageId ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4588
+ view.structuralPrevIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: "Structural prev (chart shape)", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PlainTags, { labels: view.structuralPrevIds }) }),
4589
+ view.structuralNextIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: "Structural next (chart shape)", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PlainTags, { labels: view.structuralNextIds }) }),
4590
+ view.runtimePrevIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: "Runtime prev (this execution)", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(RuntimeRefs, { refs: view.runtimePrevIds, onClick: onNavigate }) }),
4591
+ view.runtimeNextIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: "Runtime next (this execution)", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(RuntimeRefs, { refs: view.runtimeNextIds, onClick: onNavigate }) }),
4592
+ Object.keys(view.updates).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: `Updates (${Object.keys(view.updates).length})`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(KeyValueGrid, { entries: Object.entries(view.updates) }) }),
4593
+ view.reads.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: `Reads (${view.reads.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PlainTags, { labels: view.reads }) }),
4594
+ view.dataDependencies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: `Data dependencies (${view.dataDependencies.length})`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("tbody", { children: view.dataDependencies.map((dep) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("tr", { children: [
4595
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0" }, children: dep.key }),
4596
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("td", { style: { color: dep.sourceRuntimeStageId ? theme.textPrimary : theme.textMuted }, children: dep.sourceRuntimeStageId ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3592
4597
  "button",
3593
4598
  {
3594
4599
  onClick: onNavigate ? () => onNavigate(dep.sourceRuntimeStageId) : void 0,
@@ -3598,10 +4603,10 @@ function CommitInspector({
3598
4603
  dep.sourceRuntimeStageId
3599
4604
  ]
3600
4605
  }
3601
- ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("em", { children: "(no prior writer \u2014 default or external)" }) })
4606
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("em", { children: "(no prior writer \u2014 default or external)" }) })
3602
4607
  ] }, dep.key)) }) }) }),
3603
- lineage.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section2, { title: `Lineage chain (${lineage.length - 1} ancestor commits)`, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: lineage.slice(0, -1).map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
3604
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4608
+ lineage.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section2, { title: `Lineage chain (${lineage.length - 1} ancestor commits)`, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: lineage.slice(0, -1).map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
4609
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3605
4610
  "button",
3606
4611
  {
3607
4612
  onClick: onNavigate ? () => onNavigate(c.runtimeStageId) : void 0,
@@ -3609,15 +4614,15 @@ function CommitInspector({
3609
4614
  children: c.runtimeStageId
3610
4615
  }
3611
4616
  ),
3612
- i < lineage.length - 2 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u2192" })
4617
+ i < lineage.length - 2 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u2192" })
3613
4618
  ] }, c.runtimeStageId)) }) })
3614
4619
  ]
3615
4620
  }
3616
4621
  );
3617
4622
  }
3618
4623
  function Section2({ title, children }) {
3619
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { marginBottom: 14 }, children: [
3620
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4624
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { marginBottom: 14 }, children: [
4625
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3621
4626
  "div",
3622
4627
  {
3623
4628
  style: {
@@ -3635,7 +4640,7 @@ function Section2({ title, children }) {
3635
4640
  ] });
3636
4641
  }
3637
4642
  function PlainTags({ labels }) {
3638
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: labels.map((l) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4643
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: labels.map((l) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3639
4644
  "span",
3640
4645
  {
3641
4646
  style: {
@@ -3655,7 +4660,7 @@ function RuntimeRefs({
3655
4660
  refs,
3656
4661
  onClick
3657
4662
  }) {
3658
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: refs.map((r) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4663
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: refs.map((r) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3659
4664
  "button",
3660
4665
  {
3661
4666
  onClick: onClick ? () => onClick(r) : void 0,
@@ -3666,9 +4671,9 @@ function RuntimeRefs({
3666
4671
  )) });
3667
4672
  }
3668
4673
  function KeyValueGrid({ entries }) {
3669
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: entries.map(([k, v2]) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
3670
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0", verticalAlign: "top" }, children: k }),
3671
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: { color: theme.textPrimary, wordBreak: "break-word" }, children: typeof v2 === "object" ? JSON.stringify(v2) : String(v2) })
4674
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("table", { style: { fontSize: 11, fontFamily: "monospace", width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("tbody", { children: entries.map(([k, v2]) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("tr", { children: [
4675
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("td", { style: { color: theme.textSecondary, padding: "2px 8px 2px 0", verticalAlign: "top" }, children: k }),
4676
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("td", { style: { color: theme.textPrimary, wordBreak: "break-word" }, children: typeof v2 === "object" ? JSON.stringify(v2) : String(v2) })
3672
4677
  ] }, k)) }) });
3673
4678
  }
3674
4679
  function crumbButtonStyle(clickable) {
@@ -3835,7 +4840,7 @@ function decorate(node, commitsByStageId) {
3835
4840
  }
3836
4841
 
3837
4842
  // src/components/FlowchartView/CommitChainView.tsx
3838
- var import_jsx_runtime14 = require("react/jsx-runtime");
4843
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3839
4844
  function CommitChainView({
3840
4845
  chain,
3841
4846
  selectedRuntimeStageId = null,
@@ -3846,7 +4851,7 @@ function CommitChainView({
3846
4851
  style
3847
4852
  }) {
3848
4853
  if (!chain) {
3849
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4854
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3850
4855
  "div",
3851
4856
  {
3852
4857
  className,
@@ -3860,7 +4865,7 @@ function CommitChainView({
3860
4865
  }
3861
4866
  );
3862
4867
  }
3863
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4868
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3864
4869
  "div",
3865
4870
  {
3866
4871
  className,
@@ -3871,11 +4876,11 @@ function CommitChainView({
3871
4876
  overflow: "auto",
3872
4877
  ...style
3873
4878
  },
3874
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4879
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3875
4880
  ChainShell,
3876
4881
  {
3877
4882
  node: chain,
3878
- renderLeaf: (leaf) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4883
+ renderLeaf: (leaf) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3879
4884
  Leaf,
3880
4885
  {
3881
4886
  leaf,
@@ -3892,10 +4897,10 @@ function CommitChainView({
3892
4897
  }
3893
4898
  function ChainShell({ node, renderLeaf }) {
3894
4899
  if (node.kind === "leaf") {
3895
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: renderLeaf(node) });
4900
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: renderLeaf(node) });
3896
4901
  }
3897
4902
  if (node.kind === "serial") {
3898
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4903
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3899
4904
  "div",
3900
4905
  {
3901
4906
  style: {
@@ -3904,13 +4909,13 @@ function ChainShell({ node, renderLeaf }) {
3904
4909
  alignItems: "center",
3905
4910
  gap: 0
3906
4911
  },
3907
- children: node.items.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4912
+ children: node.items.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3908
4913
  "div",
3909
4914
  {
3910
4915
  style: { display: "flex", flexDirection: "column", alignItems: "center" },
3911
4916
  children: [
3912
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChainShell, { node: child, renderLeaf }),
3913
- i < node.items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Connector, { orientation: "vertical" })
4917
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChainShell, { node: child, renderLeaf }),
4918
+ i < node.items.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Connector, { orientation: "vertical" })
3914
4919
  ]
3915
4920
  },
3916
4921
  chainKey(child, i)
@@ -3918,7 +4923,7 @@ function ChainShell({ node, renderLeaf }) {
3918
4923
  }
3919
4924
  );
3920
4925
  }
3921
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4926
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3922
4927
  "div",
3923
4928
  {
3924
4929
  style: {
@@ -3928,8 +4933,8 @@ function ChainShell({ node, renderLeaf }) {
3928
4933
  gap: 0
3929
4934
  },
3930
4935
  children: [
3931
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ForkMarker, {}),
3932
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4936
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ForkMarker, {}),
4937
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3933
4938
  "div",
3934
4939
  {
3935
4940
  style: {
@@ -3943,7 +4948,7 @@ function ChainShell({ node, renderLeaf }) {
3943
4948
  paddingLeft: 12,
3944
4949
  paddingRight: 12
3945
4950
  },
3946
- children: node.branches.map((branch, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4951
+ children: node.branches.map((branch, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3947
4952
  "div",
3948
4953
  {
3949
4954
  style: {
@@ -3952,13 +4957,13 @@ function ChainShell({ node, renderLeaf }) {
3952
4957
  alignItems: "center",
3953
4958
  minWidth: 120
3954
4959
  },
3955
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChainShell, { node: branch, renderLeaf })
4960
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChainShell, { node: branch, renderLeaf })
3956
4961
  },
3957
4962
  chainKey(branch, i)
3958
4963
  ))
3959
4964
  }
3960
4965
  ),
3961
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ForkMarker, {})
4966
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ForkMarker, {})
3962
4967
  ]
3963
4968
  }
3964
4969
  );
@@ -3992,7 +4997,7 @@ function Leaf({
3992
4997
  const label = resolveLabel ? resolveLabel(leaf.stageId) : leaf.stageId;
3993
4998
  const commits = "commits" in leaf ? leaf.commits : [];
3994
4999
  if (commits.length === 0) {
3995
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5000
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3996
5001
  "div",
3997
5002
  {
3998
5003
  style: {
@@ -4003,17 +5008,17 @@ function Leaf({
4003
5008
  },
4004
5009
  title: `${leaf.stageId} \u2014 not executed in this run`,
4005
5010
  children: [
4006
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { fontWeight: 600 }, children: label }),
4007
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { fontSize: 10, fontStyle: "italic" }, children: "not executed" })
5011
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { fontWeight: 600 }, children: label }),
5012
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { fontSize: 10, fontStyle: "italic" }, children: "not executed" })
4008
5013
  ]
4009
5014
  }
4010
5015
  );
4011
5016
  }
4012
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }, children: commits.map((c, i) => {
5017
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }, children: commits.map((c, i) => {
4013
5018
  const isSelected = c.runtimeStageId === selectedRuntimeStageId;
4014
5019
  const clickable = onSelectCommit !== void 0;
4015
5020
  const isRevealed = revealedThroughCommitIdx === null || c.commitIdx <= revealedThroughCommitIdx;
4016
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5021
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4017
5022
  "button",
4018
5023
  {
4019
5024
  type: "button",
@@ -4034,16 +5039,16 @@ function Leaf({
4034
5039
  "aria-current": isSelected ? "true" : void 0,
4035
5040
  title: c.runtimeStageId,
4036
5041
  children: [
4037
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { fontWeight: 600 }, children: [
5042
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { fontWeight: 600 }, children: [
4038
5043
  label,
4039
- commits.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: { color: theme.textMuted, fontWeight: 400, marginLeft: 6 }, children: [
5044
+ commits.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { color: theme.textMuted, fontWeight: 400, marginLeft: 6 }, children: [
4040
5045
  "iter ",
4041
5046
  i + 1,
4042
5047
  "/",
4043
5048
  commits.length
4044
5049
  ] })
4045
5050
  ] }),
4046
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5051
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4047
5052
  "div",
4048
5053
  {
4049
5054
  style: {
@@ -4067,7 +5072,7 @@ function Leaf({
4067
5072
  }) });
4068
5073
  }
4069
5074
  function Connector({ orientation }) {
4070
- return orientation === "vertical" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5075
+ return orientation === "vertical" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4071
5076
  "div",
4072
5077
  {
4073
5078
  "aria-hidden": true,
@@ -4077,7 +5082,7 @@ function Connector({ orientation }) {
4077
5082
  background: theme.border
4078
5083
  }
4079
5084
  }
4080
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5085
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4081
5086
  "div",
4082
5087
  {
4083
5088
  "aria-hidden": true,
@@ -4090,7 +5095,7 @@ function Connector({ orientation }) {
4090
5095
  );
4091
5096
  }
4092
5097
  function ForkMarker() {
4093
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5098
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4094
5099
  "div",
4095
5100
  {
4096
5101
  "aria-hidden": true,
@@ -4116,11 +5121,11 @@ var boxBaseStyle = {
4116
5121
  };
4117
5122
 
4118
5123
  // src/components/FlowchartView/TraceExplorerShell.tsx
4119
- var import_react22 = require("react");
5124
+ var import_react27 = require("react");
4120
5125
 
4121
5126
  // src/components/FlowchartView/RunSlider.tsx
4122
- var import_react21 = require("react");
4123
- var import_jsx_runtime15 = require("react/jsx-runtime");
5127
+ var import_react26 = require("react");
5128
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4124
5129
  function RunSlider({
4125
5130
  index,
4126
5131
  cursorRuntimeStageId,
@@ -4130,12 +5135,12 @@ function RunSlider({
4130
5135
  style
4131
5136
  }) {
4132
5137
  const total = index.commits.length;
4133
- const cursorCommitIdx = (0, import_react21.useMemo)(() => {
5138
+ const cursorCommitIdx = (0, import_react26.useMemo)(() => {
4134
5139
  if (!cursorRuntimeStageId) return 0;
4135
5140
  const view = index.byRuntimeStageId.get(cursorRuntimeStageId);
4136
5141
  return view ? view.commitIdx : 0;
4137
5142
  }, [index, cursorRuntimeStageId]);
4138
- const handleSliderChange = (0, import_react21.useCallback)(
5143
+ const handleSliderChange = (0, import_react26.useCallback)(
4139
5144
  (e) => {
4140
5145
  const value = Number(e.target.value);
4141
5146
  const view = index.commits[value];
@@ -4143,7 +5148,7 @@ function RunSlider({
4143
5148
  },
4144
5149
  [index, onCursorChange]
4145
5150
  );
4146
- const label = (0, import_react21.useMemo)(() => {
5151
+ const label = (0, import_react26.useMemo)(() => {
4147
5152
  const commit = index.commits[cursorCommitIdx] ?? null;
4148
5153
  const rsid = cursorRuntimeStageId ?? commit?.runtimeStageId ?? null;
4149
5154
  if (renderLabel)
@@ -4154,8 +5159,8 @@ function RunSlider({
4154
5159
  commit,
4155
5160
  index
4156
5161
  });
4157
- if (total === 0) return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { color: theme.textMuted }, children: "No commits yet" });
4158
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: [
5162
+ if (total === 0) return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { color: theme.textMuted }, children: "No commits yet" });
5163
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { style: { fontFamily: "monospace", fontSize: 11, color: theme.textSecondary }, children: [
4159
5164
  "#",
4160
5165
  cursorCommitIdx + 1,
4161
5166
  " / ",
@@ -4165,7 +5170,7 @@ function RunSlider({
4165
5170
  ] });
4166
5171
  }, [renderLabel, cursorCommitIdx, total, index, cursorRuntimeStageId]);
4167
5172
  const disabled = total < 2;
4168
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5173
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4169
5174
  "div",
4170
5175
  {
4171
5176
  className,
@@ -4180,7 +5185,7 @@ function RunSlider({
4180
5185
  ...style
4181
5186
  },
4182
5187
  children: [
4183
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5188
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4184
5189
  "span",
4185
5190
  {
4186
5191
  style: {
@@ -4193,7 +5198,7 @@ function RunSlider({
4193
5198
  children: "Time"
4194
5199
  }
4195
5200
  ),
4196
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5201
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4197
5202
  "input",
4198
5203
  {
4199
5204
  type: "range",
@@ -4211,14 +5216,14 @@ function RunSlider({
4211
5216
  style: { flex: 1, accentColor: theme.success }
4212
5217
  }
4213
5218
  ),
4214
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { minWidth: 200, textAlign: "right" }, children: label })
5219
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { minWidth: 200, textAlign: "right" }, children: label })
4215
5220
  ]
4216
5221
  }
4217
5222
  );
4218
5223
  }
4219
5224
 
4220
5225
  // src/components/FlowchartView/TraceExplorerShell.tsx
4221
- var import_jsx_runtime16 = require("react/jsx-runtime");
5226
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4222
5227
  function TraceExplorerShell({
4223
5228
  bundle,
4224
5229
  selectedRuntimeStageId: controlledSel,
@@ -4227,39 +5232,39 @@ function TraceExplorerShell({
4227
5232
  className,
4228
5233
  style
4229
5234
  }) {
4230
- const [internalSel, setInternalSel] = (0, import_react22.useState)(null);
5235
+ const [internalSel, setInternalSel] = (0, import_react27.useState)(null);
4231
5236
  const isControlled = controlledSel !== void 0;
4232
5237
  const selectedRuntimeStageId = isControlled ? controlledSel : internalSel;
4233
- const handleSelect = (0, import_react22.useCallback)(
5238
+ const handleSelect = (0, import_react27.useCallback)(
4234
5239
  (rsid) => {
4235
5240
  if (!isControlled) setInternalSel(rsid);
4236
5241
  onSelectionChange?.(rsid);
4237
5242
  },
4238
5243
  [isControlled, onSelectionChange]
4239
5244
  );
4240
- const handleSelectCommit = (0, import_react22.useCallback)(
5245
+ const handleSelectCommit = (0, import_react27.useCallback)(
4241
5246
  (rsid) => handleSelect(rsid),
4242
5247
  [handleSelect]
4243
5248
  );
4244
- const selectedStageId = (0, import_react22.useMemo)(() => {
5249
+ const selectedStageId = (0, import_react27.useMemo)(() => {
4245
5250
  if (!selectedRuntimeStageId) return null;
4246
5251
  const hashIdx = selectedRuntimeStageId.lastIndexOf("#");
4247
5252
  if (hashIdx <= 0) return null;
4248
5253
  return asStageId(selectedRuntimeStageId.slice(0, hashIdx));
4249
5254
  }, [selectedRuntimeStageId]);
4250
- const ChainPane = (0, import_react22.useMemo)(
5255
+ const ChainPane = (0, import_react27.useMemo)(
4251
5256
  () => slots?.chain ?? DefaultChainPane,
4252
5257
  [slots?.chain]
4253
5258
  );
4254
- const CommitPane = (0, import_react22.useMemo)(
5259
+ const CommitPane = (0, import_react27.useMemo)(
4255
5260
  () => slots?.commitInspector ?? DefaultCommitPane,
4256
5261
  [slots?.commitInspector]
4257
5262
  );
4258
- const NodePane = (0, import_react22.useMemo)(
5263
+ const NodePane = (0, import_react27.useMemo)(
4259
5264
  () => slots?.nodeInspector ?? DefaultNodePane,
4260
5265
  [slots?.nodeInspector]
4261
5266
  );
4262
- const SliderPane = (0, import_react22.useMemo)(() => {
5267
+ const SliderPane = (0, import_react27.useMemo)(() => {
4263
5268
  if (slots && "slider" in slots) {
4264
5269
  return slots.slider ?? null;
4265
5270
  }
@@ -4274,7 +5279,7 @@ function TraceExplorerShell({
4274
5279
  () => bundle.commitFlow.getIndex()
4275
5280
  );
4276
5281
  const nodeIndex = useTranslator(bundle.nodeView, () => bundle.nodeView.getIndex());
4277
- const handleStageNavigate = (0, import_react22.useCallback)(
5282
+ const handleStageNavigate = (0, import_react27.useCallback)(
4278
5283
  (stageId) => {
4279
5284
  const candidates = commitIndex.commits.filter((c) => c.stageId === stageId);
4280
5285
  const first = candidates[0];
@@ -4282,17 +5287,17 @@ function TraceExplorerShell({
4282
5287
  },
4283
5288
  [commitIndex, handleSelect]
4284
5289
  );
4285
- const revealedThroughCommitIdx = (0, import_react22.useMemo)(() => {
5290
+ const revealedThroughCommitIdx = (0, import_react27.useMemo)(() => {
4286
5291
  if (!selectedRuntimeStageId) return null;
4287
5292
  const view = commitIndex.byRuntimeStageId.get(selectedRuntimeStageId);
4288
5293
  return view ? view.commitIdx : -1;
4289
5294
  }, [selectedRuntimeStageId, commitIndex]);
4290
- const layoutStyle = (0, import_react22.useMemo)(
5295
+ const layoutStyle = (0, import_react27.useMemo)(
4291
5296
  () => SliderPane ? SHELL_STYLE_WITH_SLIDER : SHELL_STYLE_NO_SLIDER,
4292
5297
  [SliderPane]
4293
5298
  );
4294
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, style: { ...layoutStyle, ...style }, children: [
4295
- SliderPane && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Pane, { area: "slider", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5299
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className, style: { ...layoutStyle, ...style }, children: [
5300
+ SliderPane && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pane, { area: "slider", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4296
5301
  SliderPane,
4297
5302
  {
4298
5303
  index: commitIndex,
@@ -4300,7 +5305,7 @@ function TraceExplorerShell({
4300
5305
  onCursorChange: handleSelect
4301
5306
  }
4302
5307
  ) }),
4303
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Pane, { area: "chain", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5308
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pane, { area: "chain", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4304
5309
  ChainPane,
4305
5310
  {
4306
5311
  chain,
@@ -4309,7 +5314,7 @@ function TraceExplorerShell({
4309
5314
  revealedThroughCommitIdx
4310
5315
  }
4311
5316
  ) }),
4312
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Pane, { area: "commit", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5317
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pane, { area: "commit", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4313
5318
  CommitPane,
4314
5319
  {
4315
5320
  index: commitIndex,
@@ -4317,7 +5322,7 @@ function TraceExplorerShell({
4317
5322
  onNavigate: handleSelectCommit
4318
5323
  }
4319
5324
  ) }),
4320
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Pane, { area: "node", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5325
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pane, { area: "node", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4321
5326
  NodePane,
4322
5327
  {
4323
5328
  index: nodeIndex,
@@ -4333,7 +5338,7 @@ function DefaultChainPane({
4333
5338
  onSelectCommit,
4334
5339
  revealedThroughCommitIdx
4335
5340
  }) {
4336
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5341
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4337
5342
  CommitChainView,
4338
5343
  {
4339
5344
  chain,
@@ -4348,7 +5353,7 @@ function DefaultCommitPane({
4348
5353
  selectedRuntimeStageId,
4349
5354
  onNavigate
4350
5355
  }) {
4351
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5356
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4352
5357
  CommitInspector,
4353
5358
  {
4354
5359
  index,
@@ -4358,14 +5363,14 @@ function DefaultCommitPane({
4358
5363
  );
4359
5364
  }
4360
5365
  function DefaultNodePane({ index, selectedStageId, onNavigate }) {
4361
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(NodeInspector, { index, selectedId: selectedStageId, onNavigate });
5366
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(NodeInspector, { index, selectedId: selectedStageId, onNavigate });
4362
5367
  }
4363
5368
  function DefaultSliderPane({
4364
5369
  index,
4365
5370
  cursorRuntimeStageId,
4366
5371
  onCursorChange
4367
5372
  }) {
4368
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5373
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4369
5374
  RunSlider,
4370
5375
  {
4371
5376
  index,
@@ -4403,14 +5408,20 @@ var PANE_BASE_STYLE = {
4403
5408
  // permit shrinking inside grid
4404
5409
  };
4405
5410
  function Pane({ area, children }) {
4406
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { role: "region", "aria-label": area, style: { ...PANE_BASE_STYLE, gridArea: area }, children });
5411
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "region", "aria-label": area, style: { ...PANE_BASE_STYLE, gridArea: area }, children });
4407
5412
  }
4408
5413
  // Annotate the CommonJS export names for ESM import in node:
4409
5414
  0 && (module.exports = {
4410
5415
  CommitChainView,
4411
5416
  CommitInspector,
5417
+ GROUP_CONTAINER_NODE_TYPE,
5418
+ GroupContainerNode,
5419
+ LoopBackEdge,
5420
+ MAIN_CHART_BOX_ID,
4412
5421
  NodeInspector,
4413
5422
  RunSlider,
5423
+ SlotPillNode,
5424
+ SmartStepEdge,
4414
5425
  StageNode,
4415
5426
  SubflowBreadcrumb,
4416
5427
  SubflowTree,
@@ -4418,23 +5429,35 @@ function Pane({ area, children }) {
4418
5429
  TraceExplorerShell,
4419
5430
  TraceFlow,
4420
5431
  TracedFlow,
5432
+ applyGroupLayout,
4421
5433
  asRuntimeStageId,
4422
5434
  asStageId,
4423
5435
  backtraceDataFlow,
4424
5436
  backtraceStructural,
4425
5437
  buildCommitChainTree,
5438
+ buildSubflowBreadcrumb,
4426
5439
  createCommitFlowRecorder,
5440
+ createDagreTraceLayout,
5441
+ createGroupedLayout,
5442
+ createMainChartBoxLayout,
4427
5443
  createNodeViewRecorder,
5444
+ createSnappedDagreLayout,
4428
5445
  createTraceBundle,
5446
+ createTraceGroupLayout,
4429
5447
  createTraceRuntimeOverlay,
4430
5448
  createTraceStructureRecorder,
5449
+ dagreTraceLayout,
4431
5450
  defaultTraceFlowLayout,
5451
+ filterGraphForDrill,
4432
5452
  forwardtraceStructural,
4433
5453
  sliceOverlay,
5454
+ snapLinearSuccessors,
4434
5455
  structureAsChainTree,
5456
+ traceGroupLayout,
4435
5457
  useSubflowNavigation,
4436
5458
  useTranslator,
4437
5459
  walkBackward,
4438
- walkForward
5460
+ walkForward,
5461
+ wrapInMainChartBox
4439
5462
  });
4440
5463
  //# sourceMappingURL=flowchart.cjs.map