footprint-explainable-ui 0.18.0 → 0.19.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.
- package/dist/adapters/fromRuntimeSnapshot.d.ts +33 -4
- package/dist/adapters/fromRuntimeSnapshot.d.ts.map +1 -1
- package/dist/adapters/fromRuntimeSnapshot.js +162 -33
- package/dist/adapters/fromRuntimeSnapshot.js.map +1 -1
- package/dist/components/ExplainableShell/ExplainableShell.d.ts +157 -14
- package/dist/components/ExplainableShell/ExplainableShell.d.ts.map +1 -1
- package/dist/components/ExplainableShell/ExplainableShell.js +676 -68
- package/dist/components/ExplainableShell/ExplainableShell.js.map +1 -1
- package/dist/components/ExplainableShell/index.d.ts +1 -1
- package/dist/components/ExplainableShell/index.d.ts.map +1 -1
- package/dist/components/FlowchartView/SubflowTree.d.ts +7 -14
- package/dist/components/FlowchartView/SubflowTree.d.ts.map +1 -1
- package/dist/components/FlowchartView/SubflowTree.js +56 -46
- package/dist/components/FlowchartView/SubflowTree.js.map +1 -1
- package/dist/components/FlowchartView/index.d.ts +32 -4
- package/dist/components/FlowchartView/index.d.ts.map +1 -1
- package/dist/components/FlowchartView/index.js +22 -2
- package/dist/components/FlowchartView/index.js.map +1 -1
- package/dist/components/FlowchartView/useSubflowNavigation.d.ts +41 -16
- package/dist/components/FlowchartView/useSubflowNavigation.d.ts.map +1 -1
- package/dist/components/FlowchartView/useSubflowNavigation.js +69 -50
- package/dist/components/FlowchartView/useSubflowNavigation.js.map +1 -1
- package/dist/components/GanttTimeline/GanttTimeline.d.ts.map +1 -1
- package/dist/components/GanttTimeline/GanttTimeline.js +5 -5
- package/dist/components/GanttTimeline/GanttTimeline.js.map +1 -1
- package/dist/components/MemoryInspector/MemoryInspector.d.ts.map +1 -1
- package/dist/components/MemoryInspector/MemoryInspector.js +36 -13
- package/dist/components/MemoryInspector/MemoryInspector.js.map +1 -1
- package/dist/components/NarrativeTrace/NarrativeTrace.d.ts.map +1 -1
- package/dist/components/NarrativeTrace/NarrativeTrace.js +24 -17
- package/dist/components/NarrativeTrace/NarrativeTrace.js.map +1 -1
- package/dist/components/ScopeDiff/ScopeDiff.js +3 -3
- package/dist/components/ScopeDiff/ScopeDiff.js.map +1 -1
- package/dist/components/StageNode/StageNode.d.ts +21 -0
- package/dist/components/StageNode/StageNode.d.ts.map +1 -1
- package/dist/components/StageNode/StageNode.js +189 -9
- package/dist/components/StageNode/StageNode.js.map +1 -1
- package/dist/components/TimeTravelControls/TimeTravelControls.d.ts.map +1 -1
- package/dist/components/TimeTravelControls/TimeTravelControls.js +19 -3
- package/dist/components/TimeTravelControls/TimeTravelControls.js.map +1 -1
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts +19 -8
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts.map +1 -1
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js +23 -8
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js.map +1 -1
- package/dist/flowchart.cjs +3485 -1340
- package/dist/flowchart.cjs.map +1 -1
- package/dist/flowchart.d.cts +1616 -177
- package/dist/flowchart.d.ts +1616 -177
- package/dist/flowchart.d.ts.map +1 -1
- package/dist/flowchart.js +3507 -1384
- package/dist/flowchart.js.map +1 -1
- package/dist/index.cjs +749 -557
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +276 -29
- package/dist/index.d.ts +276 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +742 -547
- package/dist/index.js.map +1 -1
- package/dist/theme/ThemeProvider.d.ts +14 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -1
- package/dist/theme/ThemeProvider.js +15 -1
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/index.d.ts +4 -2
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +3 -2
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/presets.d.ts +3 -0
- package/dist/theme/presets.d.ts.map +1 -1
- package/dist/theme/presets.js +22 -0
- package/dist/theme/presets.js.map +1 -1
- package/dist/theme/tokens.d.ts +22 -1
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +23 -2
- package/dist/theme/tokens.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/components/FlowchartView/FlowchartView.d.ts +0 -20
- package/dist/components/FlowchartView/FlowchartView.d.ts.map +0 -1
- package/dist/components/FlowchartView/FlowchartView.js +0 -80
- package/dist/components/FlowchartView/FlowchartView.js.map +0 -1
- package/dist/components/FlowchartView/TracedFlowchartView.d.ts +0 -20
- package/dist/components/FlowchartView/TracedFlowchartView.d.ts.map +0 -1
- package/dist/components/FlowchartView/TracedFlowchartView.js +0 -101
- package/dist/components/FlowchartView/TracedFlowchartView.js.map +0 -1
- package/dist/components/FlowchartView/specToReactFlow.d.ts +0 -56
- package/dist/components/FlowchartView/specToReactFlow.d.ts.map +0 -1
- package/dist/components/FlowchartView/specToReactFlow.js +0 -202
- package/dist/components/FlowchartView/specToReactFlow.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -143,7 +143,14 @@ function useFootprintTheme() {
|
|
|
143
143
|
}
|
|
144
144
|
function FootprintTheme({ tokens = {}, children }) {
|
|
145
145
|
const cssVars = tokensToCSSVars(tokens);
|
|
146
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: tokens, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: tokens, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
147
|
+
"div",
|
|
148
|
+
{
|
|
149
|
+
style: { ...cssVars, display: "contents" },
|
|
150
|
+
className: "fp-theme-root",
|
|
151
|
+
children
|
|
152
|
+
}
|
|
153
|
+
) });
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
// src/theme/styles.ts
|
|
@@ -2272,7 +2279,7 @@ function TimeTravelControls({
|
|
|
2272
2279
|
}
|
|
2273
2280
|
|
|
2274
2281
|
// src/components/ExplainableShell/ExplainableShell.tsx
|
|
2275
|
-
var
|
|
2282
|
+
var import_react27 = require("react");
|
|
2276
2283
|
|
|
2277
2284
|
// src/utils/narrativeSync.ts
|
|
2278
2285
|
function buildEntryRangeIndex(entries) {
|
|
@@ -2774,7 +2781,6 @@ function NarrativePanel({
|
|
|
2774
2781
|
snapshots,
|
|
2775
2782
|
selectedIndex,
|
|
2776
2783
|
narrativeEntries,
|
|
2777
|
-
narrative: narrativeProp,
|
|
2778
2784
|
runtimeSnapshot,
|
|
2779
2785
|
spec,
|
|
2780
2786
|
size = "default",
|
|
@@ -2785,14 +2791,13 @@ function NarrativePanel({
|
|
|
2785
2791
|
const fs = fontSize[size];
|
|
2786
2792
|
const pad = padding[size];
|
|
2787
2793
|
const narrative = (0, import_react12.useMemo)(() => {
|
|
2788
|
-
if (narrativeProp && narrativeProp.length > 0) return narrativeProp;
|
|
2789
2794
|
const lines = [];
|
|
2790
2795
|
for (const snap of snapshots) {
|
|
2791
2796
|
const stageLines = (snap.narrative ?? "").split("\n").filter(Boolean);
|
|
2792
2797
|
lines.push(...stageLines);
|
|
2793
2798
|
}
|
|
2794
2799
|
return lines;
|
|
2795
|
-
}, [
|
|
2800
|
+
}, [snapshots]);
|
|
2796
2801
|
const revealedCount = (0, import_react12.useMemo)(() => {
|
|
2797
2802
|
if (snapshots.length === 0 || narrative.length === 0) return narrative.length;
|
|
2798
2803
|
const stageBoundaries = [];
|
|
@@ -3016,35 +3021,19 @@ function NarrativePanel({
|
|
|
3016
3021
|
// src/components/FlowchartView/SubflowTree.tsx
|
|
3017
3022
|
var import_react13 = require("react");
|
|
3018
3023
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3019
|
-
function
|
|
3020
|
-
if (!
|
|
3024
|
+
function graphToSubflowEntries(graph) {
|
|
3025
|
+
if (!graph?.nodes?.length) return [];
|
|
3021
3026
|
const entries = [];
|
|
3022
|
-
const
|
|
3023
|
-
|
|
3024
|
-
if (!n) return;
|
|
3025
|
-
const id = n.name || n.id || "";
|
|
3026
|
-
if (seen.has(id)) return;
|
|
3027
|
-
seen.add(id);
|
|
3027
|
+
for (const node of graph.nodes) {
|
|
3028
|
+
if (!node.data?.isSubflow) continue;
|
|
3028
3029
|
const entry = {
|
|
3029
|
-
name:
|
|
3030
|
-
|
|
3031
|
-
subflowId: n.subflowId,
|
|
3032
|
-
isSubflow: !!n.isSubflowRoot
|
|
3030
|
+
name: typeof node.data.label === "string" ? node.data.label : node.id,
|
|
3031
|
+
isSubflow: true
|
|
3033
3032
|
};
|
|
3034
|
-
if (
|
|
3035
|
-
|
|
3036
|
-
}
|
|
3033
|
+
if (typeof node.data.description === "string") entry.description = node.data.description;
|
|
3034
|
+
if (typeof node.data.subflowId === "string") entry.subflowId = node.data.subflowId;
|
|
3037
3035
|
entries.push(entry);
|
|
3038
|
-
if (n.children) {
|
|
3039
|
-
for (const child of n.children) {
|
|
3040
|
-
if (child) walk(child);
|
|
3041
|
-
}
|
|
3042
|
-
}
|
|
3043
|
-
if (n.next) {
|
|
3044
|
-
walk(n.next);
|
|
3045
|
-
}
|
|
3046
3036
|
}
|
|
3047
|
-
walk(node);
|
|
3048
3037
|
return entries;
|
|
3049
3038
|
}
|
|
3050
3039
|
var TreeNode = (0, import_react13.memo)(function TreeNode2({
|
|
@@ -3188,7 +3177,7 @@ var SectionLabel = (0, import_react13.memo)(function SectionLabel2({ children })
|
|
|
3188
3177
|
);
|
|
3189
3178
|
});
|
|
3190
3179
|
var SubflowTree = (0, import_react13.memo)(function SubflowTree2({
|
|
3191
|
-
|
|
3180
|
+
graph,
|
|
3192
3181
|
activeStage,
|
|
3193
3182
|
doneStages,
|
|
3194
3183
|
onNodeSelect,
|
|
@@ -3196,8 +3185,7 @@ var SubflowTree = (0, import_react13.memo)(function SubflowTree2({
|
|
|
3196
3185
|
className,
|
|
3197
3186
|
style
|
|
3198
3187
|
}) {
|
|
3199
|
-
const
|
|
3200
|
-
const subflowStages = (0, import_react13.useMemo)(() => tree.filter((e) => e.isSubflow), [tree]);
|
|
3188
|
+
const subflowStages = (0, import_react13.useMemo)(() => graphToSubflowEntries(graph), [graph]);
|
|
3201
3189
|
if (subflowStages.length === 0) return null;
|
|
3202
3190
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
3203
3191
|
"div",
|
|
@@ -3317,9 +3305,13 @@ var SubflowBreadcrumb = (0, import_react14.memo)(function SubflowBreadcrumb2({
|
|
|
3317
3305
|
);
|
|
3318
3306
|
});
|
|
3319
3307
|
|
|
3320
|
-
// src/components/FlowchartView/
|
|
3321
|
-
var
|
|
3322
|
-
var
|
|
3308
|
+
// src/components/FlowchartView/TracedFlow.tsx
|
|
3309
|
+
var import_react21 = require("react");
|
|
3310
|
+
var import_react22 = require("@xyflow/react");
|
|
3311
|
+
|
|
3312
|
+
// src/components/FlowchartView/TraceFlow.tsx
|
|
3313
|
+
var import_react17 = require("react");
|
|
3314
|
+
var import_react18 = require("@xyflow/react");
|
|
3323
3315
|
|
|
3324
3316
|
// src/components/StageNode/StageNode.tsx
|
|
3325
3317
|
var import_react15 = require("react");
|
|
@@ -3474,7 +3466,7 @@ function StageIcon({ type, color }) {
|
|
|
3474
3466
|
var StageNode = (0, import_react15.memo)(function StageNode2({
|
|
3475
3467
|
data
|
|
3476
3468
|
}) {
|
|
3477
|
-
const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description } = data;
|
|
3469
|
+
const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description, stageId, showStageId } = data;
|
|
3478
3470
|
const effectiveIcon = icon || (isLazy ? "lazy" : void 0);
|
|
3479
3471
|
const isLazyUnresolved = isLazy && !done && !active;
|
|
3480
3472
|
const injectedRef = (0, import_react15.useRef)(false);
|
|
@@ -3648,6 +3640,23 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
|
|
|
3648
3640
|
},
|
|
3649
3641
|
children: description
|
|
3650
3642
|
}
|
|
3643
|
+
),
|
|
3644
|
+
showStageId && stageId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3645
|
+
"span",
|
|
3646
|
+
{
|
|
3647
|
+
style: {
|
|
3648
|
+
fontSize: 8,
|
|
3649
|
+
fontFamily: "ui-monospace, monospace",
|
|
3650
|
+
color: textColor,
|
|
3651
|
+
opacity: 0.55,
|
|
3652
|
+
whiteSpace: "nowrap",
|
|
3653
|
+
overflow: "hidden",
|
|
3654
|
+
textOverflow: "ellipsis",
|
|
3655
|
+
maxWidth: 100
|
|
3656
|
+
},
|
|
3657
|
+
title: `stageId: ${stageId}`,
|
|
3658
|
+
children: stageId
|
|
3659
|
+
}
|
|
3651
3660
|
)
|
|
3652
3661
|
]
|
|
3653
3662
|
}
|
|
@@ -3746,6 +3755,23 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
|
|
|
3746
3755
|
},
|
|
3747
3756
|
children: description
|
|
3748
3757
|
}
|
|
3758
|
+
),
|
|
3759
|
+
showStageId && stageId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3760
|
+
"span",
|
|
3761
|
+
{
|
|
3762
|
+
style: {
|
|
3763
|
+
fontSize: 9,
|
|
3764
|
+
fontFamily: "ui-monospace, monospace",
|
|
3765
|
+
color: textColor,
|
|
3766
|
+
opacity: 0.55,
|
|
3767
|
+
whiteSpace: "nowrap",
|
|
3768
|
+
overflow: "hidden",
|
|
3769
|
+
textOverflow: "ellipsis",
|
|
3770
|
+
maxWidth: 160
|
|
3771
|
+
},
|
|
3772
|
+
title: `stageId: ${stageId}`,
|
|
3773
|
+
children: stageId
|
|
3774
|
+
}
|
|
3749
3775
|
)
|
|
3750
3776
|
]
|
|
3751
3777
|
}
|
|
@@ -3776,335 +3802,497 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
|
|
|
3776
3802
|
] });
|
|
3777
3803
|
});
|
|
3778
3804
|
|
|
3779
|
-
// src/components/FlowchartView/
|
|
3780
|
-
var
|
|
3781
|
-
var DEFAULT_COLORS = {
|
|
3782
|
-
edgeDefault: rawDefaults.colors.textMuted,
|
|
3783
|
-
edgeExecuted: rawDefaults.colors.success,
|
|
3784
|
-
edgeActive: rawDefaults.colors.primary,
|
|
3785
|
-
edgeLoop: rawDefaults.colors.warning,
|
|
3786
|
-
labelDefault: rawDefaults.colors.textSecondary,
|
|
3787
|
-
labelExecuted: rawDefaults.colors.success,
|
|
3788
|
-
labelLoop: rawDefaults.colors.warning,
|
|
3789
|
-
pathGlow: `${rawDefaults.colors.success}4D`
|
|
3790
|
-
// ~30% opacity hex
|
|
3791
|
-
};
|
|
3805
|
+
// src/components/FlowchartView/TraceFlow.tsx
|
|
3806
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3792
3807
|
var Y_STEP = 100;
|
|
3793
3808
|
var X_SPREAD = 200;
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
const isFork = node.type === "fork";
|
|
3812
|
-
state.nodes.push({
|
|
3813
|
-
id,
|
|
3814
|
-
x,
|
|
3815
|
-
y,
|
|
3816
|
-
label: node.name,
|
|
3817
|
-
isDecider,
|
|
3818
|
-
isFork,
|
|
3819
|
-
description: node.description,
|
|
3820
|
-
icon: node.icon,
|
|
3821
|
-
subflowId: node.subflowId,
|
|
3822
|
-
isSubflow: !!node.isSubflowRoot,
|
|
3823
|
-
isLazy: node.isLazy
|
|
3824
|
-
});
|
|
3825
|
-
let lastIds = [id];
|
|
3826
|
-
let bottomY = y;
|
|
3827
|
-
if (node.children && node.children.length > 0) {
|
|
3828
|
-
const totalWidth = (node.children.length - 1) * X_SPREAD;
|
|
3829
|
-
const startX = x - totalWidth / 2;
|
|
3830
|
-
const childY = y + Y_STEP;
|
|
3831
|
-
const childResults = [];
|
|
3832
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
3833
|
-
const child = node.children[i];
|
|
3834
|
-
if (!child) continue;
|
|
3835
|
-
const childX = startX + i * X_SPREAD;
|
|
3836
|
-
const edgeLabel = node.branchIds?.[i];
|
|
3837
|
-
state.edgeCounter++;
|
|
3838
|
-
state.edges.push({ id: `se${state.edgeCounter}`, source: id, target: nid(child), label: edgeLabel, isLoop: false });
|
|
3839
|
-
const result = walkLayout(child, state, childX, childY);
|
|
3840
|
-
childResults.push(result);
|
|
3809
|
+
var defaultTraceFlowLayout = (graph) => {
|
|
3810
|
+
if (graph.nodes.length === 0) return { nodes: [], edges: graph.edges };
|
|
3811
|
+
const branchChildrenOf = /* @__PURE__ */ new Map();
|
|
3812
|
+
const nextChildrenOf = /* @__PURE__ */ new Map();
|
|
3813
|
+
const hasIncomingForward = /* @__PURE__ */ new Set();
|
|
3814
|
+
for (const e of graph.edges) {
|
|
3815
|
+
const kind = e.data?.kind;
|
|
3816
|
+
if (kind === "loop") continue;
|
|
3817
|
+
hasIncomingForward.add(e.target);
|
|
3818
|
+
if (kind === "fork-branch" || kind === "decision-branch") {
|
|
3819
|
+
const arr = branchChildrenOf.get(e.source) ?? [];
|
|
3820
|
+
arr.push(e.target);
|
|
3821
|
+
branchChildrenOf.set(e.source, arr);
|
|
3822
|
+
} else {
|
|
3823
|
+
const arr = nextChildrenOf.get(e.source) ?? [];
|
|
3824
|
+
arr.push(e.target);
|
|
3825
|
+
nextChildrenOf.set(e.source, arr);
|
|
3841
3826
|
}
|
|
3842
|
-
lastIds = childResults.flatMap((r) => r.lastIds);
|
|
3843
|
-
bottomY = Math.max(...childResults.map((r) => r.bottomY));
|
|
3844
|
-
}
|
|
3845
|
-
if (node.loopTarget) {
|
|
3846
|
-
state.edgeCounter++;
|
|
3847
|
-
state.edges.push({ id: `se${state.edgeCounter}`, source: id, target: node.loopTarget, label: "loop", isLoop: true });
|
|
3848
3827
|
}
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3828
|
+
const seed = graph.nodes.find((n) => !hasIncomingForward.has(n.id)) ?? graph.nodes[0];
|
|
3829
|
+
const positions = /* @__PURE__ */ new Map();
|
|
3830
|
+
function layoutSubtree(nodeId, x, y) {
|
|
3831
|
+
if (positions.has(nodeId)) {
|
|
3832
|
+
return positions.get(nodeId).y;
|
|
3833
|
+
}
|
|
3834
|
+
positions.set(nodeId, { x, y });
|
|
3835
|
+
let deepestBranchY = y;
|
|
3836
|
+
const branches = branchChildrenOf.get(nodeId) ?? [];
|
|
3837
|
+
if (branches.length > 0) {
|
|
3838
|
+
const childY = y + Y_STEP;
|
|
3839
|
+
const totalWidth = (branches.length - 1) * X_SPREAD;
|
|
3840
|
+
const startX = x - totalWidth / 2;
|
|
3841
|
+
for (let i = 0; i < branches.length; i++) {
|
|
3842
|
+
const childId = branches[i];
|
|
3843
|
+
const childX = startX + i * X_SPREAD;
|
|
3844
|
+
const subtreeBottom = layoutSubtree(childId, childX, childY);
|
|
3845
|
+
if (subtreeBottom > deepestBranchY) deepestBranchY = subtreeBottom;
|
|
3857
3846
|
}
|
|
3858
|
-
return { lastIds, bottomY };
|
|
3859
3847
|
}
|
|
3860
|
-
const
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3848
|
+
const nextChildren = nextChildrenOf.get(nodeId) ?? [];
|
|
3849
|
+
if (nextChildren.length > 0) {
|
|
3850
|
+
const nextY = branches.length > 0 ? deepestBranchY + Y_STEP : y + Y_STEP;
|
|
3851
|
+
const totalWidth = (nextChildren.length - 1) * X_SPREAD;
|
|
3852
|
+
const startX = x - totalWidth / 2;
|
|
3853
|
+
let deepestNextY = nextY;
|
|
3854
|
+
for (let i = 0; i < nextChildren.length; i++) {
|
|
3855
|
+
const childId = nextChildren[i];
|
|
3856
|
+
const childX = startX + i * X_SPREAD;
|
|
3857
|
+
const subtreeBottom = layoutSubtree(childId, childX, nextY);
|
|
3858
|
+
if (subtreeBottom > deepestNextY) deepestNextY = subtreeBottom;
|
|
3859
|
+
}
|
|
3860
|
+
return deepestNextY;
|
|
3861
|
+
}
|
|
3862
|
+
return deepestBranchY;
|
|
3863
|
+
}
|
|
3864
|
+
layoutSubtree(seed.id, 0, 0);
|
|
3865
|
+
let maxY = 0;
|
|
3866
|
+
for (const p of positions.values()) {
|
|
3867
|
+
if (p.y > maxY) maxY = p.y;
|
|
3868
|
+
}
|
|
3869
|
+
let orphanY = maxY + Y_STEP;
|
|
3870
|
+
for (const n of graph.nodes) {
|
|
3871
|
+
if (!positions.has(n.id)) {
|
|
3872
|
+
positions.set(n.id, { x: 0, y: orphanY });
|
|
3873
|
+
orphanY += Y_STEP;
|
|
3864
3874
|
}
|
|
3865
|
-
return walkLayout(node.next, state, x, nextY);
|
|
3866
3875
|
}
|
|
3867
|
-
return {
|
|
3876
|
+
return {
|
|
3877
|
+
nodes: graph.nodes.map((n) => ({
|
|
3878
|
+
...n,
|
|
3879
|
+
position: positions.get(n.id) ?? n.position
|
|
3880
|
+
})),
|
|
3881
|
+
edges: graph.edges
|
|
3882
|
+
};
|
|
3883
|
+
};
|
|
3884
|
+
var DEFAULT_EDGE_COLORS = {
|
|
3885
|
+
next: rawDefaults.colors.textMuted,
|
|
3886
|
+
forkBranch: rawDefaults.colors.textMuted,
|
|
3887
|
+
decisionBranch: rawDefaults.colors.primary,
|
|
3888
|
+
loop: rawDefaults.colors.warning
|
|
3889
|
+
};
|
|
3890
|
+
|
|
3891
|
+
// src/components/FlowchartView/createTraceRuntimeOverlay.ts
|
|
3892
|
+
function sliceOverlay(overlay, index) {
|
|
3893
|
+
const order = overlay.executionOrder;
|
|
3894
|
+
if (order.length === 0) {
|
|
3895
|
+
return {
|
|
3896
|
+
doneStageIds: /* @__PURE__ */ new Set(),
|
|
3897
|
+
activeStageId: null,
|
|
3898
|
+
executedStageIds: /* @__PURE__ */ new Set(),
|
|
3899
|
+
executedOrderIds: [],
|
|
3900
|
+
errors: overlay.errors
|
|
3901
|
+
};
|
|
3902
|
+
}
|
|
3903
|
+
const clampedIndex = Math.max(0, Math.min(index, order.length - 1));
|
|
3904
|
+
const doneStageIds = /* @__PURE__ */ new Set();
|
|
3905
|
+
for (let i = 0; i < clampedIndex; i++) {
|
|
3906
|
+
doneStageIds.add(order[i].stageId);
|
|
3907
|
+
}
|
|
3908
|
+
const activeStep = order[clampedIndex];
|
|
3909
|
+
const activeStageId = activeStep ? activeStep.stageId : null;
|
|
3910
|
+
const executedStageIds = new Set(doneStageIds);
|
|
3911
|
+
if (activeStageId) executedStageIds.add(activeStageId);
|
|
3912
|
+
const executedOrderIds = order.slice(0, clampedIndex + 1).map((s) => s.stageId);
|
|
3913
|
+
return {
|
|
3914
|
+
doneStageIds,
|
|
3915
|
+
activeStageId,
|
|
3916
|
+
executedStageIds,
|
|
3917
|
+
executedOrderIds,
|
|
3918
|
+
errors: overlay.errors
|
|
3919
|
+
};
|
|
3868
3920
|
}
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3921
|
+
|
|
3922
|
+
// src/components/FlowchartView/_internal/subflowDrill.ts
|
|
3923
|
+
function filterGraphForDrill(graph, currentSubflowId) {
|
|
3924
|
+
if (graph.nodes.length === 0) return graph;
|
|
3925
|
+
const matchesScope = (subflowOf) => currentSubflowId === null ? subflowOf === void 0 : subflowOf === currentSubflowId;
|
|
3926
|
+
const visibleIds = /* @__PURE__ */ new Set();
|
|
3927
|
+
for (const n of graph.nodes) {
|
|
3928
|
+
if (matchesScope(n.data?.subflowOf)) visibleIds.add(n.id);
|
|
3929
|
+
}
|
|
3930
|
+
if (visibleIds.size === graph.nodes.length) return graph;
|
|
3931
|
+
return {
|
|
3932
|
+
nodes: graph.nodes.filter((n) => visibleIds.has(n.id)),
|
|
3933
|
+
edges: graph.edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target))
|
|
3876
3934
|
};
|
|
3877
|
-
walkLayout(spec, state, 300, 0);
|
|
3878
|
-
return { nodes: state.nodes, edges: state.edges, idToName: state.idToName };
|
|
3879
3935
|
}
|
|
3880
|
-
function
|
|
3881
|
-
const
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3936
|
+
function buildSubflowBreadcrumb(graph, currentSubflowId) {
|
|
3937
|
+
const out = [{ subflowId: null, label: "Chart" }];
|
|
3938
|
+
if (currentSubflowId !== null) {
|
|
3939
|
+
const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);
|
|
3940
|
+
out.push({
|
|
3941
|
+
subflowId: currentSubflowId,
|
|
3942
|
+
label: mount?.data?.label ?? currentSubflowId
|
|
3943
|
+
});
|
|
3944
|
+
}
|
|
3945
|
+
return out;
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
// src/components/FlowchartView/_internal/overlayProjection.ts
|
|
3949
|
+
function leafId(id) {
|
|
3950
|
+
const i = id.lastIndexOf("/");
|
|
3951
|
+
return i >= 0 ? id.slice(i + 1) : id;
|
|
3952
|
+
}
|
|
3953
|
+
function normalizeSliceLeafIds(slice) {
|
|
3954
|
+
return {
|
|
3955
|
+
doneStageIds: new Set(Array.from(slice.doneStageIds).map(leafId)),
|
|
3956
|
+
activeStageId: slice.activeStageId ? leafId(slice.activeStageId) : null,
|
|
3957
|
+
executedStageIds: new Set(Array.from(slice.executedStageIds).map(leafId)),
|
|
3958
|
+
executedOrderIds: slice.executedOrderIds.map(leafId),
|
|
3959
|
+
errors: new Map(Array.from(slice.errors).map(([k, v2]) => [leafId(k), v2]))
|
|
3960
|
+
};
|
|
3961
|
+
}
|
|
3962
|
+
function aggregateMountStatus(slice, graph, currentSubflowId) {
|
|
3963
|
+
if (graph.nodes.length === 0) return slice;
|
|
3964
|
+
const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);
|
|
3965
|
+
if (mounts.length === 0) return slice;
|
|
3966
|
+
const doneIds = new Set(slice.doneStageIds);
|
|
3967
|
+
let activeId = slice.activeStageId;
|
|
3968
|
+
for (const mount of mounts) {
|
|
3969
|
+
const sfId = mount.data.subflowId;
|
|
3970
|
+
const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);
|
|
3971
|
+
if (members.length === 0) continue;
|
|
3972
|
+
const anyActive = members.some((m) => m.id === slice.activeStageId);
|
|
3973
|
+
const anyDone = members.some((m) => slice.doneStageIds.has(m.id));
|
|
3974
|
+
const allDone = members.every((m) => slice.doneStageIds.has(m.id));
|
|
3975
|
+
if (allDone) doneIds.add(mount.id);
|
|
3976
|
+
else if ((anyActive || anyDone) && currentSubflowId === null) {
|
|
3977
|
+
activeId = mount.id;
|
|
3895
3978
|
}
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
dimmed,
|
|
3910
|
-
stepNumbers,
|
|
3911
|
-
isSubflow: ln.isSubflow,
|
|
3912
|
-
isLazy: ln.isLazy
|
|
3913
|
-
},
|
|
3914
|
-
type: "stage",
|
|
3915
|
-
style: dimmed ? { opacity: 0.35 } : void 0
|
|
3916
|
-
};
|
|
3917
|
-
});
|
|
3918
|
-
const edges = [];
|
|
3919
|
-
for (const le of layout.edges) {
|
|
3920
|
-
const executed = o && o.executedStages.has(le.source) && o.executedStages.has(le.target);
|
|
3921
|
-
const isLeadingEdge = o && le.source === o.activeStage && !o.doneStages.has(le.target);
|
|
3922
|
-
if (le.isLoop) {
|
|
3923
|
-
let loopExecuted = false;
|
|
3924
|
-
if (o?.executionOrder) {
|
|
3925
|
-
if (le.source === le.target) {
|
|
3926
|
-
const count = o.executionOrder.filter((id) => id === le.source).length;
|
|
3927
|
-
loopExecuted = count > 1;
|
|
3928
|
-
} else {
|
|
3929
|
-
const lastSourceIdx = o.executionOrder.lastIndexOf(le.source);
|
|
3930
|
-
if (lastSourceIdx >= 0) {
|
|
3931
|
-
loopExecuted = o.executionOrder.slice(lastSourceIdx + 1).includes(le.target);
|
|
3932
|
-
}
|
|
3933
|
-
}
|
|
3934
|
-
}
|
|
3935
|
-
edges.push({
|
|
3936
|
-
id: le.id,
|
|
3937
|
-
source: le.source,
|
|
3938
|
-
target: le.target,
|
|
3939
|
-
sourceHandle: "loop-source",
|
|
3940
|
-
targetHandle: "loop-target",
|
|
3941
|
-
label: le.label ?? "loop",
|
|
3942
|
-
type: "smoothstep",
|
|
3943
|
-
pathOptions: { offset: 60, borderRadius: 20 },
|
|
3944
|
-
markerEnd: { type: import_react17.MarkerType.ArrowClosed, color: loopExecuted ? c.edgeActive : c.edgeLoop, width: 16, height: 16 },
|
|
3945
|
-
style: {
|
|
3946
|
-
stroke: loopExecuted ? c.edgeActive : c.edgeLoop,
|
|
3947
|
-
strokeWidth: loopExecuted ? 4 : 2,
|
|
3948
|
-
strokeDasharray: loopExecuted ? void 0 : "6 3",
|
|
3949
|
-
opacity: o && !loopExecuted ? 0.35 : 1
|
|
3950
|
-
},
|
|
3951
|
-
labelStyle: { fontSize: 10, fontWeight: 700, fill: loopExecuted ? c.edgeActive : c.labelLoop },
|
|
3952
|
-
animated: loopExecuted,
|
|
3953
|
-
zIndex: 2
|
|
3954
|
-
});
|
|
3955
|
-
} else if (executed) {
|
|
3956
|
-
edges.push({
|
|
3957
|
-
id: `${le.id}-glow`,
|
|
3958
|
-
source: le.source,
|
|
3959
|
-
target: le.target,
|
|
3960
|
-
style: { stroke: c.pathGlow, strokeWidth: 8, opacity: 0.4 },
|
|
3961
|
-
zIndex: 0,
|
|
3962
|
-
selectable: false,
|
|
3963
|
-
focusable: false
|
|
3964
|
-
});
|
|
3965
|
-
edges.push({
|
|
3966
|
-
id: le.id,
|
|
3967
|
-
source: le.source,
|
|
3968
|
-
target: le.target,
|
|
3969
|
-
label: le.label,
|
|
3970
|
-
style: {
|
|
3971
|
-
stroke: isLeadingEdge ? c.edgeActive : c.edgeExecuted,
|
|
3972
|
-
strokeWidth: 3.5
|
|
3973
|
-
},
|
|
3974
|
-
labelStyle: { fontSize: 10, fontWeight: 600, fill: c.labelExecuted },
|
|
3975
|
-
animated: !!isLeadingEdge,
|
|
3976
|
-
zIndex: 1
|
|
3977
|
-
});
|
|
3978
|
-
} else {
|
|
3979
|
-
edges.push({
|
|
3980
|
-
id: le.id,
|
|
3981
|
-
source: le.source,
|
|
3982
|
-
target: le.target,
|
|
3983
|
-
label: le.label,
|
|
3984
|
-
style: {
|
|
3985
|
-
stroke: c.edgeDefault,
|
|
3986
|
-
strokeWidth: 1.5,
|
|
3987
|
-
opacity: o ? 0.3 : 1
|
|
3988
|
-
},
|
|
3989
|
-
labelStyle: { fontSize: 10, fill: c.labelDefault }
|
|
3990
|
-
});
|
|
3979
|
+
}
|
|
3980
|
+
return { ...slice, doneStageIds: doneIds, activeStageId: activeId };
|
|
3981
|
+
}
|
|
3982
|
+
|
|
3983
|
+
// src/components/FlowchartView/_internal/useSubflowDrill.ts
|
|
3984
|
+
var import_react19 = require("react");
|
|
3985
|
+
function useSubflowDrill(graph, onSubflowChange) {
|
|
3986
|
+
const [currentSubflowId, setCurrentSubflowId] = (0, import_react19.useState)(null);
|
|
3987
|
+
const lastGraphRef = (0, import_react19.useRef)(null);
|
|
3988
|
+
if (lastGraphRef.current !== graph) {
|
|
3989
|
+
lastGraphRef.current = graph;
|
|
3990
|
+
if (currentSubflowId !== null && !graph.nodes.some((n) => n.data?.subflowId === currentSubflowId)) {
|
|
3991
|
+
queueMicrotask(() => setCurrentSubflowId(null));
|
|
3991
3992
|
}
|
|
3992
3993
|
}
|
|
3993
|
-
|
|
3994
|
+
const lastNotifiedRef = (0, import_react19.useRef)(void 0);
|
|
3995
|
+
(0, import_react19.useEffect)(() => {
|
|
3996
|
+
if (lastNotifiedRef.current === currentSubflowId) return;
|
|
3997
|
+
lastNotifiedRef.current = currentSubflowId;
|
|
3998
|
+
if (currentSubflowId === null) {
|
|
3999
|
+
onSubflowChange?.(null);
|
|
4000
|
+
} else {
|
|
4001
|
+
const mount = graph.nodes.find((n) => n.data?.subflowId === currentSubflowId);
|
|
4002
|
+
if (mount) onSubflowChange?.(mount.id);
|
|
4003
|
+
}
|
|
4004
|
+
}, [currentSubflowId, graph, onSubflowChange]);
|
|
4005
|
+
const drillInto = (0, import_react19.useCallback)((subflowId) => {
|
|
4006
|
+
setCurrentSubflowId(subflowId);
|
|
4007
|
+
}, []);
|
|
4008
|
+
const drillUp = (0, import_react19.useCallback)(() => {
|
|
4009
|
+
setCurrentSubflowId(null);
|
|
4010
|
+
}, []);
|
|
4011
|
+
return { currentSubflowId, drillInto, drillUp, setCurrentSubflowId };
|
|
3994
4012
|
}
|
|
3995
4013
|
|
|
3996
|
-
// src/components/FlowchartView/
|
|
3997
|
-
var
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
const
|
|
4001
|
-
(0,
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4014
|
+
// src/components/FlowchartView/_internal/useChartAutoRefit.ts
|
|
4015
|
+
var import_react20 = require("react");
|
|
4016
|
+
function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
|
|
4017
|
+
const duration = options.duration ?? 200;
|
|
4018
|
+
const padding2 = options.padding ?? 0.1;
|
|
4019
|
+
(0, import_react20.useEffect)(() => {
|
|
4020
|
+
const el = wrapperRef.current;
|
|
4021
|
+
if (!el || !rfInstance) return;
|
|
4022
|
+
let raf = 0;
|
|
4023
|
+
const refit = () => {
|
|
4024
|
+
cancelAnimationFrame(raf);
|
|
4025
|
+
raf = requestAnimationFrame(() => {
|
|
4026
|
+
rfInstance.fitView({ duration, padding: padding2 });
|
|
4027
|
+
});
|
|
4004
4028
|
};
|
|
4005
|
-
|
|
4006
|
-
|
|
4029
|
+
const ro = new ResizeObserver(refit);
|
|
4030
|
+
ro.observe(el);
|
|
4031
|
+
window.addEventListener("resize", refit);
|
|
4007
4032
|
return () => {
|
|
4008
|
-
|
|
4009
|
-
|
|
4033
|
+
ro.disconnect();
|
|
4034
|
+
window.removeEventListener("resize", refit);
|
|
4035
|
+
cancelAnimationFrame(raf);
|
|
4010
4036
|
};
|
|
4011
|
-
}, [
|
|
4012
|
-
return null;
|
|
4037
|
+
}, [rfInstance, wrapperRef, duration, padding2]);
|
|
4013
4038
|
}
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4039
|
+
|
|
4040
|
+
// src/components/FlowchartView/SubflowBreadcrumbBar.tsx
|
|
4041
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
4042
|
+
function SubflowBreadcrumbBar({ entries, onNavigate }) {
|
|
4043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4044
|
+
"div",
|
|
4045
|
+
{
|
|
4046
|
+
style: {
|
|
4047
|
+
display: "flex",
|
|
4048
|
+
alignItems: "center",
|
|
4049
|
+
gap: 6,
|
|
4050
|
+
padding: "6px 12px",
|
|
4051
|
+
fontSize: 11,
|
|
4052
|
+
background: rawDefaults.colors.bgSecondary,
|
|
4053
|
+
borderBottom: `1px solid ${rawDefaults.colors.border}`,
|
|
4054
|
+
flexShrink: 0
|
|
4055
|
+
},
|
|
4056
|
+
"aria-label": "Subflow breadcrumb",
|
|
4057
|
+
children: entries.map((entry, i) => {
|
|
4058
|
+
const isLast = i === entries.length - 1;
|
|
4059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4060
|
+
"span",
|
|
4061
|
+
{
|
|
4062
|
+
style: { display: "inline-flex", alignItems: "center", gap: 6 },
|
|
4063
|
+
children: [
|
|
4064
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4065
|
+
"button",
|
|
4066
|
+
{
|
|
4067
|
+
type: "button",
|
|
4068
|
+
onClick: () => onNavigate(entry.subflowId),
|
|
4069
|
+
disabled: isLast,
|
|
4070
|
+
style: {
|
|
4071
|
+
background: "transparent",
|
|
4072
|
+
border: "none",
|
|
4073
|
+
padding: 0,
|
|
4074
|
+
fontSize: 11,
|
|
4075
|
+
fontWeight: isLast ? 600 : 500,
|
|
4076
|
+
color: isLast ? rawDefaults.colors.textPrimary : rawDefaults.colors.primary,
|
|
4077
|
+
cursor: isLast ? "default" : "pointer",
|
|
4078
|
+
textDecoration: isLast ? "none" : "underline",
|
|
4079
|
+
fontFamily: "inherit"
|
|
4080
|
+
},
|
|
4081
|
+
children: entry.label
|
|
4082
|
+
}
|
|
4083
|
+
),
|
|
4084
|
+
!isLast && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
|
|
4085
|
+
]
|
|
4086
|
+
},
|
|
4087
|
+
entry.subflowId ?? "__top__"
|
|
4088
|
+
);
|
|
4089
|
+
})
|
|
4090
|
+
}
|
|
4091
|
+
);
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
// src/components/FlowchartView/TracedFlow.tsx
|
|
4095
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4096
|
+
var DEFAULT_COLORS = {
|
|
4097
|
+
default: rawDefaults.colors.textMuted,
|
|
4098
|
+
done: rawDefaults.colors.success,
|
|
4099
|
+
active: rawDefaults.colors.primary,
|
|
4100
|
+
error: rawDefaults.colors.error,
|
|
4101
|
+
loop: rawDefaults.colors.warning
|
|
4102
|
+
};
|
|
4103
|
+
function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds) {
|
|
4104
|
+
const isDone = doneStageIds.has(node.id);
|
|
4105
|
+
const isActive = activeStageId === node.id;
|
|
4106
|
+
const wasExecuted = isDone || isActive;
|
|
4107
|
+
const hasError = !!errorMessage;
|
|
4108
|
+
const dimmed = !wasExecuted && executedOrderIds.length > 0;
|
|
4109
|
+
let stepNumbers;
|
|
4110
|
+
if (executedOrderIds.length > 0) {
|
|
4111
|
+
const nums = [];
|
|
4112
|
+
for (let i = 0; i < executedOrderIds.length; i++) {
|
|
4113
|
+
if (executedOrderIds[i] === node.id) nums.push(i + 1);
|
|
4114
|
+
}
|
|
4115
|
+
if (nums.length > 0) stepNumbers = nums;
|
|
4116
|
+
}
|
|
4117
|
+
const stageData = {
|
|
4118
|
+
label: node.data.label,
|
|
4119
|
+
isDecider: node.data.isDecider,
|
|
4120
|
+
isFork: node.data.isFork,
|
|
4121
|
+
isSubflow: node.data.isSubflow,
|
|
4122
|
+
active: isActive,
|
|
4123
|
+
done: isDone,
|
|
4124
|
+
error: hasError,
|
|
4125
|
+
...node.data.description !== void 0 && { description: node.data.description },
|
|
4126
|
+
...node.data.icon !== void 0 && { icon: node.data.icon },
|
|
4127
|
+
...node.data.subflowId !== void 0 && { subflowId: node.data.subflowId },
|
|
4128
|
+
...node.data.isLazy === true && { isLazy: true },
|
|
4129
|
+
...dimmed && { dimmed: true },
|
|
4130
|
+
...stepNumbers && { stepNumbers },
|
|
4131
|
+
...errorMessage && { errorMessage }
|
|
4132
|
+
};
|
|
4133
|
+
return {
|
|
4134
|
+
...node,
|
|
4135
|
+
type: "stageNode",
|
|
4136
|
+
data: stageData,
|
|
4137
|
+
...dimmed && { style: { opacity: 0.35 } }
|
|
4138
|
+
};
|
|
4139
|
+
}
|
|
4140
|
+
function styleEdgeWithOverlay(edge, doneStageIds, activeStageId, colors) {
|
|
4141
|
+
const kind = edge.data?.kind ?? "next";
|
|
4142
|
+
const sourceExecuted = doneStageIds.has(edge.source) || activeStageId === edge.source;
|
|
4143
|
+
const targetExecuted = doneStageIds.has(edge.target) || activeStageId === edge.target;
|
|
4144
|
+
const traversed = sourceExecuted && targetExecuted;
|
|
4145
|
+
const isLeadingEdge = activeStageId === edge.source && !doneStageIds.has(edge.target);
|
|
4146
|
+
let color = colors.default;
|
|
4147
|
+
if (kind === "loop") color = colors.loop;
|
|
4148
|
+
else if (isLeadingEdge) color = colors.active;
|
|
4149
|
+
else if (traversed) color = colors.done;
|
|
4150
|
+
const styled = {
|
|
4151
|
+
...edge,
|
|
4152
|
+
type: "smoothstep",
|
|
4153
|
+
animated: isLeadingEdge,
|
|
4154
|
+
style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },
|
|
4155
|
+
markerEnd: { type: import_react22.MarkerType.ArrowClosed, color, width: 16, height: 16 }
|
|
4156
|
+
};
|
|
4157
|
+
if (kind === "loop") {
|
|
4158
|
+
styled.style = { ...styled.style, strokeDasharray: "4 3" };
|
|
4159
|
+
styled.data = {
|
|
4160
|
+
...styled.data ?? {},
|
|
4161
|
+
pathOptions: { borderRadius: 14, offset: 36 }
|
|
4162
|
+
};
|
|
4163
|
+
styled.sourceHandle = "loop-source";
|
|
4164
|
+
styled.targetHandle = "loop-target";
|
|
4165
|
+
}
|
|
4166
|
+
return styled;
|
|
4167
|
+
}
|
|
4168
|
+
var nodeTypes = { stageNode: StageNode };
|
|
4169
|
+
function TracedFlow({
|
|
4170
|
+
graph,
|
|
4171
|
+
overlay,
|
|
4172
|
+
scrubIndex,
|
|
4173
|
+
layout: layoutProp,
|
|
4174
|
+
colors: colorOverrides,
|
|
4018
4175
|
onNodeClick,
|
|
4019
|
-
|
|
4020
|
-
unstyled = false,
|
|
4176
|
+
onSubflowChange,
|
|
4021
4177
|
className,
|
|
4022
4178
|
style
|
|
4023
4179
|
}) {
|
|
4024
|
-
const
|
|
4025
|
-
const
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4180
|
+
const layout = layoutProp ?? defaultTraceFlowLayout;
|
|
4181
|
+
const colors = (0, import_react21.useMemo)(
|
|
4182
|
+
() => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
|
|
4183
|
+
[colorOverrides]
|
|
4184
|
+
);
|
|
4185
|
+
const drill = useSubflowDrill(graph, onSubflowChange);
|
|
4186
|
+
const filteredGraph = (0, import_react21.useMemo)(
|
|
4187
|
+
() => filterGraphForDrill(graph, drill.currentSubflowId),
|
|
4188
|
+
[graph, drill.currentSubflowId]
|
|
4189
|
+
);
|
|
4190
|
+
const breadcrumb = (0, import_react21.useMemo)(
|
|
4191
|
+
() => buildSubflowBreadcrumb(graph, drill.currentSubflowId),
|
|
4192
|
+
[graph, drill.currentSubflowId]
|
|
4193
|
+
);
|
|
4194
|
+
const positioned = (0, import_react21.useMemo)(
|
|
4195
|
+
() => layout === "passthrough" ? filteredGraph : layout(filteredGraph),
|
|
4196
|
+
[filteredGraph, layout]
|
|
4197
|
+
);
|
|
4198
|
+
const slice = (0, import_react21.useMemo)(() => {
|
|
4199
|
+
const empty = {
|
|
4200
|
+
doneStageIds: /* @__PURE__ */ new Set(),
|
|
4201
|
+
activeStageId: null,
|
|
4202
|
+
executedStageIds: /* @__PURE__ */ new Set(),
|
|
4203
|
+
executedOrderIds: [],
|
|
4204
|
+
errors: /* @__PURE__ */ new Map()
|
|
4205
|
+
};
|
|
4206
|
+
if (!overlay) return empty;
|
|
4207
|
+
const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);
|
|
4208
|
+
const normalized = normalizeSliceLeafIds(sliceOverlay(overlay, idx));
|
|
4209
|
+
return aggregateMountStatus(normalized, graph, drill.currentSubflowId);
|
|
4210
|
+
}, [overlay, scrubIndex, graph, drill.currentSubflowId]);
|
|
4211
|
+
const reactFlowNodes = (0, import_react21.useMemo)(
|
|
4212
|
+
() => positioned.nodes.map(
|
|
4213
|
+
(n) => toStageNodeWithOverlay(
|
|
4214
|
+
n,
|
|
4215
|
+
slice.doneStageIds,
|
|
4216
|
+
slice.activeStageId,
|
|
4217
|
+
slice.errors.get(n.id),
|
|
4218
|
+
slice.executedOrderIds
|
|
4219
|
+
)
|
|
4220
|
+
),
|
|
4221
|
+
[positioned.nodes, slice]
|
|
4222
|
+
);
|
|
4223
|
+
const reactFlowEdges = (0, import_react21.useMemo)(
|
|
4224
|
+
() => positioned.edges.map(
|
|
4225
|
+
(e) => styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors)
|
|
4226
|
+
),
|
|
4227
|
+
[positioned.edges, slice, colors]
|
|
4228
|
+
);
|
|
4229
|
+
const handleNodeClick = (0, import_react21.useCallback)(
|
|
4051
4230
|
(_, node) => {
|
|
4052
|
-
|
|
4053
|
-
|
|
4231
|
+
const data = node.data ?? {};
|
|
4232
|
+
if (data.isSubflow && data.subflowId) {
|
|
4233
|
+
drill.drillInto(data.subflowId);
|
|
4234
|
+
}
|
|
4235
|
+
onNodeClick?.(node.id);
|
|
4054
4236
|
},
|
|
4055
|
-
[onNodeClick]
|
|
4237
|
+
[drill, onNodeClick]
|
|
4056
4238
|
);
|
|
4057
|
-
|
|
4239
|
+
const wrapperRef = (0, import_react21.useRef)(null);
|
|
4240
|
+
const [rfInstance, setRfInstance] = (0, import_react21.useState)(null);
|
|
4241
|
+
useChartAutoRefit(wrapperRef, rfInstance);
|
|
4242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
4058
4243
|
"div",
|
|
4059
4244
|
{
|
|
4245
|
+
ref: wrapperRef,
|
|
4060
4246
|
className,
|
|
4061
|
-
style: {
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4247
|
+
style: {
|
|
4248
|
+
width: "100%",
|
|
4249
|
+
height: "100%",
|
|
4250
|
+
minHeight: 300,
|
|
4251
|
+
display: "flex",
|
|
4252
|
+
flexDirection: "column",
|
|
4253
|
+
...style
|
|
4254
|
+
},
|
|
4255
|
+
children: [
|
|
4256
|
+
breadcrumb.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4257
|
+
SubflowBreadcrumbBar,
|
|
4258
|
+
{
|
|
4259
|
+
entries: breadcrumb,
|
|
4260
|
+
onNavigate: drill.setCurrentSubflowId
|
|
4261
|
+
}
|
|
4262
|
+
),
|
|
4263
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4264
|
+
import_react22.ReactFlow,
|
|
4265
|
+
{
|
|
4266
|
+
nodes: reactFlowNodes,
|
|
4267
|
+
edges: reactFlowEdges,
|
|
4268
|
+
nodeTypes,
|
|
4269
|
+
onNodeClick: handleNodeClick,
|
|
4270
|
+
onInit: setRfInstance,
|
|
4271
|
+
fitView: true,
|
|
4272
|
+
proOptions: { hideAttribution: true },
|
|
4273
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.Background, { variant: import_react22.BackgroundVariant.Dots, gap: 20, size: 1 })
|
|
4274
|
+
}
|
|
4275
|
+
) })
|
|
4276
|
+
]
|
|
4089
4277
|
}
|
|
4090
4278
|
);
|
|
4091
4279
|
}
|
|
4092
4280
|
|
|
4093
4281
|
// src/components/InspectorPanel/InspectorPanel.tsx
|
|
4094
|
-
var
|
|
4282
|
+
var import_react24 = require("react");
|
|
4095
4283
|
|
|
4096
4284
|
// src/components/DataTracePanel/DataTracePanel.tsx
|
|
4097
|
-
var
|
|
4098
|
-
var
|
|
4099
|
-
var DataTracePanel = (0,
|
|
4285
|
+
var import_react23 = require("react");
|
|
4286
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
4287
|
+
var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
|
|
4100
4288
|
frames,
|
|
4101
4289
|
selectedStageId,
|
|
4102
4290
|
onFrameClick,
|
|
4103
4291
|
fromStageName
|
|
4104
4292
|
}) {
|
|
4105
4293
|
if (frames.length === 0) {
|
|
4106
|
-
return /* @__PURE__ */ (0,
|
|
4107
|
-
/* @__PURE__ */ (0,
|
|
4294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
|
|
4295
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4108
4296
|
"div",
|
|
4109
4297
|
{
|
|
4110
4298
|
style: {
|
|
@@ -4118,13 +4306,13 @@ var DataTracePanel = (0, import_react20.memo)(function DataTracePanel2({
|
|
|
4118
4306
|
children: "Backward causal chain"
|
|
4119
4307
|
}
|
|
4120
4308
|
),
|
|
4121
|
-
/* @__PURE__ */ (0,
|
|
4122
|
-
/* @__PURE__ */ (0,
|
|
4309
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { color: theme.textSecondary, marginBottom: 10 }, children: "Trace any value back to the stage that created it \u2014 and everything upstream that influenced it." }),
|
|
4310
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
|
|
4123
4311
|
] });
|
|
4124
4312
|
}
|
|
4125
|
-
return /* @__PURE__ */ (0,
|
|
4126
|
-
fromStageName && /* @__PURE__ */ (0,
|
|
4127
|
-
/* @__PURE__ */ (0,
|
|
4313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
|
|
4314
|
+
fromStageName && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "4px 12px 8px" }, children: [
|
|
4315
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4128
4316
|
"div",
|
|
4129
4317
|
{
|
|
4130
4318
|
style: {
|
|
@@ -4140,7 +4328,7 @@ var DataTracePanel = (0, import_react20.memo)(function DataTracePanel2({
|
|
|
4140
4328
|
]
|
|
4141
4329
|
}
|
|
4142
4330
|
),
|
|
4143
|
-
/* @__PURE__ */ (0,
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4144
4332
|
"div",
|
|
4145
4333
|
{
|
|
4146
4334
|
style: {
|
|
@@ -4153,7 +4341,7 @@ var DataTracePanel = (0, import_react20.memo)(function DataTracePanel2({
|
|
|
4153
4341
|
}
|
|
4154
4342
|
)
|
|
4155
4343
|
] }),
|
|
4156
|
-
frames.map((frame, i) => /* @__PURE__ */ (0,
|
|
4344
|
+
frames.map((frame, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4157
4345
|
DataTraceFrame,
|
|
4158
4346
|
{
|
|
4159
4347
|
frame,
|
|
@@ -4166,14 +4354,14 @@ var DataTracePanel = (0, import_react20.memo)(function DataTracePanel2({
|
|
|
4166
4354
|
))
|
|
4167
4355
|
] });
|
|
4168
4356
|
});
|
|
4169
|
-
var DataTraceFrame = (0,
|
|
4357
|
+
var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
|
|
4170
4358
|
frame,
|
|
4171
4359
|
isFirst,
|
|
4172
4360
|
isLast,
|
|
4173
4361
|
isSelected,
|
|
4174
4362
|
onClick
|
|
4175
4363
|
}) {
|
|
4176
|
-
return /* @__PURE__ */ (0,
|
|
4364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4177
4365
|
"button",
|
|
4178
4366
|
{
|
|
4179
4367
|
onClick: () => onClick?.(frame.runtimeStageId),
|
|
@@ -4190,9 +4378,9 @@ var DataTraceFrame = (0, import_react20.memo)(function DataTraceFrame2({
|
|
|
4190
4378
|
fontSize: 13
|
|
4191
4379
|
},
|
|
4192
4380
|
children: [
|
|
4193
|
-
/* @__PURE__ */ (0,
|
|
4194
|
-
!isFirst && /* @__PURE__ */ (0,
|
|
4195
|
-
/* @__PURE__ */ (0,
|
|
4381
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4382
|
+
!isFirst && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { color: theme.textMuted, fontSize: 11 }, children: "\u2191" }),
|
|
4383
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4196
4384
|
"span",
|
|
4197
4385
|
{
|
|
4198
4386
|
style: {
|
|
@@ -4202,7 +4390,7 @@ var DataTraceFrame = (0, import_react20.memo)(function DataTraceFrame2({
|
|
|
4202
4390
|
children: frame.stageName
|
|
4203
4391
|
}
|
|
4204
4392
|
),
|
|
4205
|
-
isLast && !isFirst && /* @__PURE__ */ (0,
|
|
4393
|
+
isLast && !isFirst && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4206
4394
|
"span",
|
|
4207
4395
|
{
|
|
4208
4396
|
style: {
|
|
@@ -4214,7 +4402,7 @@ var DataTraceFrame = (0, import_react20.memo)(function DataTraceFrame2({
|
|
|
4214
4402
|
}
|
|
4215
4403
|
)
|
|
4216
4404
|
] }),
|
|
4217
|
-
frame.keysWritten.length > 0 && /* @__PURE__ */ (0,
|
|
4405
|
+
frame.keysWritten.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4218
4406
|
"div",
|
|
4219
4407
|
{
|
|
4220
4408
|
style: {
|
|
@@ -4226,11 +4414,11 @@ var DataTraceFrame = (0, import_react20.memo)(function DataTraceFrame2({
|
|
|
4226
4414
|
children: [
|
|
4227
4415
|
"wrote:",
|
|
4228
4416
|
" ",
|
|
4229
|
-
/* @__PURE__ */ (0,
|
|
4417
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { color: theme.textSecondary }, children: frame.keysWritten.join(", ") })
|
|
4230
4418
|
]
|
|
4231
4419
|
}
|
|
4232
4420
|
),
|
|
4233
|
-
frame.linkedBy && /* @__PURE__ */ (0,
|
|
4421
|
+
frame.linkedBy && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4234
4422
|
"div",
|
|
4235
4423
|
{
|
|
4236
4424
|
style: {
|
|
@@ -4251,17 +4439,17 @@ var DataTraceFrame = (0, import_react20.memo)(function DataTraceFrame2({
|
|
|
4251
4439
|
});
|
|
4252
4440
|
|
|
4253
4441
|
// src/components/InspectorPanel/InspectorPanel.tsx
|
|
4254
|
-
var
|
|
4255
|
-
var InspectorPanel = (0,
|
|
4442
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4443
|
+
var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
|
|
4256
4444
|
snapshots,
|
|
4257
4445
|
selectedIndex,
|
|
4258
4446
|
dataTraceFrames,
|
|
4259
4447
|
selectedStageId,
|
|
4260
4448
|
onNavigateToStage
|
|
4261
4449
|
}) {
|
|
4262
|
-
const [tab, setTab] = (0,
|
|
4450
|
+
const [tab, setTab] = (0, import_react24.useState)("state");
|
|
4263
4451
|
const currentSnapshot = snapshots[selectedIndex];
|
|
4264
|
-
return /* @__PURE__ */ (0,
|
|
4452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4265
4453
|
"div",
|
|
4266
4454
|
{
|
|
4267
4455
|
style: {
|
|
@@ -4271,7 +4459,7 @@ var InspectorPanel = (0, import_react21.memo)(function InspectorPanel2({
|
|
|
4271
4459
|
overflow: "hidden"
|
|
4272
4460
|
},
|
|
4273
4461
|
children: [
|
|
4274
|
-
/* @__PURE__ */ (0,
|
|
4462
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4275
4463
|
"div",
|
|
4276
4464
|
{
|
|
4277
4465
|
style: {
|
|
@@ -4280,7 +4468,7 @@ var InspectorPanel = (0, import_react21.memo)(function InspectorPanel2({
|
|
|
4280
4468
|
flexShrink: 0
|
|
4281
4469
|
},
|
|
4282
4470
|
children: [
|
|
4283
|
-
/* @__PURE__ */ (0,
|
|
4471
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4284
4472
|
TabButton,
|
|
4285
4473
|
{
|
|
4286
4474
|
active: tab === "state",
|
|
@@ -4288,7 +4476,7 @@ var InspectorPanel = (0, import_react21.memo)(function InspectorPanel2({
|
|
|
4288
4476
|
label: "State"
|
|
4289
4477
|
}
|
|
4290
4478
|
),
|
|
4291
|
-
/* @__PURE__ */ (0,
|
|
4479
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4292
4480
|
TabButton,
|
|
4293
4481
|
{
|
|
4294
4482
|
active: tab === "trace",
|
|
@@ -4300,15 +4488,15 @@ var InspectorPanel = (0, import_react21.memo)(function InspectorPanel2({
|
|
|
4300
4488
|
]
|
|
4301
4489
|
}
|
|
4302
4490
|
),
|
|
4303
|
-
/* @__PURE__ */ (0,
|
|
4304
|
-
tab === "state" && /* @__PURE__ */ (0,
|
|
4491
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
|
|
4492
|
+
tab === "state" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4305
4493
|
MemoryPanel,
|
|
4306
4494
|
{
|
|
4307
4495
|
snapshots,
|
|
4308
4496
|
selectedIndex
|
|
4309
4497
|
}
|
|
4310
4498
|
),
|
|
4311
|
-
tab === "trace" && /* @__PURE__ */ (0,
|
|
4499
|
+
tab === "trace" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4312
4500
|
DataTracePanel,
|
|
4313
4501
|
{
|
|
4314
4502
|
frames: dataTraceFrames,
|
|
@@ -4328,7 +4516,7 @@ function TabButton({
|
|
|
4328
4516
|
label,
|
|
4329
4517
|
badge
|
|
4330
4518
|
}) {
|
|
4331
|
-
return /* @__PURE__ */ (0,
|
|
4519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
4332
4520
|
"button",
|
|
4333
4521
|
{
|
|
4334
4522
|
onClick,
|
|
@@ -4347,7 +4535,7 @@ function TabButton({
|
|
|
4347
4535
|
},
|
|
4348
4536
|
children: [
|
|
4349
4537
|
label,
|
|
4350
|
-
badge && /* @__PURE__ */ (0,
|
|
4538
|
+
badge && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4351
4539
|
"span",
|
|
4352
4540
|
{
|
|
4353
4541
|
style: {
|
|
@@ -4367,28 +4555,28 @@ function TabButton({
|
|
|
4367
4555
|
}
|
|
4368
4556
|
|
|
4369
4557
|
// src/components/InsightPanel/InsightPanel.tsx
|
|
4370
|
-
var
|
|
4371
|
-
var
|
|
4372
|
-
var InsightPanel = (0,
|
|
4558
|
+
var import_react25 = require("react");
|
|
4559
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4560
|
+
var InsightPanel = (0, import_react25.memo)(function InsightPanel2({
|
|
4373
4561
|
insights,
|
|
4374
4562
|
expandedId,
|
|
4375
4563
|
mode
|
|
4376
4564
|
}) {
|
|
4377
4565
|
if (insights.length === 0) {
|
|
4378
|
-
return /* @__PURE__ */ (0,
|
|
4566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "No insights available. Attach recorders to see data." });
|
|
4379
4567
|
}
|
|
4380
4568
|
if (mode === "grid") {
|
|
4381
|
-
return /* @__PURE__ */ (0,
|
|
4569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InsightGrid, { insights });
|
|
4382
4570
|
}
|
|
4383
|
-
return /* @__PURE__ */ (0,
|
|
4571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InsightTabs, { insights, defaultId: expandedId });
|
|
4384
4572
|
});
|
|
4385
|
-
var InsightTabs = (0,
|
|
4573
|
+
var InsightTabs = (0, import_react25.memo)(function InsightTabs2({
|
|
4386
4574
|
insights,
|
|
4387
4575
|
defaultId
|
|
4388
4576
|
}) {
|
|
4389
|
-
const [activeId, setActiveId] = (0,
|
|
4577
|
+
const [activeId, setActiveId] = (0, import_react25.useState)(defaultId ?? insights[0]?.id);
|
|
4390
4578
|
const active = insights.find((i) => i.id === activeId) ?? insights[0];
|
|
4391
|
-
return /* @__PURE__ */ (0,
|
|
4579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4392
4580
|
"div",
|
|
4393
4581
|
{
|
|
4394
4582
|
style: {
|
|
@@ -4398,7 +4586,7 @@ var InsightTabs = (0, import_react22.memo)(function InsightTabs2({
|
|
|
4398
4586
|
overflow: "hidden"
|
|
4399
4587
|
},
|
|
4400
4588
|
children: [
|
|
4401
|
-
/* @__PURE__ */ (0,
|
|
4589
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4402
4590
|
"div",
|
|
4403
4591
|
{
|
|
4404
4592
|
style: {
|
|
@@ -4407,7 +4595,7 @@ var InsightTabs = (0, import_react22.memo)(function InsightTabs2({
|
|
|
4407
4595
|
flexShrink: 0,
|
|
4408
4596
|
overflowX: "auto"
|
|
4409
4597
|
},
|
|
4410
|
-
children: insights.map((insight) => /* @__PURE__ */ (0,
|
|
4598
|
+
children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4411
4599
|
"button",
|
|
4412
4600
|
{
|
|
4413
4601
|
onClick: () => setActiveId(insight.id),
|
|
@@ -4428,16 +4616,16 @@ var InsightTabs = (0, import_react22.memo)(function InsightTabs2({
|
|
|
4428
4616
|
))
|
|
4429
4617
|
}
|
|
4430
4618
|
),
|
|
4431
|
-
/* @__PURE__ */ (0,
|
|
4619
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: active?.render() })
|
|
4432
4620
|
]
|
|
4433
4621
|
}
|
|
4434
4622
|
);
|
|
4435
4623
|
});
|
|
4436
|
-
var InsightGrid = (0,
|
|
4624
|
+
var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
|
|
4437
4625
|
insights
|
|
4438
4626
|
}) {
|
|
4439
4627
|
const cols = insights.length <= 2 ? 1 : 2;
|
|
4440
|
-
return /* @__PURE__ */ (0,
|
|
4628
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4441
4629
|
"div",
|
|
4442
4630
|
{
|
|
4443
4631
|
style: {
|
|
@@ -4448,7 +4636,7 @@ var InsightGrid = (0, import_react22.memo)(function InsightGrid2({
|
|
|
4448
4636
|
gap: 1,
|
|
4449
4637
|
background: theme.border
|
|
4450
4638
|
},
|
|
4451
|
-
children: insights.map((insight) => /* @__PURE__ */ (0,
|
|
4639
|
+
children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4452
4640
|
"div",
|
|
4453
4641
|
{
|
|
4454
4642
|
style: {
|
|
@@ -4458,7 +4646,7 @@ var InsightGrid = (0, import_react22.memo)(function InsightGrid2({
|
|
|
4458
4646
|
overflow: "hidden"
|
|
4459
4647
|
},
|
|
4460
4648
|
children: [
|
|
4461
|
-
/* @__PURE__ */ (0,
|
|
4649
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
4462
4650
|
"div",
|
|
4463
4651
|
{
|
|
4464
4652
|
style: {
|
|
@@ -4473,7 +4661,7 @@ var InsightGrid = (0, import_react22.memo)(function InsightGrid2({
|
|
|
4473
4661
|
},
|
|
4474
4662
|
children: [
|
|
4475
4663
|
insight.name,
|
|
4476
|
-
insight.summary && /* @__PURE__ */ (0,
|
|
4664
|
+
insight.summary && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4477
4665
|
"span",
|
|
4478
4666
|
{
|
|
4479
4667
|
style: {
|
|
@@ -4488,7 +4676,7 @@ var InsightGrid = (0, import_react22.memo)(function InsightGrid2({
|
|
|
4488
4676
|
]
|
|
4489
4677
|
}
|
|
4490
4678
|
),
|
|
4491
|
-
/* @__PURE__ */ (0,
|
|
4679
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: insight.render() })
|
|
4492
4680
|
]
|
|
4493
4681
|
},
|
|
4494
4682
|
insight.id
|
|
@@ -4498,17 +4686,17 @@ var InsightGrid = (0, import_react22.memo)(function InsightGrid2({
|
|
|
4498
4686
|
});
|
|
4499
4687
|
|
|
4500
4688
|
// src/components/CompactTimeline/CompactTimeline.tsx
|
|
4501
|
-
var
|
|
4502
|
-
var
|
|
4503
|
-
var CompactTimeline = (0,
|
|
4689
|
+
var import_react26 = require("react");
|
|
4690
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4691
|
+
var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
|
|
4504
4692
|
snapshots,
|
|
4505
4693
|
selectedIndex,
|
|
4506
4694
|
defaultExpanded = false
|
|
4507
4695
|
}) {
|
|
4508
|
-
const [expanded, setExpanded] = (0,
|
|
4696
|
+
const [expanded, setExpanded] = (0, import_react26.useState)(defaultExpanded);
|
|
4509
4697
|
if (snapshots.length === 0) return null;
|
|
4510
|
-
return /* @__PURE__ */ (0,
|
|
4511
|
-
/* @__PURE__ */ (0,
|
|
4698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { borderTop: `1px solid ${theme.border}` }, children: [
|
|
4699
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
4512
4700
|
"button",
|
|
4513
4701
|
{
|
|
4514
4702
|
onClick: () => setExpanded((e) => !e),
|
|
@@ -4528,13 +4716,13 @@ var CompactTimeline = (0, import_react23.memo)(function CompactTimeline2({
|
|
|
4528
4716
|
letterSpacing: "0.5px"
|
|
4529
4717
|
},
|
|
4530
4718
|
children: [
|
|
4531
|
-
/* @__PURE__ */ (0,
|
|
4719
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10 }, children: expanded ? "\u25BC" : "\u25B8" }),
|
|
4532
4720
|
"Timeline",
|
|
4533
|
-
/* @__PURE__ */ (0,
|
|
4721
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { style: { fontWeight: 400, fontSize: 10 }, children: [
|
|
4534
4722
|
snapshots.length,
|
|
4535
4723
|
" stages"
|
|
4536
4724
|
] }),
|
|
4537
|
-
!expanded && /* @__PURE__ */ (0,
|
|
4725
|
+
!expanded && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
4538
4726
|
"div",
|
|
4539
4727
|
{
|
|
4540
4728
|
style: {
|
|
@@ -4545,7 +4733,7 @@ var CompactTimeline = (0, import_react23.memo)(function CompactTimeline2({
|
|
|
4545
4733
|
marginLeft: 8
|
|
4546
4734
|
},
|
|
4547
4735
|
children: [
|
|
4548
|
-
snapshots.map((snap, i) => /* @__PURE__ */ (0,
|
|
4736
|
+
snapshots.map((snap, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4549
4737
|
"div",
|
|
4550
4738
|
{
|
|
4551
4739
|
style: {
|
|
@@ -4560,7 +4748,7 @@ var CompactTimeline = (0, import_react23.memo)(function CompactTimeline2({
|
|
|
4560
4748
|
},
|
|
4561
4749
|
i
|
|
4562
4750
|
)),
|
|
4563
|
-
/* @__PURE__ */ (0,
|
|
4751
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4564
4752
|
"div",
|
|
4565
4753
|
{
|
|
4566
4754
|
style: {
|
|
@@ -4578,7 +4766,7 @@ var CompactTimeline = (0, import_react23.memo)(function CompactTimeline2({
|
|
|
4578
4766
|
]
|
|
4579
4767
|
}
|
|
4580
4768
|
),
|
|
4581
|
-
expanded && /* @__PURE__ */ (0,
|
|
4769
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "0 12px 8px" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4582
4770
|
GanttTimeline,
|
|
4583
4771
|
{
|
|
4584
4772
|
snapshots,
|
|
@@ -4589,21 +4777,21 @@ var CompactTimeline = (0, import_react23.memo)(function CompactTimeline2({
|
|
|
4589
4777
|
});
|
|
4590
4778
|
|
|
4591
4779
|
// src/components/ExplainableShell/ExplainableShell.tsx
|
|
4592
|
-
var
|
|
4593
|
-
var HLinePill = (0,
|
|
4780
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4781
|
+
var HLinePill = (0, import_react27.memo)(function HLinePill2({
|
|
4594
4782
|
label,
|
|
4595
4783
|
detail,
|
|
4596
4784
|
expanded,
|
|
4597
4785
|
onClick
|
|
4598
4786
|
}) {
|
|
4599
|
-
return /* @__PURE__ */ (0,
|
|
4787
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: {
|
|
4600
4788
|
display: "flex",
|
|
4601
4789
|
alignItems: "center",
|
|
4602
4790
|
gap: 0,
|
|
4603
4791
|
padding: "0"
|
|
4604
4792
|
}, children: [
|
|
4605
|
-
/* @__PURE__ */ (0,
|
|
4606
|
-
/* @__PURE__ */ (0,
|
|
4793
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } }),
|
|
4794
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
4607
4795
|
"button",
|
|
4608
4796
|
{
|
|
4609
4797
|
onClick,
|
|
@@ -4627,31 +4815,31 @@ var HLinePill = (0, import_react24.memo)(function HLinePill2({
|
|
|
4627
4815
|
transition: "color 0.15s ease"
|
|
4628
4816
|
},
|
|
4629
4817
|
children: [
|
|
4630
|
-
/* @__PURE__ */ (0,
|
|
4818
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 7 }, children: expanded ? "\u25BC" : "\u25B6" }),
|
|
4631
4819
|
label,
|
|
4632
|
-
detail && /* @__PURE__ */ (0,
|
|
4820
|
+
detail && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 400, opacity: 0.5, fontSize: 9 }, children: detail })
|
|
4633
4821
|
]
|
|
4634
4822
|
}
|
|
4635
4823
|
),
|
|
4636
|
-
/* @__PURE__ */ (0,
|
|
4824
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } })
|
|
4637
4825
|
] });
|
|
4638
4826
|
});
|
|
4639
|
-
var VLinePill = (0,
|
|
4827
|
+
var VLinePill = (0, import_react27.memo)(function VLinePill2({
|
|
4640
4828
|
label,
|
|
4641
4829
|
expanded,
|
|
4642
4830
|
side = "right",
|
|
4643
4831
|
onClick
|
|
4644
4832
|
}) {
|
|
4645
4833
|
const arrow = side === "right" ? expanded ? "\u25B6" : "\u25C0" : expanded ? "\u25C0" : "\u25B6";
|
|
4646
|
-
return /* @__PURE__ */ (0,
|
|
4834
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: {
|
|
4647
4835
|
display: "flex",
|
|
4648
4836
|
flexDirection: "column",
|
|
4649
4837
|
alignItems: "center",
|
|
4650
4838
|
gap: 0,
|
|
4651
4839
|
padding: "0"
|
|
4652
4840
|
}, children: [
|
|
4653
|
-
/* @__PURE__ */ (0,
|
|
4654
|
-
/* @__PURE__ */ (0,
|
|
4841
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } }),
|
|
4842
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
4655
4843
|
"button",
|
|
4656
4844
|
{
|
|
4657
4845
|
onClick,
|
|
@@ -4676,12 +4864,12 @@ var VLinePill = (0, import_react24.memo)(function VLinePill2({
|
|
|
4676
4864
|
transition: "color 0.15s ease"
|
|
4677
4865
|
},
|
|
4678
4866
|
children: [
|
|
4679
|
-
/* @__PURE__ */ (0,
|
|
4867
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 7, writingMode: "horizontal-tb" }, children: arrow }),
|
|
4680
4868
|
label
|
|
4681
4869
|
]
|
|
4682
4870
|
}
|
|
4683
4871
|
),
|
|
4684
|
-
/* @__PURE__ */ (0,
|
|
4872
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } })
|
|
4685
4873
|
] });
|
|
4686
4874
|
});
|
|
4687
4875
|
function detectKeyedSteps(data) {
|
|
@@ -4718,9 +4906,9 @@ function KeyedRecorderView({
|
|
|
4718
4906
|
snapshots,
|
|
4719
4907
|
selectedIndex
|
|
4720
4908
|
}) {
|
|
4721
|
-
const [showAggregate, setShowAggregate] = (0,
|
|
4722
|
-
const detected = (0,
|
|
4723
|
-
const visibleKeys = (0,
|
|
4909
|
+
const [showAggregate, setShowAggregate] = (0, import_react27.useState)(false);
|
|
4910
|
+
const detected = (0, import_react27.useMemo)(() => detectKeyedSteps(data), [data]);
|
|
4911
|
+
const visibleKeys = (0, import_react27.useMemo)(() => {
|
|
4724
4912
|
const keys = /* @__PURE__ */ new Set();
|
|
4725
4913
|
for (let i = 0; i <= selectedIndex && i < snapshots.length; i++) {
|
|
4726
4914
|
const snap = snapshots[i];
|
|
@@ -4735,7 +4923,7 @@ function KeyedRecorderView({
|
|
|
4735
4923
|
}, [snapshots, selectedIndex, detected?.keyType]);
|
|
4736
4924
|
const isAtEnd = selectedIndex >= snapshots.length - 1;
|
|
4737
4925
|
if (!detected) {
|
|
4738
|
-
return /* @__PURE__ */ (0,
|
|
4926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: 12, fontFamily: theme.fontMono, fontSize: 11, whiteSpace: "pre-wrap", overflow: "auto", height: "100%" }, children: typeof data === "string" ? data : JSON.stringify(data, null, 2) });
|
|
4739
4927
|
}
|
|
4740
4928
|
const steps = detected.steps;
|
|
4741
4929
|
const hints = extractRenderHints(data);
|
|
@@ -4749,13 +4937,13 @@ function KeyedRecorderView({
|
|
|
4749
4937
|
}
|
|
4750
4938
|
}
|
|
4751
4939
|
const grandTotal = hints?.grandTotal ?? 0;
|
|
4752
|
-
return /* @__PURE__ */ (0,
|
|
4753
|
-
description && /* @__PURE__ */ (0,
|
|
4754
|
-
/* @__PURE__ */ (0,
|
|
4940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { overflow: "auto", height: "100%", display: "flex", flexDirection: "column" }, children: [
|
|
4941
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: "6px 12px", fontSize: 11, color: theme.textMuted, fontStyle: "italic", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }, children: description }),
|
|
4942
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: 12, flex: 1, overflow: "auto" }, children: [
|
|
4755
4943
|
preferredOperation === "aggregate" ? (
|
|
4756
4944
|
/* AGGREGATE: collect silently during scrub, button at end to reveal total */
|
|
4757
|
-
/* @__PURE__ */ (0,
|
|
4758
|
-
isAtEnd ? /* @__PURE__ */ (0,
|
|
4945
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4946
|
+
isAtEnd ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { marginBottom: 16 }, children: !showAggregate ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4759
4947
|
"button",
|
|
4760
4948
|
{
|
|
4761
4949
|
onClick: () => setShowAggregate(true),
|
|
@@ -4773,35 +4961,35 @@ function KeyedRecorderView({
|
|
|
4773
4961
|
},
|
|
4774
4962
|
children: "Aggregate \u2014 Show Grand Total"
|
|
4775
4963
|
}
|
|
4776
|
-
) : /* @__PURE__ */ (0,
|
|
4777
|
-
/* @__PURE__ */ (0,
|
|
4778
|
-
numFieldKey && /* @__PURE__ */ (0,
|
|
4964
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "14px 16px", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }, children: [
|
|
4965
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Aggregate \u2014 grand total" }),
|
|
4966
|
+
numFieldKey && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 26, fontWeight: 700, color: theme.success }, children: [
|
|
4779
4967
|
grandTotal < 1 ? grandTotal.toFixed(3) : grandTotal.toFixed(1),
|
|
4780
|
-
/* @__PURE__ */ (0,
|
|
4968
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }, children: [
|
|
4781
4969
|
numFieldKey,
|
|
4782
4970
|
" \xB7 ",
|
|
4783
4971
|
allKeys.length,
|
|
4784
4972
|
" steps"
|
|
4785
4973
|
] })
|
|
4786
4974
|
] })
|
|
4787
|
-
] }) }) : /* @__PURE__ */ (0,
|
|
4788
|
-
/* @__PURE__ */ (0,
|
|
4789
|
-
/* @__PURE__ */ (0,
|
|
4975
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }, children: [
|
|
4976
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600 }, children: "Collecting data..." }),
|
|
4977
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
|
|
4790
4978
|
visibleEntries.length,
|
|
4791
4979
|
" of ",
|
|
4792
4980
|
allKeys.length,
|
|
4793
4981
|
" steps collected. Scrub to end to aggregate."
|
|
4794
4982
|
] })
|
|
4795
4983
|
] }),
|
|
4796
|
-
/* @__PURE__ */ (0,
|
|
4984
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
|
|
4797
4985
|
] })
|
|
4798
4986
|
) : preferredOperation === "accumulate" ? (
|
|
4799
4987
|
/* ACCUMULATE: running total grows with slider — IS the total at end, no button */
|
|
4800
|
-
/* @__PURE__ */ (0,
|
|
4801
|
-
numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ (0,
|
|
4802
|
-
/* @__PURE__ */ (0,
|
|
4803
|
-
/* @__PURE__ */ (0,
|
|
4804
|
-
/* @__PURE__ */ (0,
|
|
4988
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4989
|
+
numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }, children: [
|
|
4990
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 4, fontWeight: 600 }, children: "Accumulate \u2014 running total up to this step" }),
|
|
4991
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 700, fontSize: 18, color: theme.primary }, children: runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1) }),
|
|
4992
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { color: theme.textMuted, marginLeft: 8, fontSize: 10 }, children: [
|
|
4805
4993
|
numFieldKey,
|
|
4806
4994
|
" \xB7 ",
|
|
4807
4995
|
visibleEntries.length,
|
|
@@ -4810,31 +4998,30 @@ function KeyedRecorderView({
|
|
|
4810
4998
|
" steps"
|
|
4811
4999
|
] })
|
|
4812
5000
|
] }),
|
|
4813
|
-
/* @__PURE__ */ (0,
|
|
5001
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
|
|
4814
5002
|
] })
|
|
4815
5003
|
) : (
|
|
4816
5004
|
/* TRANSLATE: per-step entries prominent, no totals */
|
|
4817
|
-
/* @__PURE__ */ (0,
|
|
5005
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Translate \u2014 per-step detail" })
|
|
4818
5006
|
),
|
|
4819
5007
|
visibleEntries.map((key) => {
|
|
4820
5008
|
const entry = steps[key];
|
|
4821
5009
|
const label = entry.stageName ?? key;
|
|
4822
5010
|
const numVal = numFieldKey ? entry[numFieldKey] : void 0;
|
|
4823
|
-
return /* @__PURE__ */ (0,
|
|
4824
|
-
/* @__PURE__ */ (0,
|
|
4825
|
-
/* @__PURE__ */ (0,
|
|
4826
|
-
numVal !== void 0 && /* @__PURE__ */ (0,
|
|
5011
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "4px 0", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }, children: [
|
|
5012
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }, children: key }),
|
|
5013
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 600, flex: 1 }, children: label }),
|
|
5014
|
+
numVal !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { color: theme.primary, fontWeight: 700, marginLeft: 8 }, children: numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1) })
|
|
4827
5015
|
] }, key);
|
|
4828
5016
|
}),
|
|
4829
|
-
visibleEntries.length === 0 && /* @__PURE__ */ (0,
|
|
5017
|
+
visibleEntries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", padding: "8px 0" }, children: "Scrub the slider to reveal entries..." })
|
|
4830
5018
|
] })
|
|
4831
5019
|
] });
|
|
4832
5020
|
}
|
|
4833
|
-
var DetailsContent = (0,
|
|
5021
|
+
var DetailsContent = (0, import_react27.memo)(function DetailsContent2({
|
|
4834
5022
|
snapshots,
|
|
4835
5023
|
selectedIndex,
|
|
4836
5024
|
narrativeEntries,
|
|
4837
|
-
narrative,
|
|
4838
5025
|
size,
|
|
4839
5026
|
fillHeight,
|
|
4840
5027
|
extraViews
|
|
@@ -4843,27 +5030,27 @@ var DetailsContent = (0, import_react24.memo)(function DetailsContent2({
|
|
|
4843
5030
|
{
|
|
4844
5031
|
id: "memory",
|
|
4845
5032
|
name: "Memory",
|
|
4846
|
-
render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0,
|
|
5033
|
+
render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: fillHeight ? { height: "100%" } : void 0 })
|
|
4847
5034
|
},
|
|
4848
5035
|
{
|
|
4849
5036
|
id: "narrative",
|
|
4850
5037
|
name: "Narrative",
|
|
4851
|
-
render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0,
|
|
5038
|
+
render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries, size, style: fillHeight ? { height: "100%" } : void 0 })
|
|
4852
5039
|
}
|
|
4853
5040
|
];
|
|
4854
5041
|
const allViews = [...builtInViews, ...extraViews ?? []];
|
|
4855
|
-
const [activeViewId, setActiveViewId] = (0,
|
|
5042
|
+
const [activeViewId, setActiveViewId] = (0, import_react27.useState)(allViews[0]?.id ?? "memory");
|
|
4856
5043
|
const viewIds = allViews.map((v2) => v2.id).join(",");
|
|
4857
|
-
(0,
|
|
5044
|
+
(0, import_react27.useEffect)(() => {
|
|
4858
5045
|
if (!allViews.find((v2) => v2.id === activeViewId)) {
|
|
4859
5046
|
setActiveViewId(allViews[0]?.id ?? "memory");
|
|
4860
5047
|
}
|
|
4861
5048
|
}, [viewIds]);
|
|
4862
5049
|
const activeView = allViews.find((v2) => v2.id === activeViewId) ?? allViews[0];
|
|
4863
|
-
return /* @__PURE__ */ (0,
|
|
4864
|
-
/* @__PURE__ */ (0,
|
|
5050
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
|
|
5051
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: "auto" }, children: allViews.map((view) => {
|
|
4865
5052
|
const active = view.id === activeViewId;
|
|
4866
|
-
return /* @__PURE__ */ (0,
|
|
5053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4867
5054
|
"button",
|
|
4868
5055
|
{
|
|
4869
5056
|
onClick: () => setActiveViewId(view.id),
|
|
@@ -4887,7 +5074,7 @@ var DetailsContent = (0, import_react24.memo)(function DetailsContent2({
|
|
|
4887
5074
|
view.id
|
|
4888
5075
|
);
|
|
4889
5076
|
}) }),
|
|
4890
|
-
/* @__PURE__ */ (0,
|
|
5077
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: activeView?.render({ snapshots, selectedIndex }) })
|
|
4891
5078
|
] });
|
|
4892
5079
|
});
|
|
4893
5080
|
function resolveSubflowLevel(parentSpec, parentSnapshots, subflowNodeName, narrativeEntries) {
|
|
@@ -4961,7 +5148,7 @@ function buildDataTrace(commitLog, targetRuntimeStageId, maxDepth = 10) {
|
|
|
4961
5148
|
}
|
|
4962
5149
|
return frames;
|
|
4963
5150
|
}
|
|
4964
|
-
var RightPanel = (0,
|
|
5151
|
+
var RightPanel = (0, import_react27.memo)(function RightPanel2({
|
|
4965
5152
|
mode,
|
|
4966
5153
|
onModeChange,
|
|
4967
5154
|
snapshots,
|
|
@@ -4971,19 +5158,18 @@ var RightPanel = (0, import_react24.memo)(function RightPanel2({
|
|
|
4971
5158
|
activeTab,
|
|
4972
5159
|
allTabs,
|
|
4973
5160
|
activeNarrativeEntries,
|
|
4974
|
-
activeNarrative,
|
|
4975
5161
|
recorderViews,
|
|
4976
5162
|
autoRecorderViews,
|
|
4977
5163
|
size,
|
|
4978
5164
|
onNavigateToStage
|
|
4979
5165
|
}) {
|
|
4980
|
-
return /* @__PURE__ */ (0,
|
|
4981
|
-
/* @__PURE__ */ (0,
|
|
5166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
5167
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
4982
5168
|
display: "flex",
|
|
4983
5169
|
borderBottom: `1px solid ${theme.border}`,
|
|
4984
5170
|
flexShrink: 0,
|
|
4985
5171
|
background: theme.bgSecondary
|
|
4986
|
-
}, children: ["insights", "what"].map((m) => /* @__PURE__ */ (0,
|
|
5172
|
+
}, children: ["insights", "what"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4987
5173
|
"button",
|
|
4988
5174
|
{
|
|
4989
5175
|
onClick: () => onModeChange(m),
|
|
@@ -5005,7 +5191,7 @@ var RightPanel = (0, import_react24.memo)(function RightPanel2({
|
|
|
5005
5191
|
},
|
|
5006
5192
|
m
|
|
5007
5193
|
)) }),
|
|
5008
|
-
/* @__PURE__ */ (0,
|
|
5194
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5009
5195
|
InsightPanel,
|
|
5010
5196
|
{
|
|
5011
5197
|
mode: "tabs",
|
|
@@ -5014,16 +5200,16 @@ var RightPanel = (0, import_react24.memo)(function RightPanel2({
|
|
|
5014
5200
|
id: tab.id,
|
|
5015
5201
|
name: insightName(tab.name),
|
|
5016
5202
|
render: () => {
|
|
5017
|
-
if (tab.id === "narrative") return /* @__PURE__ */ (0,
|
|
5203
|
+
if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, runtimeSnapshot, spec, size, style: { height: "100%" } });
|
|
5018
5204
|
const customView = recorderViews?.find((v2) => v2.id === tab.id);
|
|
5019
5205
|
if (customView?.render) return customView.render({ snapshots, selectedIndex });
|
|
5020
5206
|
const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
|
|
5021
|
-
if (autoView) return /* @__PURE__ */ (0,
|
|
5207
|
+
if (autoView) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
|
|
5022
5208
|
return null;
|
|
5023
5209
|
}
|
|
5024
5210
|
}))
|
|
5025
5211
|
}
|
|
5026
|
-
) : /* @__PURE__ */ (0,
|
|
5212
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5027
5213
|
InspectorPanel,
|
|
5028
5214
|
{
|
|
5029
5215
|
snapshots,
|
|
@@ -5045,17 +5231,6 @@ function insightName(name) {
|
|
|
5045
5231
|
};
|
|
5046
5232
|
return map[name] ?? name;
|
|
5047
5233
|
}
|
|
5048
|
-
function defaultRenderFlowchart({ spec: s, snapshots: snaps, selectedIndex, onNodeClick }) {
|
|
5049
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
5050
|
-
TracedFlowchartView,
|
|
5051
|
-
{
|
|
5052
|
-
spec: s,
|
|
5053
|
-
snapshots: snaps,
|
|
5054
|
-
snapshotIndex: selectedIndex,
|
|
5055
|
-
onNodeClick
|
|
5056
|
-
}
|
|
5057
|
-
);
|
|
5058
|
-
}
|
|
5059
5234
|
function ExplainableShell({
|
|
5060
5235
|
snapshots: snapshotsProp,
|
|
5061
5236
|
runtimeSnapshot,
|
|
@@ -5063,7 +5238,6 @@ function ExplainableShell({
|
|
|
5063
5238
|
title,
|
|
5064
5239
|
resultData: resultDataProp,
|
|
5065
5240
|
logs = [],
|
|
5066
|
-
narrative: narrativeProp,
|
|
5067
5241
|
narrativeEntries,
|
|
5068
5242
|
tabs = ["result", "explainable"],
|
|
5069
5243
|
defaultTab,
|
|
@@ -5073,36 +5247,58 @@ function ExplainableShell({
|
|
|
5073
5247
|
defaultExpanded,
|
|
5074
5248
|
recorderViews,
|
|
5075
5249
|
renderFlowchart,
|
|
5250
|
+
showStageId = false,
|
|
5251
|
+
traceGraph,
|
|
5252
|
+
runtimeOverlay,
|
|
5076
5253
|
size = "default",
|
|
5077
5254
|
unstyled = false,
|
|
5078
5255
|
className,
|
|
5079
5256
|
style
|
|
5080
5257
|
}) {
|
|
5081
|
-
const derivedFromRuntime = (0,
|
|
5258
|
+
const derivedFromRuntime = (0, import_react27.useMemo)(() => {
|
|
5082
5259
|
if (!runtimeSnapshot) return null;
|
|
5083
5260
|
try {
|
|
5084
5261
|
const snaps = toVisualizationSnapshots(runtimeSnapshot, narrativeEntries);
|
|
5085
|
-
|
|
5086
|
-
for (const snap of snaps) {
|
|
5087
|
-
const lines = (snap.narrative ?? "").split("\n").filter(Boolean);
|
|
5088
|
-
narr.push(...lines);
|
|
5089
|
-
}
|
|
5090
|
-
return { snapshots: snaps, resultData: runtimeSnapshot.sharedState, narrative: narr };
|
|
5262
|
+
return { snapshots: snaps, resultData: runtimeSnapshot.sharedState };
|
|
5091
5263
|
} catch {
|
|
5092
5264
|
return null;
|
|
5093
5265
|
}
|
|
5094
5266
|
}, [runtimeSnapshot, narrativeEntries]);
|
|
5095
5267
|
const snapshots = snapshotsProp ?? derivedFromRuntime?.snapshots ?? [];
|
|
5096
5268
|
const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;
|
|
5097
|
-
const
|
|
5098
|
-
|
|
5269
|
+
const tracedFlowRenderer = (0, import_react27.useMemo)(() => {
|
|
5270
|
+
if (!traceGraph) return void 0;
|
|
5271
|
+
return ({ selectedIndex, snapshots: snapshots2, onNodeClick }) => {
|
|
5272
|
+
const activeRsid = snapshots2[selectedIndex]?.runtimeStageId;
|
|
5273
|
+
let overlayIdx = selectedIndex;
|
|
5274
|
+
if (activeRsid && runtimeOverlay) {
|
|
5275
|
+
const i = runtimeOverlay.executionOrder.findIndex(
|
|
5276
|
+
(s) => s.runtimeStageId === activeRsid
|
|
5277
|
+
);
|
|
5278
|
+
if (i >= 0) overlayIdx = i;
|
|
5279
|
+
}
|
|
5280
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5281
|
+
TracedFlow,
|
|
5282
|
+
{
|
|
5283
|
+
graph: traceGraph,
|
|
5284
|
+
overlay: runtimeOverlay ?? void 0,
|
|
5285
|
+
scrubIndex: overlayIdx,
|
|
5286
|
+
onNodeClick: (stageId) => onNodeClick?.(stageId),
|
|
5287
|
+
onSubflowChange: (mountId) => {
|
|
5288
|
+
if (mountId !== null) onNodeClick?.(mountId);
|
|
5289
|
+
}
|
|
5290
|
+
}
|
|
5291
|
+
);
|
|
5292
|
+
};
|
|
5293
|
+
}, [traceGraph, runtimeOverlay]);
|
|
5294
|
+
const effectiveRenderFlowchart = renderFlowchart ?? tracedFlowRenderer;
|
|
5099
5295
|
const leftLabel = panelLabels?.topology ?? "Topology";
|
|
5100
5296
|
const rightLabel = panelLabels?.details ?? "Details";
|
|
5101
5297
|
const bottomLabel = panelLabels?.timeline ?? "Timeline";
|
|
5102
|
-
const shellRef = (0,
|
|
5103
|
-
const [isNarrow, setIsNarrow] = (0,
|
|
5104
|
-
const [isMedium, setIsMedium] = (0,
|
|
5105
|
-
(0,
|
|
5298
|
+
const shellRef = (0, import_react27.useRef)(null);
|
|
5299
|
+
const [isNarrow, setIsNarrow] = (0, import_react27.useState)(false);
|
|
5300
|
+
const [isMedium, setIsMedium] = (0, import_react27.useState)(false);
|
|
5301
|
+
(0, import_react27.useEffect)(() => {
|
|
5106
5302
|
const el = shellRef.current;
|
|
5107
5303
|
if (!el) return;
|
|
5108
5304
|
const ro = new ResizeObserver(([entry]) => {
|
|
@@ -5114,14 +5310,14 @@ function ExplainableShell({
|
|
|
5114
5310
|
ro.observe(el);
|
|
5115
5311
|
return () => ro.disconnect();
|
|
5116
5312
|
}, []);
|
|
5117
|
-
const autoRecorderViews = (0,
|
|
5313
|
+
const autoRecorderViews = (0, import_react27.useMemo)(() => {
|
|
5118
5314
|
const recorders = runtimeSnapshot?.recorders;
|
|
5119
5315
|
if (!recorders?.length) return [];
|
|
5120
5316
|
const explicitIds = new Set((recorderViews ?? []).map((v2) => v2.id));
|
|
5121
5317
|
return recorders.filter((r) => !explicitIds.has(r.id)).map((r) => ({ id: r.id, name: r.name, description: r.description, preferredOperation: r.preferredOperation, data: r.data }));
|
|
5122
5318
|
}, [runtimeSnapshot, recorderViews]);
|
|
5123
|
-
const hasNarrative = !!
|
|
5124
|
-
const allTabs = (0,
|
|
5319
|
+
const hasNarrative = !!narrativeEntries?.length;
|
|
5320
|
+
const allTabs = (0, import_react27.useMemo)(() => {
|
|
5125
5321
|
const tabs2 = [
|
|
5126
5322
|
{ id: "result", name: "Result", description: "Final output and console logs" },
|
|
5127
5323
|
{ id: "memory", name: "Memory", description: "Accumulator \u2014 progressive shared state at each stage" }
|
|
@@ -5140,38 +5336,38 @@ function ExplainableShell({
|
|
|
5140
5336
|
}, [hasNarrative, recorderViews, autoRecorderViews, hideTabsProp]);
|
|
5141
5337
|
const validTabIds = new Set(allTabs.map((t) => t.id));
|
|
5142
5338
|
const resolvedDefault = defaultTab && validTabIds.has(defaultTab) ? defaultTab : allTabs[0]?.id ?? "result";
|
|
5143
|
-
const [activeTab, setActiveTab] = (0,
|
|
5144
|
-
const [snapshotIdx, setSnapshotIdx] = (0,
|
|
5145
|
-
const [drillDownStack, setDrillDownStack] = (0,
|
|
5146
|
-
const [rightExpanded, setRightExpanded] = (0,
|
|
5147
|
-
const [rightPanelMode, setRightPanelMode] = (0,
|
|
5148
|
-
const [leftExpanded, setLeftExpanded] = (0,
|
|
5149
|
-
const [timelineExpanded, setTimelineExpanded] = (0,
|
|
5150
|
-
(0,
|
|
5339
|
+
const [activeTab, setActiveTab] = (0, import_react27.useState)(resolvedDefault);
|
|
5340
|
+
const [snapshotIdx, setSnapshotIdx] = (0, import_react27.useState)(0);
|
|
5341
|
+
const [drillDownStack, setDrillDownStack] = (0, import_react27.useState)([]);
|
|
5342
|
+
const [rightExpanded, setRightExpanded] = (0, import_react27.useState)(defaultExpanded?.details ?? true);
|
|
5343
|
+
const [rightPanelMode, setRightPanelMode] = (0, import_react27.useState)("insights");
|
|
5344
|
+
const [leftExpanded, setLeftExpanded] = (0, import_react27.useState)(defaultExpanded?.topology ?? false);
|
|
5345
|
+
const [timelineExpanded, setTimelineExpanded] = (0, import_react27.useState)(defaultExpanded?.timeline ?? false);
|
|
5346
|
+
(0, import_react27.useEffect)(() => {
|
|
5151
5347
|
if (isNarrow) {
|
|
5152
5348
|
setLeftExpanded(false);
|
|
5153
5349
|
setRightExpanded(false);
|
|
5154
5350
|
setTimelineExpanded(false);
|
|
5155
5351
|
}
|
|
5156
5352
|
}, [isNarrow]);
|
|
5157
|
-
const triggerReflow = (0,
|
|
5353
|
+
const triggerReflow = (0, import_react27.useCallback)(() => {
|
|
5158
5354
|
requestAnimationFrame(() => window.dispatchEvent(new Event("resize")));
|
|
5159
5355
|
setTimeout(() => window.dispatchEvent(new Event("resize")), 320);
|
|
5160
5356
|
}, []);
|
|
5161
|
-
const toggleLeft = (0,
|
|
5357
|
+
const toggleLeft = (0, import_react27.useCallback)((v2) => {
|
|
5162
5358
|
setLeftExpanded(v2);
|
|
5163
5359
|
triggerReflow();
|
|
5164
5360
|
}, [triggerReflow]);
|
|
5165
|
-
const toggleRight = (0,
|
|
5361
|
+
const toggleRight = (0, import_react27.useCallback)((v2) => {
|
|
5166
5362
|
setRightExpanded(v2);
|
|
5167
5363
|
triggerReflow();
|
|
5168
5364
|
}, [triggerReflow]);
|
|
5169
|
-
const toggleTimeline = (0,
|
|
5365
|
+
const toggleTimeline = (0, import_react27.useCallback)(() => {
|
|
5170
5366
|
setTimelineExpanded((p) => !p);
|
|
5171
5367
|
triggerReflow();
|
|
5172
5368
|
}, [triggerReflow]);
|
|
5173
5369
|
const isInSubflow = drillDownStack.length > 0;
|
|
5174
|
-
const currentLevel = (0,
|
|
5370
|
+
const currentLevel = (0, import_react27.useMemo)(() => {
|
|
5175
5371
|
if (drillDownStack.length > 0) {
|
|
5176
5372
|
const top = drillDownStack[drillDownStack.length - 1];
|
|
5177
5373
|
return { spec: top.spec, snapshots: top.snapshots };
|
|
@@ -5181,35 +5377,31 @@ function ExplainableShell({
|
|
|
5181
5377
|
const activeSnapshots = currentLevel.snapshots;
|
|
5182
5378
|
const activeSpec = currentLevel.spec;
|
|
5183
5379
|
const safeIdx = activeSnapshots.length > 0 ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1)) : 0;
|
|
5184
|
-
const activeNarrative = (0, import_react24.useMemo)(() => {
|
|
5185
|
-
if (!isInSubflow) return narrative;
|
|
5186
|
-
const lines = [];
|
|
5187
|
-
for (const snap of activeSnapshots) {
|
|
5188
|
-
const stageLines = (snap.narrative ?? "").split("\n").filter(Boolean);
|
|
5189
|
-
lines.push(...stageLines);
|
|
5190
|
-
}
|
|
5191
|
-
return lines.length > 0 ? lines : void 0;
|
|
5192
|
-
}, [isInSubflow, narrative, activeSnapshots]);
|
|
5193
5380
|
const activeNarrativeEntries = isInSubflow ? void 0 : narrativeEntries;
|
|
5194
|
-
const breadcrumbs = (0,
|
|
5381
|
+
const breadcrumbs = (0, import_react27.useMemo)(() => {
|
|
5195
5382
|
const root = { label: title || "Flowchart", spec, description: spec?.description };
|
|
5196
5383
|
return [root, ...drillDownStack.map((e) => ({ label: e.label, spec: e.spec, description: void 0 }))];
|
|
5197
5384
|
}, [spec, title, drillDownStack]);
|
|
5198
|
-
const showTreeSidebar = (0,
|
|
5199
|
-
|
|
5385
|
+
const showTreeSidebar = (0, import_react27.useMemo)(() => {
|
|
5386
|
+
if (traceGraph?.nodes?.length) {
|
|
5387
|
+
return traceGraph.nodes.some((n) => n.data?.isSubflow === true);
|
|
5388
|
+
}
|
|
5389
|
+
return !!spec && hasSubflowNodes(spec);
|
|
5390
|
+
}, [traceGraph, spec]);
|
|
5391
|
+
const rootOverlay = (0, import_react27.useMemo)(() => {
|
|
5200
5392
|
if (isInSubflow || !snapshots.length) return { activeStage: void 0, doneStages: void 0 };
|
|
5201
5393
|
const doneStages = new Set(snapshots.slice(0, safeIdx).map((s) => s.stageLabel));
|
|
5202
5394
|
const activeStage = snapshots[safeIdx]?.stageLabel ?? null;
|
|
5203
5395
|
return { activeStage, doneStages };
|
|
5204
5396
|
}, [isInSubflow, snapshots, safeIdx]);
|
|
5205
|
-
const handleTabChange = (0,
|
|
5397
|
+
const handleTabChange = (0, import_react27.useCallback)((tab) => {
|
|
5206
5398
|
setActiveTab(tab);
|
|
5207
5399
|
setDrillDownStack([]);
|
|
5208
5400
|
}, []);
|
|
5209
|
-
const handleSnapshotChange = (0,
|
|
5401
|
+
const handleSnapshotChange = (0, import_react27.useCallback)((idx) => {
|
|
5210
5402
|
if (typeof idx === "number") setSnapshotIdx(idx);
|
|
5211
5403
|
}, []);
|
|
5212
|
-
const handleDrillDown = (0,
|
|
5404
|
+
const handleDrillDown = (0, import_react27.useCallback)(
|
|
5213
5405
|
(nodeName) => {
|
|
5214
5406
|
if (!activeSpec) return;
|
|
5215
5407
|
const entry = resolveSubflowLevel(activeSpec, activeSnapshots, nodeName, narrativeEntries);
|
|
@@ -5220,14 +5412,14 @@ function ExplainableShell({
|
|
|
5220
5412
|
},
|
|
5221
5413
|
[activeSpec, activeSnapshots, narrativeEntries, snapshotIdx]
|
|
5222
5414
|
);
|
|
5223
|
-
const handleBreadcrumbNavigate = (0,
|
|
5415
|
+
const handleBreadcrumbNavigate = (0, import_react27.useCallback)((level) => {
|
|
5224
5416
|
setDrillDownStack((prev) => {
|
|
5225
5417
|
const popped = level === 0 ? prev[0] : prev[level];
|
|
5226
5418
|
if (popped) setSnapshotIdx(popped.parentSnapshotIdx);
|
|
5227
5419
|
return level === 0 ? [] : prev.slice(0, level);
|
|
5228
5420
|
});
|
|
5229
5421
|
}, []);
|
|
5230
|
-
const handleNodeClick = (0,
|
|
5422
|
+
const handleNodeClick = (0, import_react27.useCallback)(
|
|
5231
5423
|
(indexOrId) => {
|
|
5232
5424
|
if (typeof indexOrId === "number") {
|
|
5233
5425
|
setSnapshotIdx(indexOrId);
|
|
@@ -5245,7 +5437,7 @@ function ExplainableShell({
|
|
|
5245
5437
|
},
|
|
5246
5438
|
[activeSpec, activeSnapshots, handleDrillDown]
|
|
5247
5439
|
);
|
|
5248
|
-
const handleTreeNodeSelect = (0,
|
|
5440
|
+
const handleTreeNodeSelect = (0, import_react27.useCallback)(
|
|
5249
5441
|
(name, isSubflow) => {
|
|
5250
5442
|
if (isSubflow && spec) {
|
|
5251
5443
|
setDrillDownStack([]);
|
|
@@ -5264,31 +5456,31 @@ function ExplainableShell({
|
|
|
5264
5456
|
);
|
|
5265
5457
|
const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));
|
|
5266
5458
|
if (unstyled) {
|
|
5267
|
-
return /* @__PURE__ */ (0,
|
|
5268
|
-
/* @__PURE__ */ (0,
|
|
5269
|
-
/* @__PURE__ */ (0,
|
|
5270
|
-
activeTab === "result" && /* @__PURE__ */ (0,
|
|
5271
|
-
(activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ (0,
|
|
5272
|
-
/* @__PURE__ */ (0,
|
|
5273
|
-
isInSubflow && /* @__PURE__ */ (0,
|
|
5274
|
-
activeSpec && effectiveRenderFlowchart?.({ spec: activeSpec, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick }),
|
|
5275
|
-
/* @__PURE__ */ (0,
|
|
5276
|
-
/* @__PURE__ */ (0,
|
|
5277
|
-
/* @__PURE__ */ (0,
|
|
5459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className, style, "data-fp": "explainable-shell", children: [
|
|
5460
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
|
|
5461
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
|
|
5462
|
+
activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
|
|
5463
|
+
(activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
5464
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true }),
|
|
5465
|
+
isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
|
|
5466
|
+
activeSpec && effectiveRenderFlowchart?.({ spec: activeSpec, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId }),
|
|
5467
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
|
|
5468
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
|
|
5469
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
|
|
5278
5470
|
] })
|
|
5279
5471
|
] })
|
|
5280
5472
|
] });
|
|
5281
5473
|
}
|
|
5282
5474
|
const showTopology = !!effectiveRenderFlowchart && !!activeSpec;
|
|
5283
|
-
const detailsContent = (0,
|
|
5475
|
+
const detailsContent = (0, import_react27.useMemo)(() => {
|
|
5284
5476
|
if (activeTab === "result") {
|
|
5285
|
-
return /* @__PURE__ */ (0,
|
|
5477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, size });
|
|
5286
5478
|
}
|
|
5287
5479
|
if (activeTab === "memory") {
|
|
5288
|
-
return /* @__PURE__ */ (0,
|
|
5480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
|
|
5289
5481
|
}
|
|
5290
5482
|
if (activeTab === "narrative") {
|
|
5291
|
-
return /* @__PURE__ */ (0,
|
|
5483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, size, style: { height: "100%" } });
|
|
5292
5484
|
}
|
|
5293
5485
|
const customView = recorderViews?.find((v2) => v2.id === activeTab);
|
|
5294
5486
|
if (customView?.render) {
|
|
@@ -5296,7 +5488,7 @@ function ExplainableShell({
|
|
|
5296
5488
|
}
|
|
5297
5489
|
const autoView = autoRecorderViews.find((v2) => v2.id === activeTab);
|
|
5298
5490
|
if (autoView) {
|
|
5299
|
-
return /* @__PURE__ */ (0,
|
|
5491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5300
5492
|
KeyedRecorderView,
|
|
5301
5493
|
{
|
|
5302
5494
|
data: autoView.data,
|
|
@@ -5308,9 +5500,9 @@ function ExplainableShell({
|
|
|
5308
5500
|
);
|
|
5309
5501
|
}
|
|
5310
5502
|
return null;
|
|
5311
|
-
}, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries,
|
|
5312
|
-
const detailsPanel = /* @__PURE__ */ (0,
|
|
5313
|
-
/* @__PURE__ */ (0,
|
|
5503
|
+
}, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries, recorderViews, autoRecorderViews]);
|
|
5504
|
+
const detailsPanel = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }, children: [
|
|
5505
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: {
|
|
5314
5506
|
display: "flex",
|
|
5315
5507
|
borderBottom: `1px solid ${theme.border}`,
|
|
5316
5508
|
background: theme.bgSecondary,
|
|
@@ -5318,7 +5510,7 @@ function ExplainableShell({
|
|
|
5318
5510
|
overflowX: "auto"
|
|
5319
5511
|
}, children: allTabs.map((tab) => {
|
|
5320
5512
|
const active = tab.id === activeTab;
|
|
5321
|
-
return /* @__PURE__ */ (0,
|
|
5513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5322
5514
|
"button",
|
|
5323
5515
|
{
|
|
5324
5516
|
onClick: () => handleTabChange(tab.id),
|
|
@@ -5342,9 +5534,9 @@ function ExplainableShell({
|
|
|
5342
5534
|
tab.id
|
|
5343
5535
|
);
|
|
5344
5536
|
}) }),
|
|
5345
|
-
/* @__PURE__ */ (0,
|
|
5537
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
|
|
5346
5538
|
] });
|
|
5347
|
-
return /* @__PURE__ */ (0,
|
|
5539
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5348
5540
|
"div",
|
|
5349
5541
|
{
|
|
5350
5542
|
ref: shellRef,
|
|
@@ -5362,7 +5554,7 @@ function ExplainableShell({
|
|
|
5362
5554
|
},
|
|
5363
5555
|
"data-fp": "explainable-shell",
|
|
5364
5556
|
children: [
|
|
5365
|
-
/* @__PURE__ */ (0,
|
|
5557
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5366
5558
|
TimeTravelControls,
|
|
5367
5559
|
{
|
|
5368
5560
|
snapshots: activeSnapshots,
|
|
@@ -5371,57 +5563,59 @@ function ExplainableShell({
|
|
|
5371
5563
|
size
|
|
5372
5564
|
}
|
|
5373
5565
|
),
|
|
5374
|
-
isInSubflow && /* @__PURE__ */ (0,
|
|
5375
|
-
/* @__PURE__ */ (0,
|
|
5566
|
+
isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
|
|
5567
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: isNarrow ? (
|
|
5376
5568
|
/* ── Mobile: stacked vertical ── */
|
|
5377
|
-
/* @__PURE__ */ (0,
|
|
5378
|
-
showTopology && /* @__PURE__ */ (0,
|
|
5569
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
5570
|
+
showTopology && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { height: 350, flexShrink: 0, overflow: "hidden" }, children: effectiveRenderFlowchart({
|
|
5379
5571
|
spec: activeSpec,
|
|
5380
5572
|
snapshots: activeSnapshots,
|
|
5381
5573
|
selectedIndex: safeIdx,
|
|
5382
|
-
onNodeClick: handleNodeClick
|
|
5574
|
+
onNodeClick: handleNodeClick,
|
|
5575
|
+
showStageId
|
|
5383
5576
|
}) }),
|
|
5384
|
-
showTreeSidebar && /* @__PURE__ */ (0,
|
|
5385
|
-
/* @__PURE__ */ (0,
|
|
5386
|
-
leftExpanded && /* @__PURE__ */ (0,
|
|
5577
|
+
showTreeSidebar && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
5578
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
|
|
5579
|
+
leftExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { maxHeight: 180, overflow: "auto", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5387
5580
|
SubflowTree,
|
|
5388
5581
|
{
|
|
5389
|
-
|
|
5582
|
+
graph: traceGraph ?? { nodes: [], edges: [] },
|
|
5390
5583
|
activeStage: rootOverlay.activeStage,
|
|
5391
5584
|
doneStages: rootOverlay.doneStages,
|
|
5392
5585
|
onNodeSelect: handleTreeNodeSelect
|
|
5393
5586
|
}
|
|
5394
5587
|
) })
|
|
5395
5588
|
] }),
|
|
5396
|
-
/* @__PURE__ */ (0,
|
|
5397
|
-
rightExpanded && /* @__PURE__ */ (0,
|
|
5398
|
-
/* @__PURE__ */ (0,
|
|
5399
|
-
timelineExpanded && /* @__PURE__ */ (0,
|
|
5589
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
|
|
5590
|
+
rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { maxHeight: 350, flexShrink: 0, overflow: "hidden" }, children: detailsPanel }),
|
|
5591
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
|
|
5592
|
+
timelineExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
|
|
5400
5593
|
] })
|
|
5401
5594
|
) : (
|
|
5402
5595
|
/* ── Desktop: two-column — Flowchart | Right Panel ── */
|
|
5403
|
-
/* @__PURE__ */ (0,
|
|
5404
|
-
/* @__PURE__ */ (0,
|
|
5405
|
-
showTreeSidebar && (leftExpanded ? /* @__PURE__ */ (0,
|
|
5406
|
-
/* @__PURE__ */ (0,
|
|
5596
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
5597
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
|
|
5598
|
+
showTreeSidebar && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
|
|
5599
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5407
5600
|
SubflowTree,
|
|
5408
5601
|
{
|
|
5409
|
-
|
|
5602
|
+
graph: traceGraph ?? { nodes: [], edges: [] },
|
|
5410
5603
|
activeStage: rootOverlay.activeStage,
|
|
5411
5604
|
doneStages: rootOverlay.doneStages,
|
|
5412
5605
|
onNodeSelect: handleTreeNodeSelect
|
|
5413
5606
|
}
|
|
5414
5607
|
) }),
|
|
5415
|
-
/* @__PURE__ */ (0,
|
|
5416
|
-
] }) : /* @__PURE__ */ (0,
|
|
5417
|
-
showTopology ? /* @__PURE__ */ (0,
|
|
5608
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
|
|
5609
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
|
|
5610
|
+
showTopology ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
|
|
5418
5611
|
spec: activeSpec,
|
|
5419
5612
|
snapshots: activeSnapshots,
|
|
5420
5613
|
selectedIndex: safeIdx,
|
|
5421
|
-
onNodeClick: handleNodeClick
|
|
5422
|
-
|
|
5423
|
-
/* @__PURE__ */ (0,
|
|
5424
|
-
|
|
5614
|
+
onNodeClick: handleNodeClick,
|
|
5615
|
+
showStageId
|
|
5616
|
+
}) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1 } }),
|
|
5617
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
|
|
5618
|
+
rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5425
5619
|
RightPanel,
|
|
5426
5620
|
{
|
|
5427
5621
|
mode: rightPanelMode,
|
|
@@ -5433,7 +5627,6 @@ function ExplainableShell({
|
|
|
5433
5627
|
activeTab,
|
|
5434
5628
|
allTabs,
|
|
5435
5629
|
activeNarrativeEntries,
|
|
5436
|
-
activeNarrative,
|
|
5437
5630
|
recorderViews,
|
|
5438
5631
|
autoRecorderViews,
|
|
5439
5632
|
size,
|
|
@@ -5444,7 +5637,7 @@ function ExplainableShell({
|
|
|
5444
5637
|
}
|
|
5445
5638
|
) })
|
|
5446
5639
|
] }),
|
|
5447
|
-
/* @__PURE__ */ (0,
|
|
5640
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5448
5641
|
CompactTimeline,
|
|
5449
5642
|
{
|
|
5450
5643
|
snapshots: activeSnapshots,
|
|
@@ -5461,8 +5654,8 @@ function ExplainableShell({
|
|
|
5461
5654
|
|
|
5462
5655
|
// src/components/TraceViewer/TraceViewer.tsx
|
|
5463
5656
|
var React = __toESM(require("react"), 1);
|
|
5464
|
-
var
|
|
5465
|
-
var
|
|
5657
|
+
var import_react28 = require("react");
|
|
5658
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
5466
5659
|
function parseTrace(input) {
|
|
5467
5660
|
if (input == null) {
|
|
5468
5661
|
return {
|
|
@@ -5525,11 +5718,11 @@ function TraceViewer({
|
|
|
5525
5718
|
recorderViews,
|
|
5526
5719
|
renderFlowchart
|
|
5527
5720
|
}) {
|
|
5528
|
-
const parsed = (0,
|
|
5721
|
+
const parsed = (0, import_react28.useMemo)(() => parseTrace(trace), [trace]);
|
|
5529
5722
|
React.useEffect(() => {
|
|
5530
5723
|
if (!parsed.ok && onError) onError(parsed.error);
|
|
5531
5724
|
}, [parsed, onError]);
|
|
5532
|
-
const snapshots = (0,
|
|
5725
|
+
const snapshots = (0, import_react28.useMemo)(() => {
|
|
5533
5726
|
if (!parsed.ok || !parsed.trace.snapshot) return [];
|
|
5534
5727
|
try {
|
|
5535
5728
|
return toVisualizationSnapshots(
|
|
@@ -5543,12 +5736,11 @@ function TraceViewer({
|
|
|
5543
5736
|
if (!parsed.ok || snapshots.length === 0) {
|
|
5544
5737
|
return fallback ?? null;
|
|
5545
5738
|
}
|
|
5546
|
-
return /* @__PURE__ */ (0,
|
|
5739
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5547
5740
|
ExplainableShell,
|
|
5548
5741
|
{
|
|
5549
5742
|
snapshots,
|
|
5550
5743
|
spec: parsed.trace.spec,
|
|
5551
|
-
narrative: parsed.trace.narrative,
|
|
5552
5744
|
narrativeEntries: parsed.trace.narrativeEntries,
|
|
5553
5745
|
tabs,
|
|
5554
5746
|
defaultTab,
|