footprint-explainable-ui 0.17.0 → 0.18.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/index.cjs CHANGED
@@ -2361,13 +2361,20 @@ function extractStageTimings(recorders) {
2361
2361
  const timings = /* @__PURE__ */ new Map();
2362
2362
  if (!recorders) return timings;
2363
2363
  for (const rec of recorders) {
2364
- if (rec.name === "Metrics" && rec.data && typeof rec.data === "object") {
2365
- const data = rec.data;
2366
- if (data.stages) {
2367
- for (const [stageName, metrics] of Object.entries(data.stages)) {
2368
- if (typeof metrics.totalDuration === "number" && metrics.totalDuration > 0) {
2369
- timings.set(stageName, Math.round(metrics.totalDuration));
2370
- }
2364
+ if (rec.name !== "Metrics" || !rec.data || typeof rec.data !== "object") continue;
2365
+ const data = rec.data;
2366
+ if (data.steps) {
2367
+ for (const step of Object.values(data.steps)) {
2368
+ const name = step?.stageName;
2369
+ const d = step?.duration;
2370
+ if (!name || typeof d !== "number" || d <= 0) continue;
2371
+ timings.set(name, Math.round((timings.get(name) ?? 0) + d));
2372
+ }
2373
+ }
2374
+ if (data.stages) {
2375
+ for (const [stageName, metrics] of Object.entries(data.stages)) {
2376
+ if (typeof metrics.totalDuration === "number" && metrics.totalDuration > 0) {
2377
+ timings.set(stageName, Math.round(metrics.totalDuration));
2371
2378
  }
2372
2379
  }
2373
2380
  }
@@ -2739,11 +2746,37 @@ function StoryNarrative({
2739
2746
 
2740
2747
  // src/components/NarrativePanel/NarrativePanel.tsx
2741
2748
  var import_jsx_runtime13 = require("react/jsx-runtime");
2749
+ function safeJsonStringify(value) {
2750
+ const seen = /* @__PURE__ */ new WeakSet();
2751
+ const MAX_CHARS = 5e5;
2752
+ try {
2753
+ let text = JSON.stringify(
2754
+ value,
2755
+ (_key, v2) => {
2756
+ if (typeof v2 === "object" && v2 !== null) {
2757
+ if (seen.has(v2)) return "[Circular]";
2758
+ seen.add(v2);
2759
+ }
2760
+ return v2;
2761
+ },
2762
+ 2
2763
+ );
2764
+ if (text && text.length > MAX_CHARS) {
2765
+ text = text.slice(0, MAX_CHARS) + `
2766
+ ... [truncated at ${MAX_CHARS} chars]`;
2767
+ }
2768
+ return text ?? "undefined";
2769
+ } catch (err) {
2770
+ return `[stringify error: ${err instanceof Error ? err.message : String(err)}]`;
2771
+ }
2772
+ }
2742
2773
  function NarrativePanel({
2743
2774
  snapshots,
2744
2775
  selectedIndex,
2745
2776
  narrativeEntries,
2746
2777
  narrative: narrativeProp,
2778
+ runtimeSnapshot,
2779
+ spec,
2747
2780
  size = "default",
2748
2781
  unstyled = false,
2749
2782
  className,
@@ -2852,8 +2885,53 @@ function NarrativePanel({
2852
2885
  sections.push("");
2853
2886
  }
2854
2887
  }
2888
+ if (runtimeSnapshot) {
2889
+ const snap = runtimeSnapshot;
2890
+ if (snap.sharedState !== void 0) {
2891
+ sections.push("\n\n## Final Shared State");
2892
+ sections.push("```json");
2893
+ sections.push(safeJsonStringify(snap.sharedState));
2894
+ sections.push("```");
2895
+ }
2896
+ if (Array.isArray(snap.commitLog) && snap.commitLog.length > 0) {
2897
+ sections.push("\n\n## Commit Log");
2898
+ sections.push(
2899
+ "Each entry = one stage execution's writes to shared state. `rsid` is the runtimeStageId (use it to correlate with narrative + executionTree).\n"
2900
+ );
2901
+ sections.push("```json");
2902
+ sections.push(safeJsonStringify(snap.commitLog));
2903
+ sections.push("```");
2904
+ }
2905
+ if (snap.recorders && typeof snap.recorders === "object") {
2906
+ sections.push("\n\n## Recorder Snapshots");
2907
+ sections.push(
2908
+ "Per-recorder data captured DURING the run (metrics, tokens, instructions, emit events).\n"
2909
+ );
2910
+ sections.push("```json");
2911
+ sections.push(safeJsonStringify(snap.recorders));
2912
+ sections.push("```");
2913
+ }
2914
+ if (snap.subflowResults && typeof snap.subflowResults === "object") {
2915
+ const keys = Object.keys(snap.subflowResults);
2916
+ if (keys.length > 0) {
2917
+ sections.push("\n\n## Subflow Results");
2918
+ sections.push("```json");
2919
+ sections.push(safeJsonStringify(snap.subflowResults));
2920
+ sections.push("```");
2921
+ }
2922
+ }
2923
+ }
2924
+ if (spec) {
2925
+ sections.push("\n\n## Flowchart Spec (topology)");
2926
+ sections.push(
2927
+ "Node + edge metadata for the chart that ran. Useful for 'where in the graph did step N happen?' questions.\n"
2928
+ );
2929
+ sections.push("```json");
2930
+ sections.push(safeJsonStringify(spec));
2931
+ sections.push("```");
2932
+ }
2855
2933
  return sections.join("\n");
2856
- }, [narrativeEntries, narrative]);
2934
+ }, [narrativeEntries, narrative, runtimeSnapshot, spec]);
2857
2935
  const handleCopy = (0, import_react12.useCallback)(async () => {
2858
2936
  const text = buildLLMNarrative();
2859
2937
  await navigator.clipboard.writeText(text);
@@ -4889,6 +4967,7 @@ var RightPanel = (0, import_react24.memo)(function RightPanel2({
4889
4967
  snapshots,
4890
4968
  selectedIndex,
4891
4969
  runtimeSnapshot,
4970
+ spec,
4892
4971
  activeTab,
4893
4972
  allTabs,
4894
4973
  activeNarrativeEntries,
@@ -4935,7 +5014,7 @@ var RightPanel = (0, import_react24.memo)(function RightPanel2({
4935
5014
  id: tab.id,
4936
5015
  name: insightName(tab.name),
4937
5016
  render: () => {
4938
- if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, narrative: activeNarrative, size, style: { height: "100%" } });
5017
+ if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, narrative: activeNarrative, runtimeSnapshot, spec, size, style: { height: "100%" } });
4939
5018
  const customView = recorderViews?.find((v2) => v2.id === tab.id);
4940
5019
  if (customView?.render) return customView.render({ snapshots, selectedIndex });
4941
5020
  const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
@@ -5350,6 +5429,7 @@ function ExplainableShell({
5350
5429
  snapshots: activeSnapshots,
5351
5430
  selectedIndex: safeIdx,
5352
5431
  runtimeSnapshot,
5432
+ spec,
5353
5433
  activeTab,
5354
5434
  allTabs,
5355
5435
  activeNarrativeEntries,