footprint-explainable-ui 0.26.2 → 0.28.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/flowchart.cjs +35 -2
- package/dist/flowchart.cjs.map +1 -1
- package/dist/flowchart.d.cts +12 -1
- package/dist/flowchart.d.ts +12 -1
- package/dist/flowchart.js +35 -2
- package/dist/flowchart.js.map +1 -1
- package/dist/index.cjs +151 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +151 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -625,10 +625,17 @@ interface RecorderView {
|
|
|
625
625
|
}) => React.ReactNode;
|
|
626
626
|
}
|
|
627
627
|
/**
|
|
628
|
-
* The Trace flowchart's two-colour theme (footprintjs level).
|
|
629
|
-
*
|
|
630
|
-
* `
|
|
631
|
-
*
|
|
628
|
+
* The Trace flowchart's two-colour theme (footprintjs level).
|
|
629
|
+
*
|
|
630
|
+
* `mode` is the COARSE switch: it applies eui's full light or dark preset
|
|
631
|
+
* (`coolLight` / `coolDark`) as `--fp-*` variables on the shell root, so the
|
|
632
|
+
* ENTIRE shell — canvas, panels, nodes, text, borders — follows dark/light from
|
|
633
|
+
* this one field. You do NOT need to hand-set `--fp-*` yourself. (`--fp-*`
|
|
634
|
+
* remains available as a fine escape hatch for individual token overrides.)
|
|
635
|
+
*
|
|
636
|
+
* `visited` and `current` are the two semantic node colours, layered on top of
|
|
637
|
+
* the mode base. All optional — sensible per-mode defaults are used for anything
|
|
638
|
+
* omitted.
|
|
632
639
|
*/
|
|
633
640
|
interface TraceTheme {
|
|
634
641
|
mode?: "dark" | "light";
|
|
@@ -676,11 +683,11 @@ interface ExplainableShellProps extends BaseComponentProps {
|
|
|
676
683
|
runtimeOverlay?: RuntimeOverlay | null;
|
|
677
684
|
/**
|
|
678
685
|
* Trace flowchart theme — the footprintjs-LEVEL **two-colour** scheme:
|
|
679
|
-
* `visited` (executed nodes) + `current` (the cursor node). `mode`
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
* use the per-mode defaults. The agent-semantic three-colour theme
|
|
683
|
-
* `<Lens>`, not here.
|
|
686
|
+
* `visited` (executed nodes) + `current` (the cursor node). `mode` is the
|
|
687
|
+
* coarse light/dark switch — it applies eui's full preset to the whole shell,
|
|
688
|
+
* so you pass one word instead of a wall of `--fp-*` vars. Colours are optional
|
|
689
|
+
* — omit to use the per-mode defaults. The agent-semantic three-colour theme
|
|
690
|
+
* belongs to `<Lens>`, not here.
|
|
684
691
|
*/
|
|
685
692
|
traceTheme?: TraceTheme;
|
|
686
693
|
title?: string;
|
|
@@ -724,6 +731,9 @@ interface ExplainableShellProps extends BaseComponentProps {
|
|
|
724
731
|
selectedIndex: number;
|
|
725
732
|
onNodeClick?: (indexOrId: number | string) => void;
|
|
726
733
|
showStageId?: boolean;
|
|
734
|
+
/** Dependency-cone overlay (chart node id → BFS depth) — painted while
|
|
735
|
+
* the Inspector's Data Trace tab is open. Custom renderers may ignore it. */
|
|
736
|
+
sliceCone?: ReadonlyMap<string, number>;
|
|
727
737
|
}) => React.ReactNode;
|
|
728
738
|
/**
|
|
729
739
|
* When true, render each node's stable `stageId` as a small monospace
|
|
@@ -1075,6 +1085,8 @@ interface DataTracePanelProps {
|
|
|
1075
1085
|
onFrameClick?: (runtimeStageId: string) => void;
|
|
1076
1086
|
/** Optional: stage name for the "tracing from" header. */
|
|
1077
1087
|
fromStageName?: string;
|
|
1088
|
+
/** Optional honesty line rendered under the header (⚠-style). */
|
|
1089
|
+
note?: string;
|
|
1078
1090
|
}
|
|
1079
1091
|
/**
|
|
1080
1092
|
* Render the backward causal chain as a stack trace.
|
|
@@ -1088,10 +1100,15 @@ interface InspectorPanelProps {
|
|
|
1088
1100
|
selectedIndex: number;
|
|
1089
1101
|
/** Causal chain frames for the selected node (empty = no trace available). */
|
|
1090
1102
|
dataTraceFrames: CausalFrame[];
|
|
1103
|
+
/** Optional honesty line for the Data Trace tab (e.g. reads not recorded). */
|
|
1104
|
+
dataTraceNote?: string;
|
|
1091
1105
|
/** Currently selected runtimeStageId. */
|
|
1092
1106
|
selectedStageId?: string;
|
|
1093
1107
|
/** Navigate to a stage when clicking a Data Trace frame. */
|
|
1094
1108
|
onNavigateToStage?: (runtimeStageId: string) => void;
|
|
1109
|
+
/** Fires when the user switches tabs — lets the shell paint the chart's
|
|
1110
|
+
* dependency cone while the Data Trace tab is open. */
|
|
1111
|
+
onTabChange?: (tab: "state" | "trace") => void;
|
|
1095
1112
|
}
|
|
1096
1113
|
declare const InspectorPanel: react.NamedExoticComponent<InspectorPanelProps>;
|
|
1097
1114
|
|
package/dist/index.d.ts
CHANGED
|
@@ -625,10 +625,17 @@ interface RecorderView {
|
|
|
625
625
|
}) => React.ReactNode;
|
|
626
626
|
}
|
|
627
627
|
/**
|
|
628
|
-
* The Trace flowchart's two-colour theme (footprintjs level).
|
|
629
|
-
*
|
|
630
|
-
* `
|
|
631
|
-
*
|
|
628
|
+
* The Trace flowchart's two-colour theme (footprintjs level).
|
|
629
|
+
*
|
|
630
|
+
* `mode` is the COARSE switch: it applies eui's full light or dark preset
|
|
631
|
+
* (`coolLight` / `coolDark`) as `--fp-*` variables on the shell root, so the
|
|
632
|
+
* ENTIRE shell — canvas, panels, nodes, text, borders — follows dark/light from
|
|
633
|
+
* this one field. You do NOT need to hand-set `--fp-*` yourself. (`--fp-*`
|
|
634
|
+
* remains available as a fine escape hatch for individual token overrides.)
|
|
635
|
+
*
|
|
636
|
+
* `visited` and `current` are the two semantic node colours, layered on top of
|
|
637
|
+
* the mode base. All optional — sensible per-mode defaults are used for anything
|
|
638
|
+
* omitted.
|
|
632
639
|
*/
|
|
633
640
|
interface TraceTheme {
|
|
634
641
|
mode?: "dark" | "light";
|
|
@@ -676,11 +683,11 @@ interface ExplainableShellProps extends BaseComponentProps {
|
|
|
676
683
|
runtimeOverlay?: RuntimeOverlay | null;
|
|
677
684
|
/**
|
|
678
685
|
* Trace flowchart theme — the footprintjs-LEVEL **two-colour** scheme:
|
|
679
|
-
* `visited` (executed nodes) + `current` (the cursor node). `mode`
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
* use the per-mode defaults. The agent-semantic three-colour theme
|
|
683
|
-
* `<Lens>`, not here.
|
|
686
|
+
* `visited` (executed nodes) + `current` (the cursor node). `mode` is the
|
|
687
|
+
* coarse light/dark switch — it applies eui's full preset to the whole shell,
|
|
688
|
+
* so you pass one word instead of a wall of `--fp-*` vars. Colours are optional
|
|
689
|
+
* — omit to use the per-mode defaults. The agent-semantic three-colour theme
|
|
690
|
+
* belongs to `<Lens>`, not here.
|
|
684
691
|
*/
|
|
685
692
|
traceTheme?: TraceTheme;
|
|
686
693
|
title?: string;
|
|
@@ -724,6 +731,9 @@ interface ExplainableShellProps extends BaseComponentProps {
|
|
|
724
731
|
selectedIndex: number;
|
|
725
732
|
onNodeClick?: (indexOrId: number | string) => void;
|
|
726
733
|
showStageId?: boolean;
|
|
734
|
+
/** Dependency-cone overlay (chart node id → BFS depth) — painted while
|
|
735
|
+
* the Inspector's Data Trace tab is open. Custom renderers may ignore it. */
|
|
736
|
+
sliceCone?: ReadonlyMap<string, number>;
|
|
727
737
|
}) => React.ReactNode;
|
|
728
738
|
/**
|
|
729
739
|
* When true, render each node's stable `stageId` as a small monospace
|
|
@@ -1075,6 +1085,8 @@ interface DataTracePanelProps {
|
|
|
1075
1085
|
onFrameClick?: (runtimeStageId: string) => void;
|
|
1076
1086
|
/** Optional: stage name for the "tracing from" header. */
|
|
1077
1087
|
fromStageName?: string;
|
|
1088
|
+
/** Optional honesty line rendered under the header (⚠-style). */
|
|
1089
|
+
note?: string;
|
|
1078
1090
|
}
|
|
1079
1091
|
/**
|
|
1080
1092
|
* Render the backward causal chain as a stack trace.
|
|
@@ -1088,10 +1100,15 @@ interface InspectorPanelProps {
|
|
|
1088
1100
|
selectedIndex: number;
|
|
1089
1101
|
/** Causal chain frames for the selected node (empty = no trace available). */
|
|
1090
1102
|
dataTraceFrames: CausalFrame[];
|
|
1103
|
+
/** Optional honesty line for the Data Trace tab (e.g. reads not recorded). */
|
|
1104
|
+
dataTraceNote?: string;
|
|
1091
1105
|
/** Currently selected runtimeStageId. */
|
|
1092
1106
|
selectedStageId?: string;
|
|
1093
1107
|
/** Navigate to a stage when clicking a Data Trace frame. */
|
|
1094
1108
|
onNavigateToStage?: (runtimeStageId: string) => void;
|
|
1109
|
+
/** Fires when the user switches tabs — lets the shell paint the chart's
|
|
1110
|
+
* dependency cone while the Data Trace tab is open. */
|
|
1111
|
+
onTabChange?: (tab: "state" | "trace") => void;
|
|
1095
1112
|
}
|
|
1096
1113
|
declare const InspectorPanel: react.NamedExoticComponent<InspectorPanelProps>;
|
|
1097
1114
|
|
package/dist/index.js
CHANGED
|
@@ -2228,6 +2228,67 @@ function TimeTravelControls({
|
|
|
2228
2228
|
// src/components/ExplainableShell/ExplainableShell.tsx
|
|
2229
2229
|
import { memo as memo8, useState as useState14, useCallback as useCallback8, useMemo as useMemo12, useRef as useRef9, useEffect as useEffect11 } from "react";
|
|
2230
2230
|
|
|
2231
|
+
// src/components/ExplainableShell/_internal/dataTrace.ts
|
|
2232
|
+
function readsByStep(tree) {
|
|
2233
|
+
const byStep = /* @__PURE__ */ new Map();
|
|
2234
|
+
if (!tree) return byStep;
|
|
2235
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2236
|
+
const stack = [tree];
|
|
2237
|
+
while (stack.length > 0) {
|
|
2238
|
+
const node = stack.pop();
|
|
2239
|
+
if (visited.has(node)) continue;
|
|
2240
|
+
visited.add(node);
|
|
2241
|
+
if (node.runtimeStageId && node.stageReads) {
|
|
2242
|
+
const keys = Object.keys(node.stageReads);
|
|
2243
|
+
if (keys.length > 0) byStep.set(node.runtimeStageId, keys);
|
|
2244
|
+
}
|
|
2245
|
+
if (node.next) stack.push(node.next);
|
|
2246
|
+
if (node.children) for (const c of node.children) stack.push(c);
|
|
2247
|
+
}
|
|
2248
|
+
return byStep;
|
|
2249
|
+
}
|
|
2250
|
+
function buildDataTrace(commitLog, executionTree, targetRuntimeStageId, maxDepth = 10, maxFrames = 50) {
|
|
2251
|
+
const log = commitLog ?? [];
|
|
2252
|
+
const reads = readsByStep(executionTree);
|
|
2253
|
+
const readsAvailable = reads.size > 0;
|
|
2254
|
+
if (!log.length) return { frames: [], readsAvailable };
|
|
2255
|
+
const idxOf = /* @__PURE__ */ new Map();
|
|
2256
|
+
for (let i = 0; i < log.length; i++) idxOf.set(log[i].runtimeStageId, i);
|
|
2257
|
+
const startIdx = idxOf.get(targetRuntimeStageId);
|
|
2258
|
+
if (startIdx === void 0) return { frames: [], readsAvailable };
|
|
2259
|
+
const findLastWriter = (key, beforeIdx) => {
|
|
2260
|
+
for (let i = beforeIdx - 1; i >= 0; i--) {
|
|
2261
|
+
if (log[i].trace.some((t) => t.path === key)) return i;
|
|
2262
|
+
}
|
|
2263
|
+
return -1;
|
|
2264
|
+
};
|
|
2265
|
+
const frames = [];
|
|
2266
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2267
|
+
const queue = [[startIdx, 0, ""]];
|
|
2268
|
+
while (queue.length > 0 && frames.length < maxFrames) {
|
|
2269
|
+
const [idx, depth, linkedBy] = queue.shift();
|
|
2270
|
+
const commit = log[idx];
|
|
2271
|
+
if (visited.has(commit.runtimeStageId)) continue;
|
|
2272
|
+
visited.add(commit.runtimeStageId);
|
|
2273
|
+
frames.push({
|
|
2274
|
+
runtimeStageId: commit.runtimeStageId,
|
|
2275
|
+
stageId: commit.stageId,
|
|
2276
|
+
stageName: commit.stage,
|
|
2277
|
+
keysWritten: commit.trace.map((t) => t.path),
|
|
2278
|
+
linkedBy,
|
|
2279
|
+
depth
|
|
2280
|
+
});
|
|
2281
|
+
if (depth >= maxDepth) continue;
|
|
2282
|
+
for (const key of reads.get(commit.runtimeStageId) ?? []) {
|
|
2283
|
+
const writerIdx = findLastWriter(key, idx);
|
|
2284
|
+
if (writerIdx >= 0 && !visited.has(log[writerIdx].runtimeStageId)) {
|
|
2285
|
+
queue.push([writerIdx, depth + 1, key]);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
return { frames, readsAvailable };
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2231
2292
|
// src/utils/narrativeSync.ts
|
|
2232
2293
|
function buildEntryRangeIndex(entries) {
|
|
2233
2294
|
const ranges = /* @__PURE__ */ new Map();
|
|
@@ -4964,6 +5025,7 @@ function TracedFlow({
|
|
|
4964
5025
|
nodeTypes: userNodeTypes,
|
|
4965
5026
|
edgeTypes: userEdgeTypes,
|
|
4966
5027
|
coActiveStageIds,
|
|
5028
|
+
sliceCone,
|
|
4967
5029
|
children,
|
|
4968
5030
|
className,
|
|
4969
5031
|
style
|
|
@@ -5065,6 +5127,38 @@ function TracedFlow({
|
|
|
5065
5127
|
),
|
|
5066
5128
|
[positioned.edges, slice, colors]
|
|
5067
5129
|
);
|
|
5130
|
+
const [coneRevealed, setConeRevealed] = useState10(false);
|
|
5131
|
+
useEffect10(() => {
|
|
5132
|
+
if (!sliceCone) return;
|
|
5133
|
+
setConeRevealed(false);
|
|
5134
|
+
const raf = requestAnimationFrame(() => setConeRevealed(true));
|
|
5135
|
+
return () => cancelAnimationFrame(raf);
|
|
5136
|
+
}, [sliceCone]);
|
|
5137
|
+
const conedNodes = useMemo10(() => {
|
|
5138
|
+
if (!sliceCone || sliceCone.size === 0) return reactFlowNodes;
|
|
5139
|
+
return reactFlowNodes.map((n) => {
|
|
5140
|
+
const depth = sliceCone.get(n.id);
|
|
5141
|
+
if (depth === void 0) {
|
|
5142
|
+
return { ...n, style: { ...n.style, opacity: 0.22, transition: "opacity 260ms ease" } };
|
|
5143
|
+
}
|
|
5144
|
+
return {
|
|
5145
|
+
...n,
|
|
5146
|
+
style: {
|
|
5147
|
+
...n.style,
|
|
5148
|
+
opacity: coneRevealed ? 1 : 0.22,
|
|
5149
|
+
transition: "opacity 320ms ease",
|
|
5150
|
+
transitionDelay: `${depth * 90}ms`
|
|
5151
|
+
}
|
|
5152
|
+
};
|
|
5153
|
+
});
|
|
5154
|
+
}, [reactFlowNodes, sliceCone, coneRevealed]);
|
|
5155
|
+
const conedEdges = useMemo10(() => {
|
|
5156
|
+
if (!sliceCone || sliceCone.size === 0) return reactFlowEdges;
|
|
5157
|
+
return reactFlowEdges.map((e) => {
|
|
5158
|
+
const inCone = sliceCone.has(e.source) && sliceCone.has(e.target);
|
|
5159
|
+
return inCone ? e : { ...e, style: { ...e.style, opacity: 0.12, transition: "opacity 260ms ease" } };
|
|
5160
|
+
});
|
|
5161
|
+
}, [reactFlowEdges, sliceCone]);
|
|
5068
5162
|
const handleNodeClick = useCallback7(
|
|
5069
5163
|
(_, node) => {
|
|
5070
5164
|
const data = node.data ?? {};
|
|
@@ -5106,8 +5200,8 @@ function TracedFlow({
|
|
|
5106
5200
|
/* @__PURE__ */ jsx21("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsxs18(
|
|
5107
5201
|
ReactFlow,
|
|
5108
5202
|
{
|
|
5109
|
-
nodes:
|
|
5110
|
-
edges:
|
|
5203
|
+
nodes: conedNodes,
|
|
5204
|
+
edges: conedEdges,
|
|
5111
5205
|
nodeTypes: mergedNodeTypes,
|
|
5112
5206
|
edgeTypes: mergedEdgeTypes,
|
|
5113
5207
|
onNodeClick: handleNodeClick,
|
|
@@ -5138,8 +5232,10 @@ var DataTracePanel = memo4(function DataTracePanel2({
|
|
|
5138
5232
|
frames,
|
|
5139
5233
|
selectedStageId,
|
|
5140
5234
|
onFrameClick,
|
|
5141
|
-
fromStageName
|
|
5235
|
+
fromStageName,
|
|
5236
|
+
note
|
|
5142
5237
|
}) {
|
|
5238
|
+
const noteLine = note ? /* @__PURE__ */ jsx22("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", marginBottom: 8 }, children: note }) : null;
|
|
5143
5239
|
if (frames.length === 0) {
|
|
5144
5240
|
return /* @__PURE__ */ jsxs19("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
|
|
5145
5241
|
/* @__PURE__ */ jsx22(
|
|
@@ -5157,10 +5253,12 @@ var DataTracePanel = memo4(function DataTracePanel2({
|
|
|
5157
5253
|
}
|
|
5158
5254
|
),
|
|
5159
5255
|
/* @__PURE__ */ jsx22("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." }),
|
|
5256
|
+
noteLine,
|
|
5160
5257
|
/* @__PURE__ */ jsx22("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
|
|
5161
5258
|
] });
|
|
5162
5259
|
}
|
|
5163
5260
|
return /* @__PURE__ */ jsxs19("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
|
|
5261
|
+
note && /* @__PURE__ */ jsx22("div", { style: { padding: "4px 12px 0", fontSize: 11, color: theme.textMuted, fontStyle: "italic" }, children: note }),
|
|
5164
5262
|
fromStageName && /* @__PURE__ */ jsxs19("div", { style: { padding: "4px 12px 8px" }, children: [
|
|
5165
5263
|
/* @__PURE__ */ jsxs19(
|
|
5166
5264
|
"div",
|
|
@@ -5294,10 +5392,16 @@ var InspectorPanel = memo5(function InspectorPanel2({
|
|
|
5294
5392
|
snapshots,
|
|
5295
5393
|
selectedIndex,
|
|
5296
5394
|
dataTraceFrames,
|
|
5395
|
+
dataTraceNote,
|
|
5297
5396
|
selectedStageId,
|
|
5298
|
-
onNavigateToStage
|
|
5397
|
+
onNavigateToStage,
|
|
5398
|
+
onTabChange
|
|
5299
5399
|
}) {
|
|
5300
|
-
const [tab,
|
|
5400
|
+
const [tab, setTabState] = useState11("state");
|
|
5401
|
+
const setTab = (t) => {
|
|
5402
|
+
setTabState(t);
|
|
5403
|
+
onTabChange?.(t);
|
|
5404
|
+
};
|
|
5301
5405
|
const currentSnapshot = snapshots[selectedIndex];
|
|
5302
5406
|
return /* @__PURE__ */ jsxs20(
|
|
5303
5407
|
"div",
|
|
@@ -5350,6 +5454,7 @@ var InspectorPanel = memo5(function InspectorPanel2({
|
|
|
5350
5454
|
DataTracePanel,
|
|
5351
5455
|
{
|
|
5352
5456
|
frames: dataTraceFrames,
|
|
5457
|
+
note: dataTraceNote,
|
|
5353
5458
|
selectedStageId,
|
|
5354
5459
|
onFrameClick: onNavigateToStage,
|
|
5355
5460
|
fromStageName: currentSnapshot?.stageName
|
|
@@ -5941,40 +6046,6 @@ function resolveSubflowFromRuntime(parentSnapshots, subflowId, narrativeEntries)
|
|
|
5941
6046
|
if (sfSnapshots.length === 0) return null;
|
|
5942
6047
|
return { subflowId, label, spec: null, snapshots: sfSnapshots, narrative: sfNarrative };
|
|
5943
6048
|
}
|
|
5944
|
-
function buildDataTrace(commitLog, targetRuntimeStageId, maxDepth = 10) {
|
|
5945
|
-
const log = commitLog;
|
|
5946
|
-
if (!log?.length) return [];
|
|
5947
|
-
const idxMap = /* @__PURE__ */ new Map();
|
|
5948
|
-
for (let i = 0; i < log.length; i++) idxMap.set(log[i].runtimeStageId, i);
|
|
5949
|
-
const startIdx = idxMap.get(targetRuntimeStageId);
|
|
5950
|
-
if (startIdx === void 0) return [];
|
|
5951
|
-
const startCommit = log[startIdx];
|
|
5952
|
-
const frames = [];
|
|
5953
|
-
const visited = /* @__PURE__ */ new Set();
|
|
5954
|
-
let current = startCommit;
|
|
5955
|
-
let currentIdx = startIdx;
|
|
5956
|
-
let depth = 0;
|
|
5957
|
-
while (current && depth <= maxDepth) {
|
|
5958
|
-
if (visited.has(current.runtimeStageId)) break;
|
|
5959
|
-
visited.add(current.runtimeStageId);
|
|
5960
|
-
frames.push({
|
|
5961
|
-
runtimeStageId: current.runtimeStageId,
|
|
5962
|
-
stageId: current.stageId,
|
|
5963
|
-
stageName: current.stage,
|
|
5964
|
-
keysWritten: current.trace.map((t) => t.path),
|
|
5965
|
-
linkedBy: depth === 0 ? "" : current.trace[0]?.path ?? "",
|
|
5966
|
-
depth
|
|
5967
|
-
});
|
|
5968
|
-
if (currentIdx > 0) {
|
|
5969
|
-
currentIdx--;
|
|
5970
|
-
current = log[currentIdx];
|
|
5971
|
-
depth++;
|
|
5972
|
-
} else {
|
|
5973
|
-
break;
|
|
5974
|
-
}
|
|
5975
|
-
}
|
|
5976
|
-
return frames;
|
|
5977
|
-
}
|
|
5978
6049
|
var RightPanel = memo8(function RightPanel2({
|
|
5979
6050
|
mode,
|
|
5980
6051
|
onModeChange,
|
|
@@ -5987,7 +6058,9 @@ var RightPanel = memo8(function RightPanel2({
|
|
|
5987
6058
|
recorderViews,
|
|
5988
6059
|
autoRecorderViews,
|
|
5989
6060
|
size,
|
|
5990
|
-
onNavigateToStage
|
|
6061
|
+
onNavigateToStage,
|
|
6062
|
+
dataTrace,
|
|
6063
|
+
onInspectorTabChange
|
|
5991
6064
|
}) {
|
|
5992
6065
|
return /* @__PURE__ */ jsxs23(Fragment6, { children: [
|
|
5993
6066
|
/* @__PURE__ */ jsx26("div", { style: {
|
|
@@ -6040,7 +6113,9 @@ var RightPanel = memo8(function RightPanel2({
|
|
|
6040
6113
|
{
|
|
6041
6114
|
snapshots,
|
|
6042
6115
|
selectedIndex,
|
|
6043
|
-
dataTraceFrames:
|
|
6116
|
+
dataTraceFrames: dataTrace.frames,
|
|
6117
|
+
dataTraceNote: dataTrace.readsAvailable ? void 0 : "\u26A0 reads were not recorded (readTracking off) \u2014 dependencies are unknowable, not absent.",
|
|
6118
|
+
onTabChange: onInspectorTabChange,
|
|
6044
6119
|
selectedStageId: snapshots[selectedIndex]?.runtimeStageId,
|
|
6045
6120
|
onNavigateToStage
|
|
6046
6121
|
}
|
|
@@ -6094,7 +6169,7 @@ function ExplainableShell({
|
|
|
6094
6169
|
const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;
|
|
6095
6170
|
const tracedFlowRenderer = useMemo12(() => {
|
|
6096
6171
|
if (!traceGraph) return void 0;
|
|
6097
|
-
return ({ selectedIndex, snapshots: snapshots2, onNodeClick }) => {
|
|
6172
|
+
return ({ selectedIndex, snapshots: snapshots2, onNodeClick, sliceCone: sliceCone2 }) => {
|
|
6098
6173
|
const activeRsid = snapshots2[selectedIndex]?.runtimeStageId;
|
|
6099
6174
|
let overlayIdx = selectedIndex;
|
|
6100
6175
|
if (activeRsid && runtimeOverlay) {
|
|
@@ -6118,6 +6193,7 @@ function ExplainableShell({
|
|
|
6118
6193
|
{
|
|
6119
6194
|
graph: traceGraph,
|
|
6120
6195
|
overlay: runtimeOverlay ?? void 0,
|
|
6196
|
+
sliceCone: sliceCone2 ?? void 0,
|
|
6121
6197
|
colors: traceColors || void 0,
|
|
6122
6198
|
scrubIndex: overlayIdx,
|
|
6123
6199
|
onNodeClick: (stageId) => onNodeClick?.(stageId),
|
|
@@ -6178,6 +6254,7 @@ function ExplainableShell({
|
|
|
6178
6254
|
const [drillDownStack, setDrillDownStack] = useState14([]);
|
|
6179
6255
|
const [rightExpanded, setRightExpanded] = useState14(defaultExpanded?.details ?? true);
|
|
6180
6256
|
const [rightPanelMode, setRightPanelMode] = useState14("insights");
|
|
6257
|
+
const [inspectorTab, setInspectorTab] = useState14("state");
|
|
6181
6258
|
const [leftExpanded, setLeftExpanded] = useState14(defaultExpanded?.topology ?? false);
|
|
6182
6259
|
const [timelineExpanded, setTimelineExpanded] = useState14(defaultExpanded?.timeline ?? false);
|
|
6183
6260
|
useEffect11(() => {
|
|
@@ -6213,6 +6290,21 @@ function ExplainableShell({
|
|
|
6213
6290
|
}, [drillDownStack, snapshots]);
|
|
6214
6291
|
const activeSnapshots = currentLevel.snapshots;
|
|
6215
6292
|
const safeIdx = activeSnapshots.length > 0 ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1)) : 0;
|
|
6293
|
+
const shellDataTrace = useMemo12(
|
|
6294
|
+
() => runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, activeSnapshots[safeIdx]?.runtimeStageId ?? "") : { frames: [], readsAvailable: true },
|
|
6295
|
+
[runtimeSnapshot, activeSnapshots, safeIdx]
|
|
6296
|
+
);
|
|
6297
|
+
const sliceCone = useMemo12(() => {
|
|
6298
|
+
if (rightPanelMode !== "what" || inspectorTab !== "trace") return void 0;
|
|
6299
|
+
if (shellDataTrace.frames.length < 2) return void 0;
|
|
6300
|
+
const cone = /* @__PURE__ */ new Map();
|
|
6301
|
+
for (const f of shellDataTrace.frames) {
|
|
6302
|
+
const stagePart = f.runtimeStageId.split("#")[0];
|
|
6303
|
+
const prev = cone.get(stagePart);
|
|
6304
|
+
if (prev === void 0 || f.depth < prev) cone.set(stagePart, f.depth);
|
|
6305
|
+
}
|
|
6306
|
+
return cone;
|
|
6307
|
+
}, [rightPanelMode, inspectorTab, shellDataTrace]);
|
|
6216
6308
|
const activeNarrativeEntries = isInSubflow ? currentLevel.narrative : narrativeEntries;
|
|
6217
6309
|
const breadcrumbs = useMemo12(() => {
|
|
6218
6310
|
const root = { label: title || "Flowchart", spec: null, description: void 0 };
|
|
@@ -6296,7 +6388,7 @@ function ExplainableShell({
|
|
|
6296
6388
|
(activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ jsxs23(Fragment6, { children: [
|
|
6297
6389
|
/* @__PURE__ */ jsx26(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true }),
|
|
6298
6390
|
isInSubflow && /* @__PURE__ */ jsx26(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
|
|
6299
|
-
traceGraph && effectiveRenderFlowchart?.({ spec: null, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId }),
|
|
6391
|
+
traceGraph && effectiveRenderFlowchart?.({ spec: null, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId, ...sliceCone && { sliceCone } }),
|
|
6300
6392
|
/* @__PURE__ */ jsx26(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
|
|
6301
6393
|
/* @__PURE__ */ jsx26(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
|
|
6302
6394
|
/* @__PURE__ */ jsx26(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
|
|
@@ -6369,12 +6461,22 @@ function ExplainableShell({
|
|
|
6369
6461
|
}) }),
|
|
6370
6462
|
/* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
|
|
6371
6463
|
] });
|
|
6464
|
+
const shellThemeVars = useMemo12(() => {
|
|
6465
|
+
if (!traceTheme) return {};
|
|
6466
|
+
const base = traceTheme.mode ? tokensToCSSVars(traceTheme.mode === "light" ? coolLight : coolDark) : {};
|
|
6467
|
+
return {
|
|
6468
|
+
...base,
|
|
6469
|
+
...traceTheme.visited !== void 0 && { ["--fp-node-visited"]: traceTheme.visited },
|
|
6470
|
+
...traceTheme.current !== void 0 && { ["--fp-node-cursor"]: traceTheme.current }
|
|
6471
|
+
};
|
|
6472
|
+
}, [traceTheme]);
|
|
6372
6473
|
return /* @__PURE__ */ jsxs23(
|
|
6373
6474
|
"div",
|
|
6374
6475
|
{
|
|
6375
6476
|
ref: shellRef,
|
|
6376
6477
|
className,
|
|
6377
6478
|
style: {
|
|
6479
|
+
...shellThemeVars,
|
|
6378
6480
|
height: "100%",
|
|
6379
6481
|
display: "flex",
|
|
6380
6482
|
flexDirection: "column",
|
|
@@ -6405,7 +6507,8 @@ function ExplainableShell({
|
|
|
6405
6507
|
snapshots: activeSnapshots,
|
|
6406
6508
|
selectedIndex: safeIdx,
|
|
6407
6509
|
onNodeClick: handleNodeClick,
|
|
6408
|
-
showStageId
|
|
6510
|
+
showStageId,
|
|
6511
|
+
...sliceCone && { sliceCone }
|
|
6409
6512
|
}) }),
|
|
6410
6513
|
showTreeSidebar && /* @__PURE__ */ jsxs23(Fragment6, { children: [
|
|
6411
6514
|
/* @__PURE__ */ jsx26(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
|
|
@@ -6445,7 +6548,8 @@ function ExplainableShell({
|
|
|
6445
6548
|
snapshots: activeSnapshots,
|
|
6446
6549
|
selectedIndex: safeIdx,
|
|
6447
6550
|
onNodeClick: handleNodeClick,
|
|
6448
|
-
showStageId
|
|
6551
|
+
showStageId,
|
|
6552
|
+
...sliceCone && { sliceCone }
|
|
6449
6553
|
}) }) : /* @__PURE__ */ jsx26("div", { style: { flex: 1 } }),
|
|
6450
6554
|
/* @__PURE__ */ jsx26(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
|
|
6451
6555
|
rightExpanded && /* @__PURE__ */ jsx26("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsx26(
|
|
@@ -6453,6 +6557,8 @@ function ExplainableShell({
|
|
|
6453
6557
|
{
|
|
6454
6558
|
mode: rightPanelMode,
|
|
6455
6559
|
onModeChange: setRightPanelMode,
|
|
6560
|
+
dataTrace: shellDataTrace,
|
|
6561
|
+
onInspectorTabChange: setInspectorTab,
|
|
6456
6562
|
snapshots: activeSnapshots,
|
|
6457
6563
|
selectedIndex: safeIdx,
|
|
6458
6564
|
runtimeSnapshot,
|