@almadar/ui 2.27.5 → 2.28.1

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.
@@ -33573,6 +33573,119 @@ function EventDispatcherTab({ traits: traits2, schema }) {
33573
33573
  ] });
33574
33574
  }
33575
33575
  EventDispatcherTab.displayName = "EventDispatcherTab";
33576
+ function ServerResponseRow({ sr }) {
33577
+ const entityEntries = Object.entries(sr.dataEntities);
33578
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-4 pl-2 border-l border-purple-700/50 py-0.5 text-[10px] font-mono", children: [
33579
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
33580
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: sr.success ? "text-green-400" : "text-red-400", children: [
33581
+ sr.success ? "\u2713" : "\u2717",
33582
+ " server"
33583
+ ] }),
33584
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-300", children: sr.orbitalName }),
33585
+ sr.clientEffects > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 rounded bg-purple-900/50 text-purple-300", children: [
33586
+ sr.clientEffects,
33587
+ " clientEffect",
33588
+ sr.clientEffects !== 1 ? "s" : ""
33589
+ ] }),
33590
+ sr.emittedEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 rounded bg-blue-900/50 text-blue-300", children: [
33591
+ "emit: ",
33592
+ sr.emittedEvents.join(", ")
33593
+ ] }),
33594
+ sr.error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 rounded bg-red-900/50 text-red-400 truncate max-w-[300px]", children: sr.error })
33595
+ ] }),
33596
+ entityEntries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 mt-0.5", children: entityEntries.map(([name, count]) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 rounded bg-gray-800 text-gray-300", children: [
33597
+ name,
33598
+ ": ",
33599
+ count,
33600
+ " row",
33601
+ count !== 1 ? "s" : ""
33602
+ ] }, name)) })
33603
+ ] });
33604
+ }
33605
+ function TransitionRow({ trace }) {
33606
+ const isServerEntry = !!trace.serverResponse && trace.traitName.startsWith("server:");
33607
+ const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
33608
+ if (isServerEntry && trace.serverResponse) {
33609
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
33610
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
33611
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 bg-purple-500" }),
33612
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "warning", size: "sm", className: "flex-shrink-0", children: trace.event }),
33613
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400 flex-shrink-0", children: "server response" })
33614
+ ] }),
33615
+ /* @__PURE__ */ jsxRuntime.jsx(ServerResponseRow, { sr: trace.serverResponse })
33616
+ ] });
33617
+ }
33618
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
33619
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
33620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
33621
+ "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
33622
+ hasFailedEffects ? "bg-red-500" : "bg-green-500"
33623
+ ) }),
33624
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
33625
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300 flex-shrink-0", children: trace.traitName }),
33626
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
33627
+ trace.from,
33628
+ " ",
33629
+ "\u2192",
33630
+ " ",
33631
+ trace.to
33632
+ ] })
33633
+ ] }),
33634
+ trace.effects.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 ml-6 mt-0.5", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
33635
+ "px-1 rounded text-[10px]",
33636
+ eff.status === "executed" ? "bg-green-900/50 text-green-400" : eff.status === "failed" ? "bg-red-900/50 text-red-400" : "bg-yellow-900/50 text-yellow-400"
33637
+ ), children: [
33638
+ eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
33639
+ " ",
33640
+ eff.type,
33641
+ eff.args.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 40) })
33642
+ ] }, i)) }),
33643
+ trace.serverResponse && /* @__PURE__ */ jsxRuntime.jsx(ServerResponseRow, { sr: trace.serverResponse })
33644
+ ] });
33645
+ }
33646
+ function VerifyModePanel({
33647
+ className,
33648
+ failedChecks,
33649
+ transitions,
33650
+ traitStates,
33651
+ serverCount,
33652
+ localCount
33653
+ }) {
33654
+ const scrollRef = React91__namespace.useRef(null);
33655
+ const prevCountRef = React91__namespace.useRef(0);
33656
+ React91__namespace.useEffect(() => {
33657
+ if (transitions.length > prevCountRef.current && scrollRef.current) {
33658
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
33659
+ }
33660
+ prevCountRef.current = transitions.length;
33661
+ }, [transitions.length]);
33662
+ return /* @__PURE__ */ jsxRuntime.jsxs(
33663
+ "div",
33664
+ {
33665
+ className: cn(
33666
+ "runtime-debugger runtime-debugger--verify",
33667
+ "fixed bottom-0 left-0 right-0 z-[9999] h-[35vh] flex flex-col bg-gray-900 text-white border-t-2 border-cyan-500",
33668
+ className
33669
+ ),
33670
+ "data-testid": "debugger-verify",
33671
+ children: [
33672
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 flex items-center gap-3 text-xs font-mono border-b border-gray-700 flex-shrink-0", children: [
33673
+ /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
33674
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400", children: [
33675
+ localCount,
33676
+ " local"
33677
+ ] }),
33678
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-400", children: [
33679
+ serverCount,
33680
+ " server"
33681
+ ] }),
33682
+ traitStates && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
33683
+ ] }),
33684
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1", children: transitions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 text-xs font-mono py-2 text-center", children: "Waiting for transitions..." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: transitions.map((trace) => /* @__PURE__ */ jsxRuntime.jsx(TransitionRow, { trace }, trace.id)) }) }) })
33685
+ ]
33686
+ }
33687
+ );
33688
+ }
33576
33689
  function RuntimeDebugger({
33577
33690
  position = "bottom-right",
33578
33691
  defaultCollapsed = true,
@@ -33722,51 +33835,17 @@ function RuntimeDebugger({
33722
33835
  }
33723
33836
  if (mode === "verify") {
33724
33837
  const traitStates = debugData.traits.map((t) => `${t.name}:${t.currentState}`).join(" | ");
33725
- return /* @__PURE__ */ jsxRuntime.jsxs(
33726
- "div",
33838
+ const serverEntries = verification.transitions.filter((t) => t.serverResponse);
33839
+ const localEntries = verification.transitions.filter((t) => !t.serverResponse);
33840
+ return /* @__PURE__ */ jsxRuntime.jsx(
33841
+ VerifyModePanel,
33727
33842
  {
33728
- className: cn(
33729
- "runtime-debugger runtime-debugger--verify",
33730
- "fixed bottom-0 left-0 right-0 z-[9999] h-[35vh] flex flex-col bg-gray-900 text-white border-t-2 border-cyan-500",
33731
- className
33732
- ),
33733
- "data-testid": "debugger-verify",
33734
- children: [
33735
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 flex items-center gap-3 text-xs font-mono border-b border-gray-700 flex-shrink-0", children: [
33736
- /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
33737
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400", children: [
33738
- verification.transitions.length,
33739
- " transitions"
33740
- ] }),
33741
- traitStates && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
33742
- ] }),
33743
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1", children: verification.transitions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 text-xs font-mono py-2 text-center", children: "Waiting for transitions..." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: verification.transitions.map((trace) => {
33744
- const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
33745
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs font-mono py-0.5 border-b border-gray-800 last:border-0", children: [
33746
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
33747
- "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
33748
- hasFailedEffects ? "bg-red-500" : "bg-green-500"
33749
- ) }),
33750
- /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
33751
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
33752
- trace.from,
33753
- " ",
33754
- "\u2192",
33755
- " ",
33756
- trace.to
33757
- ] }),
33758
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap gap-1 ml-1", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
33759
- "px-1 rounded text-[10px]",
33760
- eff.status === "executed" ? "bg-green-900/50 text-green-400" : eff.status === "failed" ? "bg-red-900/50 text-red-400" : "bg-yellow-900/50 text-yellow-400"
33761
- ), children: [
33762
- eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
33763
- " ",
33764
- eff.type,
33765
- eff.args.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 30) })
33766
- ] }, i)) })
33767
- ] }, trace.id);
33768
- }) }) }) })
33769
- ]
33843
+ className,
33844
+ failedChecks,
33845
+ transitions: verification.transitions,
33846
+ traitStates,
33847
+ serverCount: serverEntries.length,
33848
+ localCount: localEntries.length
33770
33849
  }
