@almadar/ui 2.27.5 → 2.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/components/index.cjs +123 -44
- package/dist/components/index.js +123 -44
- package/dist/lib/index.cjs +31 -0
- package/dist/lib/index.js +31 -1
- package/dist/lib/verificationRegistry.d.ts +18 -0
- package/dist/runtime/ServerBridge.d.ts +13 -1
- package/dist/runtime/index.cjs +175 -51
- package/dist/runtime/index.js +175 -51
- package/package.json +1 -1
|
@@ -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
|
-
|
|
33726
|
-
|
|
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
|
|
33729
|
-
|
|
33730
|
-
|
|
33731
|
-
|
|
33732
|
-
|
|
33733
|
-
|
|
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
|
}
|
package/dist/components/index.js
CHANGED
|
@@ -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
|
-
|
|
33696
|
-
|
|
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
|
|
33699
|
-
|
|
33700
|
-
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
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
|
}
|
package/dist/lib/index.cjs
CHANGED
|
@@ -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;
|
|
@@ -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<
|
|
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.
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -851,6 +851,36 @@ function recordTransition(trace) {
|
|
|
851
851
|
function getTransitions() {
|
|
852
852
|
return [...getState().transitions];
|
|
853
853
|
}
|
|
854
|
+
function recordServerResponse(orbitalName, event, response) {
|
|
855
|
+
const serverResponse = {
|
|
856
|
+
...response,
|
|
857
|
+
orbitalName,
|
|
858
|
+
timestamp: Date.now()
|
|
859
|
+
};
|
|
860
|
+
const entry = {
|
|
861
|
+
id: `srv-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
862
|
+
traitName: `server:${orbitalName}`,
|
|
863
|
+
from: "server",
|
|
864
|
+
to: "server",
|
|
865
|
+
event,
|
|
866
|
+
effects: [],
|
|
867
|
+
serverResponse,
|
|
868
|
+
timestamp: Date.now()
|
|
869
|
+
};
|
|
870
|
+
getState().transitions.push(entry);
|
|
871
|
+
if (getState().transitions.length > MAX_TRANSITIONS) {
|
|
872
|
+
getState().transitions.shift();
|
|
873
|
+
}
|
|
874
|
+
if (!response.success && response.error) {
|
|
875
|
+
registerCheck(
|
|
876
|
+
`server-error-${entry.id}`,
|
|
877
|
+
`Server error for ${orbitalName}:${event}`,
|
|
878
|
+
"fail",
|
|
879
|
+
response.error
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
notifyListeners2();
|
|
883
|
+
}
|
|
854
884
|
function getBridgeHealth() {
|
|
855
885
|
const bh = getState().bridgeHealth;
|
|
856
886
|
return bh ? { ...bh } : null;
|
|
@@ -27934,6 +27964,119 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
27934
27964
|
] });
|
|
27935
27965
|
}
|
|
27936
27966
|
EventDispatcherTab.displayName = "EventDispatcherTab";
|
|
27967
|
+
function ServerResponseRow({ sr }) {
|
|
27968
|
+
const entityEntries = Object.entries(sr.dataEntities);
|
|
27969
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-4 pl-2 border-l border-purple-700/50 py-0.5 text-[10px] font-mono", children: [
|
|
27970
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
27971
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: sr.success ? "text-green-400" : "text-red-400", children: [
|
|
27972
|
+
sr.success ? "\u2713" : "\u2717",
|
|
27973
|
+
" server"
|
|
27974
|
+
] }),
|
|
27975
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-300", children: sr.orbitalName }),
|
|
27976
|
+
sr.clientEffects > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 rounded bg-purple-900/50 text-purple-300", children: [
|
|
27977
|
+
sr.clientEffects,
|
|
27978
|
+
" clientEffect",
|
|
27979
|
+
sr.clientEffects !== 1 ? "s" : ""
|
|
27980
|
+
] }),
|
|
27981
|
+
sr.emittedEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-1 rounded bg-blue-900/50 text-blue-300", children: [
|
|
27982
|
+
"emit: ",
|
|
27983
|
+
sr.emittedEvents.join(", ")
|
|
27984
|
+
] }),
|
|
27985
|
+
sr.error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 rounded bg-red-900/50 text-red-400 truncate max-w-[300px]", children: sr.error })
|
|
27986
|
+
] }),
|
|
27987
|
+
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: [
|
|
27988
|
+
name,
|
|
27989
|
+
": ",
|
|
27990
|
+
count,
|
|
27991
|
+
" row",
|
|
27992
|
+
count !== 1 ? "s" : ""
|
|
27993
|
+
] }, name)) })
|
|
27994
|
+
] });
|
|
27995
|
+
}
|
|
27996
|
+
function TransitionRow({ trace }) {
|
|
27997
|
+
const isServerEntry = !!trace.serverResponse && trace.traitName.startsWith("server:");
|
|
27998
|
+
const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
|
|
27999
|
+
if (isServerEntry && trace.serverResponse) {
|
|
28000
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
|
|
28001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
|
|
28002
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 bg-purple-500" }),
|
|
28003
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "warning", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
28004
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400 flex-shrink-0", children: "server response" })
|
|
28005
|
+
] }),
|
|
28006
|
+
/* @__PURE__ */ jsxRuntime.jsx(ServerResponseRow, { sr: trace.serverResponse })
|
|
28007
|
+
] });
|
|
28008
|
+
}
|
|
28009
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
|
|
28010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
|
|
28011
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
28012
|
+
"mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
|
|
28013
|
+
hasFailedEffects ? "bg-red-500" : "bg-green-500"
|
|
28014
|
+
) }),
|
|
28015
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
28016
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300 flex-shrink-0", children: trace.traitName }),
|
|
28017
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
|
|
28018
|
+
trace.from,
|
|
28019
|
+
" ",
|
|
28020
|
+
"\u2192",
|
|
28021
|
+
" ",
|
|
28022
|
+
trace.to
|
|
28023
|
+
] })
|
|
28024
|
+
] }),
|
|
28025
|
+
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(
|
|
28026
|
+
"px-1 rounded text-[10px]",
|
|
28027
|
+
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"
|
|
28028
|
+
), children: [
|
|
28029
|
+
eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
|
|
28030
|
+
" ",
|
|
28031
|
+
eff.type,
|
|
28032
|
+
eff.args.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 40) })
|
|
28033
|
+
] }, i)) }),
|
|
28034
|
+
trace.serverResponse && /* @__PURE__ */ jsxRuntime.jsx(ServerResponseRow, { sr: trace.serverResponse })
|
|
28035
|
+
] });
|
|
28036
|
+
}
|
|
28037
|
+
function VerifyModePanel({
|
|
28038
|
+
className,
|
|
28039
|
+
failedChecks,
|
|
28040
|
+
transitions,
|
|
28041
|
+
traitStates,
|
|
28042
|
+
serverCount,
|
|
28043
|
+
localCount
|
|
28044
|
+
}) {
|
|
28045
|
+
const scrollRef = React117__namespace.useRef(null);
|
|
28046
|
+
const prevCountRef = React117__namespace.useRef(0);
|
|
28047
|
+
React117__namespace.useEffect(() => {
|
|
28048
|
+
if (transitions.length > prevCountRef.current && scrollRef.current) {
|
|
28049
|
+
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
28050
|
+
}
|
|
28051
|
+
prevCountRef.current = transitions.length;
|
|
28052
|
+
}, [transitions.length]);
|
|
28053
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28054
|
+
"div",
|
|
28055
|
+
{
|
|
28056
|
+
className: cn(
|
|
28057
|
+
"runtime-debugger runtime-debugger--verify",
|
|
28058
|
+
"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",
|
|
28059
|
+
className
|
|
28060
|
+
),
|
|
28061
|
+
"data-testid": "debugger-verify",
|
|
28062
|
+
children: [
|
|
28063
|
+
/* @__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: [
|
|
28064
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
|
|
28065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400", children: [
|
|
28066
|
+
localCount,
|
|
28067
|
+
" local"
|
|
28068
|
+
] }),
|
|
28069
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-purple-400", children: [
|
|
28070
|
+
serverCount,
|
|
28071
|
+
" server"
|
|
28072
|
+
] }),
|
|
28073
|
+
traitStates && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
|
|
28074
|
+
] }),
|
|
28075
|
+
/* @__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)) }) }) })
|
|
28076
|
+
]
|
|
28077
|
+
}
|
|
28078
|
+
);
|
|
28079
|
+
}
|
|
27937
28080
|
function RuntimeDebugger({
|
|
27938
28081
|
position = "bottom-right",
|
|
27939
28082
|
defaultCollapsed = true,
|
|
@@ -28083,51 +28226,17 @@ function RuntimeDebugger({
|
|
|
28083
28226
|
}
|
|
28084
28227
|
if (mode === "verify") {
|
|
28085
28228
|
const traitStates = debugData.traits.map((t) => `${t.name}:${t.currentState}`).join(" | ");
|
|
28086
|
-
|
|
28087
|
-
|
|
28229
|
+
const serverEntries = verification.transitions.filter((t) => t.serverResponse);
|
|
28230
|
+
const localEntries = verification.transitions.filter((t) => !t.serverResponse);
|
|
28231
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28232
|
+
VerifyModePanel,
|
|
28088
28233
|
{
|
|
28089
|
-
className
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
children: [
|
|
28096
|
-
/* @__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: [
|
|
28097
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
|
|
28098
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400", children: [
|
|
28099
|
-
verification.transitions.length,
|
|
28100
|
-
" transitions"
|
|
28101
|
-
] }),
|
|
28102
|
-
traitStates && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
|
|
28103
|
-
] }),
|
|
28104
|
-
/* @__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) => {
|
|
28105
|
-
const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
|
|
28106
|
-
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: [
|
|
28107
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
|
|
28108
|
-
"mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
|
|
28109
|
-
hasFailedEffects ? "bg-red-500" : "bg-green-500"
|
|
28110
|
-
) }),
|
|
28111
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
28112
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
|
|
28113
|
-
trace.from,
|
|
28114
|
-
" ",
|
|
28115
|
-
"\u2192",
|
|
28116
|
-
" ",
|
|
28117
|
-
trace.to
|
|
28118
|
-
] }),
|
|
28119
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap gap-1 ml-1", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
|
|
28120
|
-
"px-1 rounded text-[10px]",
|
|
28121
|
-
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"
|
|
28122
|
-
), children: [
|
|
28123
|
-
eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
|
|
28124
|
-
" ",
|
|
28125
|
-
eff.type,
|
|
28126
|
-
eff.args.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 30) })
|
|
28127
|
-
] }, i)) })
|
|
28128
|
-
] }, trace.id);
|
|
28129
|
-
}) }) }) })
|
|
28130
|
-
]
|
|
28234
|
+
className,
|
|
28235
|
+
failedChecks,
|
|
28236
|
+
transitions: verification.transitions,
|
|
28237
|
+
traitStates,
|
|
28238
|
+
serverCount: serverEntries.length,
|
|
28239
|
+
localCount: localEntries.length
|
|
28131
28240
|
}
|
|
28132
28241
|
);
|
|
28133
28242
|
}
|
|
@@ -32486,7 +32595,8 @@ var ServerBridgeContext = React117.createContext(null);
|
|
|
32486
32595
|
function useServerBridge() {
|
|
32487
32596
|
const ctx = React117.useContext(ServerBridgeContext);
|
|
32488
32597
|
if (!ctx) {
|
|
32489
|
-
|
|
32598
|
+
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
32599
|
+
return { connected: false, sendEvent: async () => ({ effects: [], meta: emptyMeta }) };
|
|
32490
32600
|
}
|
|
32491
32601
|
return ctx;
|
|
32492
32602
|
}
|
|
@@ -32518,7 +32628,8 @@ function ServerBridgeProvider({
|
|
|
32518
32628
|
}
|
|
32519
32629
|
}, [serverUrl]);
|
|
32520
32630
|
const sendEvent = React117.useCallback(async (orbitalName, event, payload) => {
|
|
32521
|
-
|
|
32631
|
+
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
32632
|
+
if (!connected) return { effects: [], meta: emptyMeta };
|
|
32522
32633
|
try {
|
|
32523
32634
|
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
32524
32635
|
method: "POST",
|
|
@@ -32527,8 +32638,19 @@ function ServerBridgeProvider({
|
|
|
32527
32638
|
});
|
|
32528
32639
|
const result = await res.json();
|
|
32529
32640
|
const effects = [];
|
|
32641
|
+
const responseData = result.data || {};
|
|
32642
|
+
const dataEntities = {};
|
|
32643
|
+
for (const [entityName, records] of Object.entries(responseData)) {
|
|
32644
|
+
dataEntities[entityName] = Array.isArray(records) ? records.length : 0;
|
|
32645
|
+
}
|
|
32646
|
+
const meta = {
|
|
32647
|
+
success: !!result.success,
|
|
32648
|
+
clientEffects: result.clientEffects?.length ?? 0,
|
|
32649
|
+
dataEntities,
|
|
32650
|
+
emittedEvents: result.emittedEvents?.map((e) => e.event) ?? [],
|
|
32651
|
+
error: result.error
|
|
32652
|
+
};
|
|
32530
32653
|
if (result.success) {
|
|
32531
|
-
const responseData = result.data || {};
|
|
32532
32654
|
if (result.clientEffects) {
|
|
32533
32655
|
for (const effect of result.clientEffects) {
|
|
32534
32656
|
const arr = effect;
|
|
@@ -32554,10 +32676,10 @@ function ServerBridgeProvider({
|
|
|
32554
32676
|
} else if (result.error) {
|
|
32555
32677
|
console.error("[ServerBridge] Event error:", result.error);
|
|
32556
32678
|
}
|
|
32557
|
-
return effects;
|
|
32679
|
+
return { effects, meta };
|
|
32558
32680
|
} catch (err) {
|
|
32559
32681
|
console.error("[ServerBridge] Event send failed:", err);
|
|
32560
|
-
return [];
|
|
32682
|
+
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
32561
32683
|
}
|
|
32562
32684
|
}, [connected, serverUrl, eventBus]);
|
|
32563
32685
|
React117.useEffect(() => {
|
|
@@ -32618,7 +32740,8 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32618
32740
|
const onEventProcessed = React117.useCallback(async (event, payload) => {
|
|
32619
32741
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
32620
32742
|
for (const name of orbitalNames) {
|
|
32621
|
-
const effects = await bridge.sendEvent(name, event, payload);
|
|
32743
|
+
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
32744
|
+
recordServerResponse(name, event, meta);
|
|
32622
32745
|
for (const eff of effects) {
|
|
32623
32746
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32624
32747
|
slotsActions.setSlotPatterns(
|
|
@@ -32652,7 +32775,8 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32652
32775
|
initSentRef.current = true;
|
|
32653
32776
|
(async () => {
|
|
32654
32777
|
for (const name of orbitalNames) {
|
|
32655
|
-
const effects = await bridge.sendEvent(name, "INIT", {});
|
|
32778
|
+
const { effects, meta } = await bridge.sendEvent(name, "INIT", {});
|
|
32779
|
+
recordServerResponse(name, "INIT", meta);
|
|
32656
32780
|
const effectTraces = [
|
|
32657
32781
|
{ type: "fetch", args: [], status: "executed" },
|
|
32658
32782
|
...effects.map((eff) => ({
|
package/dist/runtime/index.js
CHANGED
|
@@ -821,6 +821,36 @@ function recordTransition(trace) {
|
|
|
821
821
|
function getTransitions() {
|
|
822
822
|
return [...getState().transitions];
|
|
823
823
|
}
|
|
824
|
+
function recordServerResponse(orbitalName, event, response) {
|
|
825
|
+
const serverResponse = {
|
|
826
|
+
...response,
|
|
827
|
+
orbitalName,
|
|
828
|
+
timestamp: Date.now()
|
|
829
|
+
};
|
|
830
|
+
const entry = {
|
|
831
|
+
id: `srv-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
832
|
+
traitName: `server:${orbitalName}`,
|
|
833
|
+
from: "server",
|
|
834
|
+
to: "server",
|
|
835
|
+
event,
|
|
836
|
+
effects: [],
|
|
837
|
+
serverResponse,
|
|
838
|
+
timestamp: Date.now()
|
|
839
|
+
};
|
|
840
|
+
getState().transitions.push(entry);
|
|
841
|
+
if (getState().transitions.length > MAX_TRANSITIONS) {
|
|
842
|
+
getState().transitions.shift();
|
|
843
|
+
}
|
|
844
|
+
if (!response.success && response.error) {
|
|
845
|
+
registerCheck(
|
|
846
|
+
`server-error-${entry.id}`,
|
|
847
|
+
`Server error for ${orbitalName}:${event}`,
|
|
848
|
+
"fail",
|
|
849
|
+
response.error
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
notifyListeners2();
|
|
853
|
+
}
|
|
824
854
|
function getBridgeHealth() {
|
|
825
855
|
const bh = getState().bridgeHealth;
|
|
826
856
|
return bh ? { ...bh } : null;
|
|
@@ -27904,6 +27934,119 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
27904
27934
|
] });
|
|
27905
27935
|
}
|
|
27906
27936
|
EventDispatcherTab.displayName = "EventDispatcherTab";
|
|
27937
|
+
function ServerResponseRow({ sr }) {
|
|
27938
|
+
const entityEntries = Object.entries(sr.dataEntities);
|
|
27939
|
+
return /* @__PURE__ */ jsxs("div", { className: "ml-4 pl-2 border-l border-purple-700/50 py-0.5 text-[10px] font-mono", children: [
|
|
27940
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
27941
|
+
/* @__PURE__ */ jsxs("span", { className: sr.success ? "text-green-400" : "text-red-400", children: [
|
|
27942
|
+
sr.success ? "\u2713" : "\u2717",
|
|
27943
|
+
" server"
|
|
27944
|
+
] }),
|
|
27945
|
+
/* @__PURE__ */ jsx("span", { className: "text-purple-300", children: sr.orbitalName }),
|
|
27946
|
+
sr.clientEffects > 0 && /* @__PURE__ */ jsxs("span", { className: "px-1 rounded bg-purple-900/50 text-purple-300", children: [
|
|
27947
|
+
sr.clientEffects,
|
|
27948
|
+
" clientEffect",
|
|
27949
|
+
sr.clientEffects !== 1 ? "s" : ""
|
|
27950
|
+
] }),
|
|
27951
|
+
sr.emittedEvents.length > 0 && /* @__PURE__ */ jsxs("span", { className: "px-1 rounded bg-blue-900/50 text-blue-300", children: [
|
|
27952
|
+
"emit: ",
|
|
27953
|
+
sr.emittedEvents.join(", ")
|
|
27954
|
+
] }),
|
|
27955
|
+
sr.error && /* @__PURE__ */ jsx("span", { className: "px-1 rounded bg-red-900/50 text-red-400 truncate max-w-[300px]", children: sr.error })
|
|
27956
|
+
] }),
|
|
27957
|
+
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: [
|
|
27958
|
+
name,
|
|
27959
|
+
": ",
|
|
27960
|
+
count,
|
|
27961
|
+
" row",
|
|
27962
|
+
count !== 1 ? "s" : ""
|
|
27963
|
+
] }, name)) })
|
|
27964
|
+
] });
|
|
27965
|
+
}
|
|
27966
|
+
function TransitionRow({ trace }) {
|
|
27967
|
+
const isServerEntry = !!trace.serverResponse && trace.traitName.startsWith("server:");
|
|
27968
|
+
const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
|
|
27969
|
+
if (isServerEntry && trace.serverResponse) {
|
|
27970
|
+
return /* @__PURE__ */ jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
|
|
27971
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
|
|
27972
|
+
/* @__PURE__ */ jsx("span", { className: "mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0 bg-purple-500" }),
|
|
27973
|
+
/* @__PURE__ */ jsx(Badge, { variant: "warning", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
27974
|
+
/* @__PURE__ */ jsx("span", { className: "text-purple-400 flex-shrink-0", children: "server response" })
|
|
27975
|
+
] }),
|
|
27976
|
+
/* @__PURE__ */ jsx(ServerResponseRow, { sr: trace.serverResponse })
|
|
27977
|
+
] });
|
|
27978
|
+
}
|
|
27979
|
+
return /* @__PURE__ */ jsxs("div", { className: "py-0.5 border-b border-gray-800 last:border-0", children: [
|
|
27980
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 text-xs font-mono", children: [
|
|
27981
|
+
/* @__PURE__ */ jsx("span", { className: cn(
|
|
27982
|
+
"mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
|
|
27983
|
+
hasFailedEffects ? "bg-red-500" : "bg-green-500"
|
|
27984
|
+
) }),
|
|
27985
|
+
/* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
27986
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-300 flex-shrink-0", children: trace.traitName }),
|
|
27987
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
|
|
27988
|
+
trace.from,
|
|
27989
|
+
" ",
|
|
27990
|
+
"\u2192",
|
|
27991
|
+
" ",
|
|
27992
|
+
trace.to
|
|
27993
|
+
] })
|
|
27994
|
+
] }),
|
|
27995
|
+
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(
|
|
27996
|
+
"px-1 rounded text-[10px]",
|
|
27997
|
+
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"
|
|
27998
|
+
), children: [
|
|
27999
|
+
eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
|
|
28000
|
+
" ",
|
|
28001
|
+
eff.type,
|
|
28002
|
+
eff.args.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 40) })
|
|
28003
|
+
] }, i)) }),
|
|
28004
|
+
trace.serverResponse && /* @__PURE__ */ jsx(ServerResponseRow, { sr: trace.serverResponse })
|
|
28005
|
+
] });
|
|
28006
|
+
}
|
|
28007
|
+
function VerifyModePanel({
|
|
28008
|
+
className,
|
|
28009
|
+
failedChecks,
|
|
28010
|
+
transitions,
|
|
28011
|
+
traitStates,
|
|
28012
|
+
serverCount,
|
|
28013
|
+
localCount
|
|
28014
|
+
}) {
|
|
28015
|
+
const scrollRef = React117.useRef(null);
|
|
28016
|
+
const prevCountRef = React117.useRef(0);
|
|
28017
|
+
React117.useEffect(() => {
|
|
28018
|
+
if (transitions.length > prevCountRef.current && scrollRef.current) {
|
|
28019
|
+
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
28020
|
+
}
|
|
28021
|
+
prevCountRef.current = transitions.length;
|
|
28022
|
+
}, [transitions.length]);
|
|
28023
|
+
return /* @__PURE__ */ jsxs(
|
|
28024
|
+
"div",
|
|
28025
|
+
{
|
|
28026
|
+
className: cn(
|
|
28027
|
+
"runtime-debugger runtime-debugger--verify",
|
|
28028
|
+
"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",
|
|
28029
|
+
className
|
|
28030
|
+
),
|
|
28031
|
+
"data-testid": "debugger-verify",
|
|
28032
|
+
children: [
|
|
28033
|
+
/* @__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: [
|
|
28034
|
+
/* @__PURE__ */ jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
|
|
28035
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
|
|
28036
|
+
localCount,
|
|
28037
|
+
" local"
|
|
28038
|
+
] }),
|
|
28039
|
+
/* @__PURE__ */ jsxs("span", { className: "text-purple-400", children: [
|
|
28040
|
+
serverCount,
|
|
28041
|
+
" server"
|
|
28042
|
+
] }),
|
|
28043
|
+
traitStates && /* @__PURE__ */ jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
|
|
28044
|
+
] }),
|
|
28045
|
+
/* @__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)) }) }) })
|
|
28046
|
+
]
|
|
28047
|
+
}
|
|
28048
|
+
);
|
|
28049
|
+
}
|
|
27907
28050
|
function RuntimeDebugger({
|
|
27908
28051
|
position = "bottom-right",
|
|
27909
28052
|
defaultCollapsed = true,
|
|
@@ -28053,51 +28196,17 @@ function RuntimeDebugger({
|
|
|
28053
28196
|
}
|
|
28054
28197
|
if (mode === "verify") {
|
|
28055
28198
|
const traitStates = debugData.traits.map((t) => `${t.name}:${t.currentState}`).join(" | ");
|
|
28056
|
-
|
|
28057
|
-
|
|
28199
|
+
const serverEntries = verification.transitions.filter((t) => t.serverResponse);
|
|
28200
|
+
const localEntries = verification.transitions.filter((t) => !t.serverResponse);
|
|
28201
|
+
return /* @__PURE__ */ jsx(
|
|
28202
|
+
VerifyModePanel,
|
|
28058
28203
|
{
|
|
28059
|
-
className
|
|
28060
|
-
|
|
28061
|
-
|
|
28062
|
-
|
|
28063
|
-
|
|
28064
|
-
|
|
28065
|
-
children: [
|
|
28066
|
-
/* @__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: [
|
|
28067
|
-
/* @__PURE__ */ jsx(Badge, { variant: failedChecks > 0 ? "danger" : "success", size: "sm", children: failedChecks > 0 ? `${failedChecks} fail` : "OK" }),
|
|
28068
|
-
/* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
|
|
28069
|
-
verification.transitions.length,
|
|
28070
|
-
" transitions"
|
|
28071
|
-
] }),
|
|
28072
|
-
traitStates && /* @__PURE__ */ jsx("span", { className: "text-cyan-400 truncate max-w-[400px]", children: traitStates })
|
|
28073
|
-
] }),
|
|
28074
|
-
/* @__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) => {
|
|
28075
|
-
const hasFailedEffects = trace.effects.some((e) => e.status === "failed");
|
|
28076
|
-
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: [
|
|
28077
|
-
/* @__PURE__ */ jsx("span", { className: cn(
|
|
28078
|
-
"mt-1.5 w-1.5 h-1.5 rounded-full flex-shrink-0",
|
|
28079
|
-
hasFailedEffects ? "bg-red-500" : "bg-green-500"
|
|
28080
|
-
) }),
|
|
28081
|
-
/* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", className: "flex-shrink-0", children: trace.event }),
|
|
28082
|
-
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 flex-shrink-0", children: [
|
|
28083
|
-
trace.from,
|
|
28084
|
-
" ",
|
|
28085
|
-
"\u2192",
|
|
28086
|
-
" ",
|
|
28087
|
-
trace.to
|
|
28088
|
-
] }),
|
|
28089
|
-
/* @__PURE__ */ jsx("span", { className: "flex flex-wrap gap-1 ml-1", children: trace.effects.map((eff, i) => /* @__PURE__ */ jsxs("span", { className: cn(
|
|
28090
|
-
"px-1 rounded text-[10px]",
|
|
28091
|
-
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"
|
|
28092
|
-
), children: [
|
|
28093
|
-
eff.status === "executed" ? "\u2713" : eff.status === "failed" ? "\u2717" : "-",
|
|
28094
|
-
" ",
|
|
28095
|
-
eff.type,
|
|
28096
|
-
eff.args.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-500 ml-0.5", children: JSON.stringify(eff.args).slice(0, 30) })
|
|
28097
|
-
] }, i)) })
|
|
28098
|
-
] }, trace.id);
|
|
28099
|
-
}) }) }) })
|
|
28100
|
-
]
|
|
28204
|
+
className,
|
|
28205
|
+
failedChecks,
|
|
28206
|
+
transitions: verification.transitions,
|
|
28207
|
+
traitStates,
|
|
28208
|
+
serverCount: serverEntries.length,
|
|
28209
|
+
localCount: localEntries.length
|
|
28101
28210
|
}
|
|
28102
28211
|
);
|
|
28103
28212
|
}
|
|
@@ -32456,7 +32565,8 @@ var ServerBridgeContext = createContext(null);
|
|
|
32456
32565
|
function useServerBridge() {
|
|
32457
32566
|
const ctx = useContext(ServerBridgeContext);
|
|
32458
32567
|
if (!ctx) {
|
|
32459
|
-
|
|
32568
|
+
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
32569
|
+
return { connected: false, sendEvent: async () => ({ effects: [], meta: emptyMeta }) };
|
|
32460
32570
|
}
|
|
32461
32571
|
return ctx;
|
|
32462
32572
|
}
|
|
@@ -32488,7 +32598,8 @@ function ServerBridgeProvider({
|
|
|
32488
32598
|
}
|
|
32489
32599
|
}, [serverUrl]);
|
|
32490
32600
|
const sendEvent = useCallback(async (orbitalName, event, payload) => {
|
|
32491
|
-
|
|
32601
|
+
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
32602
|
+
if (!connected) return { effects: [], meta: emptyMeta };
|
|
32492
32603
|
try {
|
|
32493
32604
|
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
32494
32605
|
method: "POST",
|
|
@@ -32497,8 +32608,19 @@ function ServerBridgeProvider({
|
|
|
32497
32608
|
});
|
|
32498
32609
|
const result = await res.json();
|
|
32499
32610
|
const effects = [];
|
|
32611
|
+
const responseData = result.data || {};
|
|
32612
|
+
const dataEntities = {};
|
|
32613
|
+
for (const [entityName, records] of Object.entries(responseData)) {
|
|
32614
|
+
dataEntities[entityName] = Array.isArray(records) ? records.length : 0;
|
|
32615
|
+
}
|
|
32616
|
+
const meta = {
|
|
32617
|
+
success: !!result.success,
|
|
32618
|
+
clientEffects: result.clientEffects?.length ?? 0,
|
|
32619
|
+
dataEntities,
|
|
32620
|
+
emittedEvents: result.emittedEvents?.map((e) => e.event) ?? [],
|
|
32621
|
+
error: result.error
|
|
32622
|
+
};
|
|
32500
32623
|
if (result.success) {
|
|
32501
|
-
const responseData = result.data || {};
|
|
32502
32624
|
if (result.clientEffects) {
|
|
32503
32625
|
for (const effect of result.clientEffects) {
|
|
32504
32626
|
const arr = effect;
|
|
@@ -32524,10 +32646,10 @@ function ServerBridgeProvider({
|
|
|
32524
32646
|
} else if (result.error) {
|
|
32525
32647
|
console.error("[ServerBridge] Event error:", result.error);
|
|
32526
32648
|
}
|
|
32527
|
-
return effects;
|
|
32649
|
+
return { effects, meta };
|
|
32528
32650
|
} catch (err) {
|
|
32529
32651
|
console.error("[ServerBridge] Event send failed:", err);
|
|
32530
|
-
return [];
|
|
32652
|
+
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
32531
32653
|
}
|
|
32532
32654
|
}, [connected, serverUrl, eventBus]);
|
|
32533
32655
|
useEffect(() => {
|
|
@@ -32588,7 +32710,8 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32588
32710
|
const onEventProcessed = useCallback(async (event, payload) => {
|
|
32589
32711
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
32590
32712
|
for (const name of orbitalNames) {
|
|
32591
|
-
const effects = await bridge.sendEvent(name, event, payload);
|
|
32713
|
+
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
32714
|
+
recordServerResponse(name, event, meta);
|
|
32592
32715
|
for (const eff of effects) {
|
|
32593
32716
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
32594
32717
|
slotsActions.setSlotPatterns(
|
|
@@ -32622,7 +32745,8 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
32622
32745
|
initSentRef.current = true;
|
|
32623
32746
|
(async () => {
|
|
32624
32747
|
for (const name of orbitalNames) {
|
|
32625
|
-
const effects = await bridge.sendEvent(name, "INIT", {});
|
|
32748
|
+
const { effects, meta } = await bridge.sendEvent(name, "INIT", {});
|
|
32749
|
+
recordServerResponse(name, "INIT", meta);
|
|
32626
32750
|
const effectTraces = [
|
|
32627
32751
|
{ type: "fetch", args: [], status: "executed" },
|
|
32628
32752
|
...effects.map((eff) => ({
|