33771
33850
  );
33772
33851
  }
@@ -33543,6 +33543,119 @@ function EventDispatcherTab({ traits: traits2, schema }) {
33543
33543
  ] });
33544
33544
  }
33545
33545
  EventDispatcherTab.displayName = "EventDispatcherTab";
33546
+ function ServerResponseRow({ sr }) {
33547
+ const entityEntries = Object.entries(sr.dataEntities);
33548
+ return /* @__PURE__ */ jsxs("div", { className: "ml-4 pl-2 border-l border-purple-700/50 py-0.5 text-[10px] font-mono", children: [
33549
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
33550
+ /* @__PURE__ */ jsxs("span", { className: sr.success ? "text-green-400" : "text-red-400", children: [
33551
+ sr.success ? "\u2713" : "\u2717",
33552
+ " server"
33553
+ ] }),
33554
+ /* @__PURE__ */ jsx("span", { className: "text-purple-300", children: sr.orbitalName }),
33555
+ sr.clientEffects > 0 && /* @__PURE__ */ jsxs("span", { className: "px-1 rounded bg-purple-900/50 text-purple-300", children: [
33556
+ sr.clientEffects,
33557
+ " clientEffect",
33558
+ sr.clientEffects !== 1 ? "s" : ""
33559
+ ] }),
33560
+ sr.emittedEvents.length > 0 && /* @__PURE__ */ jsxs("span", { className: "px-1 rounded bg-blue-900/50 text-blue-300", children: [
33561
+ "emit: ",
33562
+ sr.emittedEvents.join(", ")
33563
+ ] }),
33564
+ sr.error && /* @__PURE__ */ jsx("span", { className: "px-1 rounded bg-red-900/50 text-red-400 truncate max-w-[300px]", children: sr.error })
33565
+ ] }),
33566
+ entityEntries.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 mt-0.5", children: entityEntries.map(([name, count]) => /* @__PURE__ */ jsxs("span", { className: "px-1 rounded bg-gray-800 text-gray-300", children: [
33567
+ name,
33568
+ ": ",
33569
+ count,
33570
+ " row",
33571
+ count !== 1 ? "s" : ""
33572
+ ] }, name)) })
33573
+ ] });
33574
+ }
33575
+ function TransitionRow({ trace }) {
33576
+ const isServerEntry = !!trace.serverResponse && trace.traitName.startsWith("server:");
33577
+ const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
33578
+ if (isServerEntry && trace.serverResponse) {
33579
+ return /* @__PURE__ */ jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
33580
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
33581
+ /* @__PURE__ */ jsx("span", { className: "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 bg-purple-500" }),
33582
+ /* @__PURE__ */ jsx(Badge, { variant: "warning", size: "sm", className: "flex-shrink-0", children: trace.event }),
33583
+ /* @__PURE__ */ jsx("span", { className: "text-purple-400 flex-shrink-0", children: "server response" })
33584
+ ] }),
33585
+ /* @__PURE__ */ jsx(ServerResponseRow, { sr: trace.serverResponse })
33586
+ ] });
33587
+ }
33588
+ return /* @__PURE__ */ jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
33589
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
33590
+ /* @__PURE__ */ jsx("span", { className: cn(
33591
+ "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
33592
+ hasFailedEffects ? "bg-red-500" : "bg-green-500"
33593
+ ) }),
33594
+ /* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
33595
+ /* @__PURE__ */ jsx("span", { className: "text-gray-300 flex-shrink-0", children: trace.traitName }),
33596
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
33597
+ trace.from,
33598
+ " ",
33599
+ "\u2192",
33600
+ " ",
33601
+ trace.to
33602
+ ] })
33603
+ ] }),
33604
+ trace.effects.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 ml-6 mt-0.5", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxs("span", { className: cn(
33605
+ "px-1 rounded text-[10px]",
33606
+ eff.status === "executed" ? "bg-green-900/50 text-green-400" : eff.status === "failed" ? "bg-red-900/50 text-red-400" : "bg-yellow-900/50 text-yellow-400"
33607
+ ), children: [
33608
+ eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
33609
+ " ",
33610
+ eff.type,
33611
+ eff.args.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 40) })
33612
+ ] }, i)) }),
33613
+ trace.serverResponse && /* @__PURE__ */ jsx(ServerResponseRow, { sr: trace.serverResponse })
33614
+ ] });
33615
+ }
33616
+ function VerifyModePanel({
33617
+ className,
33618
+ failedChecks,
33619
+ transitions,
33620
+ traitStates,
33621
+ serverCount,
33622
+ localCount
33623
+ }) {
33624
+ const scrollRef = React91.useRef(null);
33625
+ const prevCountRef = React91.useRef(0);
33626
+ React91.useEffect(() => {
33627
+ if (transitions.length > prevCountRef.current && scrollRef.current) {
33628
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
33629
+ }
33630
+ prevCountRef.current = transitions.length;
33631
+ }, [transitions.length]);
33632
+ return /* @__PURE__ */ jsxs(
33633
+ "div",
33634
+ {
33635
+ className: cn(
33636
+ "runtime-debugger runtime-debugger--verify",
33637
+ "fixed bottom-0 left-0 right-0 z-[9999] h-[35vh] flex flex-col bg-gray-900 text-white border-t-2 border-cyan-500",
33638
+ className
33639
+ ),
33640
+ "data-testid": "debugger-verify",
33641
+ children: [
33642
+ /* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 flex items-center gap-3 text-xs font-mono border-b border-gray-700 flex-shrink-0", children: [
33643
+ /* @__PURE__ */ jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
33644
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
33645
+ localCount,
33646
+ " local"
33647
+ ] }),
33648
+ /* @__PURE__ */ jsxs("span", { className: "text-purple-400", children: [
33649
+ serverCount,
33650
+ " server"
33651
+ ] }),
33652
+ traitStates && /* @__PURE__ */ jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
33653
+ ] }),
33654
+ /* @__PURE__ */ jsx("div", { ref: scrollRef, className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx("div", { className: "px-2 py-1", children: transitions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-gray-500 text-xs font-mono py-2 text-center", children: "Waiting for transitions..." }) : /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: transitions.map((trace) => /* @__PURE__ */ jsx(TransitionRow, { trace }, trace.id)) }) }) })
33655
+ ]
33656
+ }
33657
+ );
33658
+ }
33546
33659
  function RuntimeDebugger({
33547
33660
  position = "bottom-right",
33548
33661
  defaultCollapsed = true,
@@ -33692,51 +33805,17 @@ function RuntimeDebugger({
33692
33805
  }
33693
33806
  if (mode === "verify") {
33694
33807
  const traitStates = debugData.traits.map((t) => `${t.name}:${t.currentState}`).join(" | ");
33695
- return /* @__PURE__ */ jsxs(
33696
- "div",
33808
+ const serverEntries = verification.transitions.filter((t) => t.serverResponse);
33809
+ const localEntries = verification.transitions.filter((t) => !t.serverResponse);
33810
+ return /* @__PURE__ */ jsx(
33811
+ VerifyModePanel,
33697
33812
  {
33698
- className: cn(
33699
- "runtime-debugger runtime-debugger--verify",
33700
- "fixed bottom-0 left-0 right-0 z-[9999] h-[35vh] flex flex-col bg-gray-900 text-white border-t-2 border-cyan-500",
33701
- className
33702
- ),
33703
- "data-testid": "debugger-verify",
33704
- children: [
33705
- /* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 flex items-center gap-3 text-xs font-mono border-b border-gray-700 flex-shrink-0", children: [
33706
- /* @__PURE__ */ jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
33707
- /* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
33708
- verification.transitions.length,
33709
- " transitions"
33710
- ] }),
33711
- traitStates && /* @__PURE__ */ jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
33712
- ] }),
33713
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx("div", { className: "px-2 py-1", children: verification.transitions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-gray-500 text-xs font-mono py-2 text-center", children: "Waiting for transitions..." }) : /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: verification.transitions.map((trace) => {
33714
- const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
33715
- return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-xs font-mono py-0.5 border-b border-gray-800 last:border-0", children: [
33716
- /* @__PURE__ */ jsx("span", { className: cn(
33717
- "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
33718
- hasFailedEffects ? "bg-red-500" : "bg-green-500"
33719
- ) }),
33720
- /* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
33721
- /* @__PURE__ */ jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
33722
- trace.from,
33723
- " ",
33724
- "\u2192",
33725
- " ",
33726
- trace.to
33727
- ] }),
33728
- /* @__PURE__ */ jsx("span", { className: "flex flex-wrap gap-1 ml-1", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxs("span", { className: cn(
33729
- "px-1 rounded text-[10px]",
33730
- eff.status === "executed" ? "bg-green-900/50 text-green-400" : eff.status === "failed" ? "bg-red-900/50 text-red-400" : "bg-yellow-900/50 text-yellow-400"
33731
- ), children: [
33732
- eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
33733
- " ",
33734
- eff.type,
33735
- eff.args.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 30) })
33736
- ] }, i)) })
33737
- ] }, trace.id);
33738
- }) }) }) })
33739
- ]
33813
+ className,
33814
+ failedChecks,
33815
+ transitions: verification.transitions,
33816
+ traitStates,
33817
+ serverCount: serverEntries.length,
33818
+ localCount: localEntries.length
33740
33819
  }
33741
33820
  );
33742
33821
  }
@@ -513,6 +513,36 @@ function getTransitions() {
513
513
  function getTransitionsForTrait(traitName) {
514
514
  return getState().transitions.filter((t) => t.traitName === traitName);
515
515
  }
516
+ function recordServerResponse(orbitalName, event, response) {
517
+ const serverResponse = {
518
+ ...response,
519
+ orbitalName,
520
+ timestamp: Date.now()
521
+ };
522
+ const entry = {
523
+ id: `srv-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
524
+ traitName: `server:${orbitalName}`,
525
+ from: "server",
526
+ to: "server",
527
+ event,
528
+ effects: [],
529
+ serverResponse,
530
+ timestamp: Date.now()
531
+ };
532
+ getState().transitions.push(entry);
533
+ if (getState().transitions.length > MAX_TRANSITIONS) {
534
+ getState().transitions.shift();
535
+ }
536
+ if (!response.success && response.error) {
537
+ registerCheck(
538
+ `server-error-${entry.id}`,
539
+ `Server error for ${orbitalName}:${event}`,
540
+ "fail",
541
+ response.error
542
+ );
543
+ }
544
+ notifyListeners5();
545
+ }
516
546
  function updateBridgeHealth(health) {
517
547
  getState().bridgeHealth = { ...health };
518
548
  const checkId = "server-bridge";
@@ -1482,6 +1512,7 @@ exports.onDebugToggle = onDebugToggle;
1482
1512
  exports.parseContentSegments = parseContentSegments;
1483
1513
  exports.parseMarkdownWithCodeBlocks = parseMarkdownWithCodeBlocks;
1484
1514
  exports.recordGuardEvaluation = recordGuardEvaluation;
1515
+ exports.recordServerResponse = recordServerResponse;
1485
1516
  exports.recordTransition = recordTransition;
1486
1517
  exports.registerCheck = registerCheck;
1487
1518
  exports.registerTick = registerTick;
package/dist/lib/index.js CHANGED
@@ -511,6 +511,36 @@ function getTransitions() {
511
511
  function getTransitionsForTrait(traitName) {
512
512
  return getState().transitions.filter((t) => t.traitName === traitName);
513
513
  }
514
+ function recordServerResponse(orbitalName, event, response) {
515
+ const serverResponse = {
516
+ ...response,
517
+ orbitalName,
518
+ timestamp: Date.now()
519
+ };
520
+ const entry = {
521
+ id: `srv-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
522
+ traitName: `server:${orbitalName}`,
523
+ from: "server",
524
+ to: "server",
525
+ event,
526
+ effects: [],
527
+ serverResponse,
528
+ timestamp: Date.now()
529
+ };
530
+ getState().transitions.push(entry);
531
+ if (getState().transitions.length > MAX_TRANSITIONS) {
532
+ getState().transitions.shift();
533
+ }
534
+ if (!response.success && response.error) {
535
+ registerCheck(
536
+ `server-error-${entry.id}`,
537
+ `Server error for ${orbitalName}:${event}`,
538
+ "fail",
539
+ response.error
540
+ );
541
+ }
542
+ notifyListeners5();
543
+ }
514
544
  function updateBridgeHealth(health) {
515
545
  getState().bridgeHealth = { ...health };
516
546
  const checkId = "server-bridge";
@@ -1416,4 +1446,4 @@ function parseContentSegments(content) {
1416
1446
  return segments;
1417
1447
  }
1418
1448
 
1419
- export { ApiError, DEFAULT_CONFIG, apiClient, bindCanvasCapture, bindEventBus, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, recordGuardEvaluation, recordTransition, registerCheck, registerTick, registerTrait, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
1449
+ export { ApiError, DEFAULT_CONFIG, apiClient, bindCanvasCapture, bindEventBus, bindTraitStateGetter, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, extractOutputsFromTransitions, extractStateMachine, formatGuard, formatNestedFieldLabel, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTransitions, getTransitionsForTrait, initDebugShortcut, isDebugEnabled, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
@@ -25,6 +25,16 @@ export interface EffectTrace {
25
25
  error?: string;
26
26
  durationMs?: number;
27
27
  }
28
+ /** Captures what the server returned for a given event */
29
+ export interface ServerResponseTrace {
30
+ orbitalName: string;
31
+ success: boolean;
32
+ clientEffects: number;
33
+ dataEntities: Record<string, number>;
34
+ emittedEvents: string[];
35
+ error?: string;
36
+ timestamp: number;
37
+ }
28
38
  export interface TransitionTrace {
29
39
  id: string;
30
40
  traitName: string;
@@ -34,6 +44,8 @@ export interface TransitionTrace {
34
44
  guardExpression?: string;
35
45
  guardResult?: boolean;
36
46
  effects: EffectTrace[];
47
+ /** Server response data when event was forwarded to server bridge */
48
+ serverResponse?: ServerResponseTrace;
37
49
  timestamp: number;
38
50
  }
39
51
  export interface BridgeHealth {
@@ -63,6 +75,12 @@ export declare function getAllChecks(): VerificationCheck[];
63
75
  export declare function recordTransition(trace: Omit<TransitionTrace, "id">): void;
64
76
  export declare function getTransitions(): TransitionTrace[];
65
77
  export declare function getTransitionsForTrait(traitName: string): TransitionTrace[];
78
+ /**
79
+ * Record a server response as a timeline entry.
80
+ * Creates a synthetic transition entry with type "server-response" to show
81
+ * what the server returned (clientEffects, data counts, emitted events).
82
+ */
83
+ export declare function recordServerResponse(orbitalName: string, event: string, response: Omit<ServerResponseTrace, "orbitalName" | "timestamp">): void;
66
84
  export declare function updateBridgeHealth(health: BridgeHealth): void;
67
85
  export declare function getBridgeHealth(): BridgeHealth | null;
68
86
  export declare function getSummary(): VerificationSummary;
@@ -3411,17 +3411,42 @@ function VerificationProvider({
3411
3411
  const pending = pendingRef.current.get(key);
3412
3412
  pendingRef.current.delete(key);
3413
3413
  const newState = payload["newState"] ?? payload["state"] ?? "unknown";
3414
- const effects = Array.isArray(payload["clientEffects"]) ? payload["clientEffects"].map((e) => ({
3414
+ const clientEffectsArr = Array.isArray(payload["clientEffects"]) ? payload["clientEffects"] : [];
3415
+ const effects = clientEffectsArr.map((e) => ({
3415
3416
  type: String(e["type"] ?? "unknown"),
3416
3417
  args: Array.isArray(e["args"]) ? e["args"] : [],
3417
3418
  status: "executed"
3418
- })) : [];
3419
+ }));
3420
+ const effectResults = Array.isArray(payload["effectResults"]) ? payload["effectResults"] : [];
3421
+ for (const er of effectResults) {
3422
+ effects.push({
3423
+ type: String(er["type"] ?? er["effect"] ?? "server-effect"),
3424
+ args: [er["entity"] ?? er["service"] ?? ""].filter(Boolean),
3425
+ status: er["error"] ? "failed" : "executed",
3426
+ error: er["error"]
3427
+ });
3428
+ }
3429
+ const dataEntities = {};
3430
+ const responseData = payload["data"];
3431
+ if (responseData && typeof responseData === "object") {
3432
+ for (const [entityName, records] of Object.entries(responseData)) {
3433
+ dataEntities[entityName] = Array.isArray(records) ? records.length : 0;
3434
+ }
3435
+ }
3419
3436
  recordTransition({
3420
3437
  traitName: parsed.traitName,
3421
3438
  from: pending?.from ?? payload["currentState"] ?? newState,
3422
3439
  to: newState,
3423
3440
  event: parsed.event,
3424
3441
  effects,
3442
+ serverResponse: {
3443
+ orbitalName: parsed.traitName,
3444
+ success: true,
3445
+ clientEffects: clientEffectsArr.length,
3446
+ dataEntities,
3447
+ emittedEvents: [],
3448
+ timestamp: Date.now()
3449
+ },
3425
3450
  timestamp: Date.now()
3426
3451
  });
3427
3452
  } else if (parsed.kind === "error" && parsed.event) {
@@ -3442,6 +3467,15 @@ function VerificationProvider({
3442
3467
  status: "failed",
3443
3468
  error: errorMsg
3444
3469
  }],
3470
+ serverResponse: {
3471
+ orbitalName: parsed.traitName,
3472
+ success: false,
3473
+ clientEffects: 0,
3474
+ dataEntities: {},
3475
+ emittedEvents: [],
3476
+ error: errorMsg,
3477
+ timestamp: Date.now()
3478
+ },
3445
3479
  timestamp: Date.now()
3446
3480
  });
3447
3481
  }
@@ -3381,17 +3381,42 @@ function VerificationProvider({
3381
3381
  const pending = pendingRef.current.get(key);
3382
3382
  pendingRef.current.delete(key);
3383
3383
  const newState = payload["newState"] ?? payload["state"] ?? "unknown";
3384
- const effects = Array.isArray(payload["clientEffects"]) ? payload["clientEffects"].map((e) => ({
3384
+ const clientEffectsArr = Array.isArray(payload["clientEffects"]) ? payload["clientEffects"] : [];
3385
+ const effects = clientEffectsArr.map((e) => ({
3385
3386
  type: String(e["type"] ?? "unknown"),
3386
3387
  args: Array.isArray(e["args"]) ? e["args"] : [],
3387
3388
  status: "executed"
3388
- })) : [];
3389
+ }));
3390
+ const effectResults = Array.isArray(payload["effectResults"]) ? payload["effectResults"] : [];
3391
+ for (const er of effectResults) {
3392
+ effects.push({
3393
+ type: String(er["type"] ?? er["effect"] ?? "server-effect"),
3394
+ args: [er["entity"] ?? er["service"] ?? ""].filter(Boolean),
3395
+ status: er["error"] ? "failed" : "executed",
3396
+ error: er["error"]
3397
+ });
3398
+ }
3399
+ const dataEntities = {};
3400
+ const responseData = payload["data"];
3401
+ if (responseData && typeof responseData === "object") {
3402
+ for (const [entityName, records] of Object.entries(responseData)) {
3403
+ dataEntities[entityName] = Array.isArray(records) ? records.length : 0;
3404
+ }
3405
+ }
3389
3406
  recordTransition({
3390
3407
  traitName: parsed.traitName,
3391
3408
  from: pending?.from ?? payload["currentState"] ?? newState,
3392
3409
  to: newState,
3393
3410
  event: parsed.event,
3394
3411
  effects,
3412
+ serverResponse: {
3413
+ orbitalName: parsed.traitName,
3414
+ success: true,
3415
+ clientEffects: clientEffectsArr.length,
3416
+ dataEntities,
3417
+ emittedEvents: [],
3418
+ timestamp: Date.now()
3419
+ },
3395
3420
  timestamp: Date.now()
3396
3421
  });
3397
3422
  } else if (parsed.kind === "error" && parsed.event) {
@@ -3412,6 +3437,15 @@ function VerificationProvider({
3412
3437
  status: "failed",
3413
3438
  error: errorMsg
3414
3439
  }],
3440
+ serverResponse: {
3441
+ orbitalName: parsed.traitName,
3442
+ success: false,
3443
+ clientEffects: 0,
3444
+ dataEntities: {},
3445
+ emittedEvents: [],
3446
+ error: errorMsg,
3447
+ timestamp: Date.now()
3448
+ },
3415
3449
  timestamp: Date.now()
3416
3450
  });
3417
3451
  }
@@ -7,9 +7,21 @@ export interface ServerClientEffect {
7
7
  params?: Record<string, unknown>;
8
8
  message?: string;
9
9
  }
10
+ /** Metadata about what the server returned, for debugger logging */
11
+ export interface ServerResponseMeta {
12
+ success: boolean;
13
+ clientEffects: number;
14
+ dataEntities: Record<string, number>;
15
+ emittedEvents: string[];
16
+ error?: string;
17
+ }
18
+ export interface SendEventResult {
19
+ effects: ServerClientEffect[];
20
+ meta: ServerResponseMeta;
21
+ }
10
22
  export interface ServerBridgeContextValue {
11
23
  connected: boolean;
12
- sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<ServerClientEffect[]>;
24
+ sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<SendEventResult>;
13
25
  }
14
26
  /**
15
27
  * Access the server bridge. Returns a no-op stub when outside the provider.