okengine 0.13.0 → 0.14.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.
Files changed (105) hide show
  1. package/manifest.v1.schema.json +7 -1
  2. package/package.json +2 -2
  3. package/site/content/docs/ai/mcp.mdx +27 -2
  4. package/site/content/docs/elements/ai.mdx +58 -11
  5. package/site/content/docs/elements/clock.mdx +27 -12
  6. package/site/content/docs/elements/flow.mdx +6 -3
  7. package/site/content/docs/elements/signal.mdx +71 -25
  8. package/site/content/docs/elements/store.mdx +1 -1
  9. package/site/content/docs/get-started/installation.mdx +2 -2
  10. package/site/content/docs/reference/fx.mdx +27 -22
  11. package/src/cli/ai-setup/recommend.test.ts +25 -0
  12. package/src/cli/ai-setup/recommend.ts +8 -3
  13. package/src/compiler/effects-infer.ts +58 -3
  14. package/src/compiler/extract.test.ts +54 -1
  15. package/src/compiler/extract.ts +69 -2
  16. package/src/compiler/response.ts +45 -1
  17. package/src/console/server/ai.ts +5 -2
  18. package/src/console/server/flows.ts +1 -0
  19. package/src/console/server/serve.ts +17 -2
  20. package/src/console/ui-next/dist/assets/cache-glyph-BanhLsEY.js +1 -0
  21. package/src/console/ui-next/dist/assets/flows-page-DxDsOd4f.js +1 -0
  22. package/src/console/ui-next/dist/assets/http-method-CJCBYL2j.js +1 -0
  23. package/src/console/ui-next/dist/assets/{index-Bp-R7jtM.js → index-Ce6WKWKM.js} +3 -3
  24. package/src/console/ui-next/dist/assets/observability-page-BEZDzyYh.js +4 -0
  25. package/src/console/ui-next/dist/assets/trace-detail-sheet-DFLFfUUX.js +2 -0
  26. package/src/console/ui-next/dist/assets/units-page-C0gW6Kdo.js +1 -0
  27. package/src/console/ui-next/dist/assets/{vault-page-Ca-MvcmJ.js → vault-page-DuKzqwzW.js} +1 -1
  28. package/src/console/ui-next/dist/index.html +1 -1
  29. package/src/console/ui-next/seed-invoke-host.ts +2 -0
  30. package/src/console/ui-next/src/features/flows/graph/build-flow-graph.test.ts +18 -0
  31. package/src/console/ui-next/src/features/flows/graph/build-flow-graph.ts +14 -1
  32. package/src/console/ui-next/src/features/flows/graph/neighborhood.test.ts +17 -0
  33. package/src/console/ui-next/src/features/flows/graph/neighborhood.ts +16 -3
  34. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +3 -1
  35. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
  36. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +9 -3
  37. package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +10 -1
  38. package/src/console/ui-next/src/features/observability/lib/ask-count.test.ts +25 -0
  39. package/src/console/ui-next/src/features/observability/lib/ask-count.ts +4 -1
  40. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +12 -4
  41. package/src/docker/docker.test.ts +1 -1
  42. package/src/docker/dockerfile.ts +1 -1
  43. package/src/drivers/ai-anthropic.ts +5 -0
  44. package/src/drivers/ai-ollama.ts +49 -30
  45. package/src/drivers/ai-openai-compatible.ts +57 -46
  46. package/src/drivers/ai-providers.test.ts +3 -0
  47. package/src/drivers/bun-native-completeness.test.ts +7 -9
  48. package/src/drivers/redis.ts +11 -4
  49. package/src/drivers/signal-redis.ts +24 -14
  50. package/src/drivers/signal-types.ts +2 -1
  51. package/src/elements/ai/declare.ts +109 -0
  52. package/src/elements/ai/errors.test.ts +5 -1
  53. package/src/elements/ai/errors.ts +30 -2
  54. package/src/elements/ai/eval.ts +4 -6
  55. package/src/elements/ai/mcp-client.test.ts +206 -0
  56. package/src/elements/ai/mcp-client.ts +362 -0
  57. package/src/elements/ai/mcp-http.ts +159 -0
  58. package/src/elements/ai/mcp-mock.ts +134 -0
  59. package/src/elements/ai/mcp-protocol.ts +234 -0
  60. package/src/elements/ai/mcp-stdio.test.ts +50 -0
  61. package/src/elements/ai/mcp-stdio.ts +212 -0
  62. package/src/elements/ai/mcp-transport.ts +70 -0
  63. package/src/elements/ai/runtime.ts +159 -29
  64. package/src/elements/ai.test.ts +139 -0
  65. package/src/elements/ai.ts +16 -0
  66. package/src/elements/clock/health.test.ts +43 -0
  67. package/src/elements/clock/runtime.ts +55 -2
  68. package/src/elements/clock/schedule.ts +71 -142
  69. package/src/elements/clock.test.ts +9 -40
  70. package/src/elements/clock.ts +6 -1
  71. package/src/elements/index.ts +2 -0
  72. package/src/elements/signal/declare.ts +2 -1
  73. package/src/elements/signal/runtime.ts +16 -1
  74. package/src/elements/signal.ts +1 -0
  75. package/src/elements/store/cache.test.ts +2 -0
  76. package/src/elements/store/cache.ts +3 -3
  77. package/src/elements/vault/builtin-adapter.ts +17 -0
  78. package/src/full.ts +2 -0
  79. package/src/index.ts +4 -0
  80. package/src/kernel/app.ts +97 -64
  81. package/src/kernel/auto-registry.test.ts +5 -0
  82. package/src/kernel/boot-bind/ai.ts +24 -0
  83. package/src/kernel/boot-bind/clock.ts +2 -0
  84. package/src/kernel/boot.ts +3 -1
  85. package/src/kernel/element-registries.ts +4 -1
  86. package/src/kernel/fx-dead-letters.test.ts +77 -0
  87. package/src/kernel/fx.test.ts +22 -0
  88. package/src/kernel/fx.ts +112 -6
  89. package/src/kernel/http-stream.test.ts +174 -0
  90. package/src/kernel/index.ts +2 -0
  91. package/src/manifest/mcp-ref.ts +88 -0
  92. package/src/manifest/types.ts +28 -2
  93. package/src/manifest/validate.test.ts +20 -0
  94. package/src/mcp/docs-server.ts +1 -1
  95. package/src/mcp/server.ts +1 -1
  96. package/src/plugins/compression.test.ts +21 -0
  97. package/src/plugins/compression.ts +1 -0
  98. package/src/runtime/bun.ts +41 -4
  99. package/src/test/reset-element-registries.ts +2 -0
  100. package/src/console/ui-next/dist/assets/cache-glyph-CLPBqZeb.js +0 -1
  101. package/src/console/ui-next/dist/assets/flows-page-Dg8CTE29.js +0 -1
  102. package/src/console/ui-next/dist/assets/http-method-BJ92Z_ke.js +0 -1
  103. package/src/console/ui-next/dist/assets/observability-page-DAnpEaq1.js +0 -4
  104. package/src/console/ui-next/dist/assets/trace-detail-sheet-D16lWQMt.js +0 -2
  105. package/src/console/ui-next/dist/assets/units-page-BtQ0bqMe.js +0 -1
@@ -197,4 +197,29 @@ describe("formatModelRow", () => {
197
197
  expect(row).toContain("text · code");
198
198
  expect(row).not.toContain(" · ≈");
199
199
  });
200
+
201
+ test("Arabic and CJK labels keep Caps aligned", () => {
202
+ const header = formatModelTableHeader();
203
+ const capsWidth = Bun.stringWidth(header.slice(0, header.indexOf("Caps")));
204
+ const ar = formatModelRow({
205
+ id: "ar",
206
+ label: "مرحبا بالعالم",
207
+ hint: "",
208
+ role: "chat",
209
+ ramGb: 8,
210
+ tier: "fast",
211
+ modalities: ["text"],
212
+ });
213
+ const cjk = formatModelRow({
214
+ id: "cjk",
215
+ label: "你好世界模型",
216
+ hint: "",
217
+ role: "chat",
218
+ ramGb: 8,
219
+ tier: "fast",
220
+ modalities: ["text"],
221
+ });
222
+ expect(Bun.stringWidth(ar.slice(0, ar.indexOf("text")))).toBe(capsWidth);
223
+ expect(Bun.stringWidth(cjk.slice(0, cjk.indexOf("text")))).toBe(capsWidth);
224
+ });
200
225
  });
@@ -195,9 +195,14 @@ const MODEL_COL_RAM = 7;
195
195
  * @param width - Fixed width
196
196
  */
197
197
  function clipPad(value: string, width: number): string {
198
- if (value.length === width) return value;
199
- if (value.length < width) return value.padEnd(width);
200
- return `${value.slice(0, Math.max(0, width - 1))}…`;
198
+ const bunAnsi = Bun as typeof Bun & {
199
+ stringWidth(text: string): number;
200
+ sliceAnsi(text: string, start: number, end: number, omission?: string): string;
201
+ };
202
+ const display = bunAnsi.stringWidth(value);
203
+ if (display === width) return value;
204
+ if (display < width) return value + " ".repeat(width - display);
205
+ return bunAnsi.sliceAnsi(value, 0, width, "…");
201
206
  }
202
207
 
203
208
  /**
@@ -12,6 +12,7 @@ import type {
12
12
  ResourceRef,
13
13
  SecretRef,
14
14
  SignalRef,
15
+ SignalResourceRef,
15
16
  TemplateRef,
16
17
  FlowRef,
17
18
  } from "../manifest/types.ts";
@@ -56,6 +57,8 @@ export interface InferBinding {
56
57
  | "flow"
57
58
  | "embed"
58
59
  | "table"
60
+ | "mcp-server"
61
+ | "mcp-tool"
59
62
  | "unknown";
60
63
  /** Resolved resource / name. */
61
64
  readonly ref: string;
@@ -142,7 +145,7 @@ const TABLE_ARG_METHODS = new Set([
142
145
  * @param options - Handler AST, bindings, and annotation flag
143
146
  */
144
147
  export function inferEffects(options: InferEffectsOptions): InferredEffects {
145
- const reads = new Set<ResourceRef>();
148
+ const reads = new Set<ResourceRef | SignalResourceRef>();
146
149
  const writes = new Set<ResourceRef>();
147
150
  const emits = new Set<SignalRef>();
148
151
  const sends = new Set<TemplateRef>();
@@ -173,6 +176,12 @@ export function inferEffects(options: InferEffectsOptions): InferredEffects {
173
176
  continue;
174
177
  }
175
178
 
179
+ if (chain.rootMethod === "deadLetters" && call === chain.rootCall) {
180
+ const ref = resolveNamed(call.arguments[0], options.bindings, "signal");
181
+ if (ref) reads.add(`signal:${ref}`);
182
+ continue;
183
+ }
184
+
176
185
  if (chain.rootMethod === "send" && call === chain.rootCall) {
177
186
  const ref = resolveNamed(call.arguments[0], options.bindings, "template");
178
187
  if (ref) sends.add(ref);
@@ -203,7 +212,7 @@ export function inferEffects(options: InferEffectsOptions): InferredEffects {
203
212
  }
204
213
 
205
214
  if (chain.rootMethod === "call" && call === chain.rootCall) {
206
- const ref = resolveNamed(call.arguments[0], options.bindings, "flow");
215
+ const ref = resolveCallTarget(call.arguments[0], options.bindings);
207
216
  if (ref) calls.add(ref);
208
217
  continue;
209
218
  }
@@ -541,12 +550,58 @@ function toolsFromAskOptions(
541
550
  );
542
551
  const out: FlowRef[] = [];
543
552
  for (const el of els) {
544
- const ref = resolveNamed(el, bindings, "flow");
553
+ const ref = resolveCallTarget(el, bindings);
545
554
  if (ref) out.push(ref as FlowRef);
546
555
  }
547
556
  return out;
548
557
  }
549
558
 
559
+ /**
560
+ * Resolve `fx.call` / ask-tools: flow name, `mcp:` ref, or `server.tool("x")`.
561
+ *
562
+ * @param node - Argument AST
563
+ * @param bindings - Known bindings
564
+ */
565
+ export function resolveCallTarget(
566
+ node: AstNode | undefined,
567
+ bindings: ReadonlyMap<string, InferBinding>,
568
+ ): string | undefined {
569
+ const mcp = resolveMcpToolExpr(node, bindings);
570
+ if (mcp) return mcp;
571
+ return resolveNamed(node, bindings, "flow");
572
+ }
573
+
574
+ /**
575
+ * Resolve `server.tool("name")` or a bound `mcp-tool` identifier.
576
+ *
577
+ * @param node - AST
578
+ * @param bindings - Known bindings
579
+ */
580
+ export function resolveMcpToolExpr(
581
+ node: AstNode | undefined,
582
+ bindings: ReadonlyMap<string, InferBinding>,
583
+ ): string | undefined {
584
+ if (!node) return undefined;
585
+ if (node.type === "CallExpression") {
586
+ const callee = (node as CallExpression).callee;
587
+ if (callee.type === "MemberExpression") {
588
+ const member = callee as AstNode & { object: AstNode; property: AstNode };
589
+ const obj = identifierName(member.object);
590
+ const prop = identifierName(member.property);
591
+ const tool = stringArg((node as CallExpression).arguments[0]);
592
+ if (obj && prop === "tool" && tool) {
593
+ const server = bindings.get(obj);
594
+ if (server?.kind === "mcp-server") {
595
+ return `mcp:${server.ref}/${tool}`;
596
+ }
597
+ }
598
+ }
599
+ }
600
+ const binding = resolveBinding(node, bindings);
601
+ if (binding?.kind === "mcp-tool") return binding.ref;
602
+ return undefined;
603
+ }
604
+
550
605
  /**
551
606
  * String literal argument.
552
607
  *
@@ -135,12 +135,15 @@ export const flow_${i} = on(
135
135
  }
136
136
  sources["src/flows/all.ts"] = parts.join("\n");
137
137
 
138
+ await extractFromSources(sources);
138
139
  const start = performance.now();
139
140
  const manifest = await extractFromSources(sources);
140
141
  const elapsed = performance.now() - start;
141
142
 
142
143
  expect(Object.keys(manifest.flows ?? {}).length).toBe(200);
143
- expect(elapsed).toBeLessThan(2000);
144
+ // Local ~400ms after warmup. GHA shared runners measured ~2.9s cold.
145
+ const budgetMs = process.env.CI ? 4_000 : 2_000;
146
+ expect(elapsed).toBeLessThan(budgetMs);
144
147
  });
145
148
  });
146
149
 
@@ -598,6 +601,25 @@ export const expire = on(
598
601
  });
599
602
  });
600
603
 
604
+ describe("extractManifest — fx.deadLetters", () => {
605
+ test("fx.deadLetters(signal) infers reads: [signal:<name>]", async () => {
606
+ const source = `
607
+ import { on, flow, http, signal } from "okengine";
608
+
609
+ export const notify = signal("notify", { delivery: "once" });
610
+
611
+ export const failed = on(
612
+ http.get("/notifications/failed").gate.public,
613
+ flow("notifications.failed", {
614
+ do: async (input, fx) => fx.json.withQuery(await fx.deadLetters(notify), input),
615
+ }),
616
+ );
617
+ `;
618
+ const manifest = await extractFromSources({ "src/flows/failed.ts": source });
619
+ expect(manifest.flows?.["notifications.failed"]?.effects?.reads).toEqual(["signal:notify"]);
620
+ });
621
+ });
622
+
601
623
  describe("extractManifest — channel medium binder aliasing", () => {
602
624
  test("mail.template(...) resolves through `const mail = channel.email(...)`", async () => {
603
625
  const source = `
@@ -776,3 +798,34 @@ export const create = on(
776
798
  expect(manifest.gates?.WRITE).toBeUndefined();
777
799
  });
778
800
  });
801
+
802
+ describe("extractManifest — ai.mcpServer", () => {
803
+ test("stamps mcpServers and infers mcp: calls from .tool()", async () => {
804
+ const source = `
805
+ import { ai, flow, on, http, vault } from "okengine";
806
+
807
+ export const token = vault.secret("GITHUB_TOKEN");
808
+ export const github = ai.mcpServer("github", {
809
+ url: "https://mcp.example/github",
810
+ auth: { bearer: token },
811
+ tools: ["create_issue"],
812
+ });
813
+
814
+ export const triage = on(
815
+ http.post("/triage"),
816
+ flow("support.triage", {
817
+ do: async (input, fx) => {
818
+ await fx.ask("ticket-triage", input, { tools: [github.tool("create_issue")] });
819
+ },
820
+ }),
821
+ );
822
+ `;
823
+ const manifest = await extractFromSources({ "src/ai.ts": source });
824
+ expect(manifest.ai?.mcpServers?.github).toEqual({
825
+ url: "https://mcp.example/github",
826
+ auth: "GITHUB_TOKEN",
827
+ tools: ["create_issue"],
828
+ });
829
+ expect(manifest.flows?.["support.triage"]?.effects?.calls).toEqual(["mcp:github/create_issue"]);
830
+ });
831
+ });
@@ -11,6 +11,7 @@ import { parseSync } from "oxc-parser";
11
11
  import type {
12
12
  Ai,
13
13
  AiAgent,
14
+ AiMcpServer,
14
15
  AiModel,
15
16
  AiPrompt,
16
17
  Channel,
@@ -35,6 +36,7 @@ import { sqlTableRef } from "../manifest/sql-resource.ts";
35
36
  import {
36
37
  identifierName,
37
38
  inferEffects,
39
+ resolveCallTarget,
38
40
  stringArg,
39
41
  walk,
40
42
  type AstNode,
@@ -177,11 +179,12 @@ export async function extractManifest(options: ExtractManifestOptions = {}): Pro
177
179
  if (Object.keys(gates).length > 0) manifest.gates = gates;
178
180
  if (Object.keys(vault).length > 0) manifest.vault = vault;
179
181
  if (Object.keys(channels).length > 0) manifest.channels = channels;
180
- if (scope.ai.models || scope.ai.prompts || scope.ai.agents) {
182
+ if (scope.ai.models || scope.ai.prompts || scope.ai.agents || scope.ai.mcpServers) {
181
183
  manifest.ai = {
182
184
  ...(scope.ai.models ? { models: sortRecord(scope.ai.models) } : {}),
183
185
  ...(scope.ai.prompts ? { prompts: sortRecord(scope.ai.prompts) } : {}),
184
186
  ...(scope.ai.agents ? { agents: sortRecord(scope.ai.agents) } : {}),
187
+ ...(scope.ai.mcpServers ? { mcpServers: sortRecord(scope.ai.mcpServers) } : {}),
185
188
  };
186
189
  }
187
190
  if (Object.keys(journeys).length > 0) manifest.journeys = journeys;
@@ -301,6 +304,13 @@ function finalizeRefs(scope: ProjectScope): void {
301
304
  );
302
305
  }
303
306
  }
307
+ if (scope.ai.mcpServers) {
308
+ for (const server of Object.values(scope.ai.mcpServers)) {
309
+ if (!server.auth) continue;
310
+ const binding = scope.bindings.get(server.auth);
311
+ if (binding?.kind === "secret") server.auth = binding.ref;
312
+ }
313
+ }
304
314
  for (const journey of Object.values(scope.journeys)) {
305
315
  if (!journey.flows) continue;
306
316
  journey.flows = journey.flows.map(
@@ -816,6 +826,7 @@ function visitDeclarationCall(call: CallExpression, program: AstNode, scope: Pro
816
826
  const model: AiModel = {
817
827
  ...(stringProp(opts, "provider") ? { provider: stringProp(opts, "provider") } : {}),
818
828
  ...(stringProp(opts, "tier") ? { tier: stringProp(opts, "tier") } : {}),
829
+ ...(stringProp(opts, "driverId") ? { driverId: stringProp(opts, "driverId") } : {}),
819
830
  };
820
831
  scope.ai.models = scope.ai.models ?? {};
821
832
  scope.ai.models[modelName] = model;
@@ -833,6 +844,24 @@ function visitDeclarationCall(call: CallExpression, program: AstNode, scope: Pro
833
844
  collectAgent(call, scope);
834
845
  }
835
846
 
847
+ if (obj === "ai" && prop === "mcpServer") {
848
+ collectMcpServer(call, program, scope);
849
+ }
850
+
851
+ if (prop === "tool" && obj) {
852
+ const toolName = stringArg(call.arguments[0]);
853
+ const server = scope.bindings.get(obj);
854
+ if (server?.kind === "mcp-server" && toolName) {
855
+ const bindingName = enclosingConstName(call, program);
856
+ if (bindingName) {
857
+ scope.bindings.set(bindingName, {
858
+ kind: "mcp-tool",
859
+ ref: `mcp:${server.ref}/${toolName}`,
860
+ });
861
+ }
862
+ }
863
+ }
864
+
836
865
  if (obj === "ai" && prop === "embed") {
837
866
  const embedName = stringArg(call.arguments[0]);
838
867
  if (embedName) {
@@ -1026,7 +1055,11 @@ function collectAgent(call: CallExpression, scope: ProjectScope): void {
1026
1055
  if (!agentName || !opts) return;
1027
1056
  const toolsArr = arrayProp(opts, "tools");
1028
1057
  const tools = toolsArr
1029
- ?.map((el) => identifierName(el) ?? stringArg(el))
1058
+ ?.map((el) => {
1059
+ const resolved = resolveCallTarget(el, scope.bindings);
1060
+ if (resolved) return resolved;
1061
+ return identifierName(el) ?? stringArg(el);
1062
+ })
1030
1063
  .filter((x): x is string => typeof x === "string")
1031
1064
  .map((id) => scope.flowExports.get(id) ?? scope.bindings.get(id)?.ref ?? id);
1032
1065
  const agent: AiAgent = {
@@ -1039,6 +1072,40 @@ function collectAgent(call: CallExpression, scope: ProjectScope): void {
1039
1072
  scope.ai.agents[agentName] = agent;
1040
1073
  }
1041
1074
 
1075
+ function collectMcpServer(call: CallExpression, program: AstNode, scope: ProjectScope): void {
1076
+ const serverName = stringArg(call.arguments[0]);
1077
+ const opts = objectArg(call.arguments[1]);
1078
+ if (!serverName || !opts) return;
1079
+ const tools = stringArrayProp(opts, "tools") ?? [];
1080
+ const url = stringProp(opts, "url");
1081
+ const command = stringProp(opts, "command");
1082
+ const args = stringArrayProp(opts, "args");
1083
+ const authObj = objectProp(opts, "auth");
1084
+ const bearerNode = authObj ? objectProp(authObj, "bearer") : undefined;
1085
+ const bearerLit = stringArg(bearerNode);
1086
+ const bearerId = identifierName(bearerNode);
1087
+ const auth =
1088
+ bearerLit ??
1089
+ (bearerId
1090
+ ? scope.bindings.get(bearerId)?.kind === "secret"
1091
+ ? scope.bindings.get(bearerId)?.ref
1092
+ : bearerId
1093
+ : undefined);
1094
+ const server: AiMcpServer = {
1095
+ tools,
1096
+ ...(url ? { url } : {}),
1097
+ ...(command ? { command } : {}),
1098
+ ...(args && args.length > 0 ? { args } : {}),
1099
+ ...(auth ? { auth } : {}),
1100
+ };
1101
+ scope.ai.mcpServers = scope.ai.mcpServers ?? {};
1102
+ scope.ai.mcpServers[serverName] = server;
1103
+ const bindingName = enclosingConstName(call, program);
1104
+ if (bindingName) {
1105
+ scope.bindings.set(bindingName, { kind: "mcp-server", ref: serverName });
1106
+ }
1107
+ }
1108
+
1042
1109
  function collectConfig(opts: AstNode | undefined, scope: ProjectScope): void {
1043
1110
  if (!opts) return;
1044
1111
 
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import type { FlowFailure } from "../kernel/errors.ts";
8
- import { isJsonResult } from "../kernel/fx.ts";
8
+ import { isJsonResult, isJsonStreamResult, type JsonStreamResult } from "../kernel/fx.ts";
9
9
  import { isFlowFailure } from "../kernel/hooks.ts";
10
10
  import { VALIDATION_ERROR_CODE } from "../validation/standard-schema.ts";
11
11
 
@@ -53,6 +53,9 @@ export function statusForFailure(failure: FlowFailure): number {
53
53
  * @param output - Handler output (`undefined` → 204)
54
54
  */
55
55
  export function encodeSuccess(output: unknown): Response {
56
+ if (isJsonStreamResult(output)) {
57
+ return encodeSseStream(output);
58
+ }
56
59
  if (isJsonResult(output)) {
57
60
  if (output.status === 204) {
58
61
  return new Response(null, { status: 204 });
@@ -110,3 +113,44 @@ export function encodeExecuteResult(result: {
110
113
  }
111
114
  return encodeSuccess(result.output);
112
115
  }
116
+
117
+ /**
118
+ * Encode {@link JsonStreamResult} as SSE (`text/event-stream`).
119
+ *
120
+ * @param carrier - Stream carrier from `fx.json.stream`
121
+ */
122
+ function encodeSseStream(carrier: JsonStreamResult): Response {
123
+ const encoder = new TextEncoder();
124
+ let finalized = false;
125
+ const finish = async (): Promise<void> => {
126
+ if (finalized) return;
127
+ finalized = true;
128
+ await carrier.finalize?.();
129
+ };
130
+ const body = new ReadableStream<Uint8Array>({
131
+ async start(controller) {
132
+ try {
133
+ for await (const chunk of carrier.chunks) {
134
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`));
135
+ }
136
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
137
+ controller.close();
138
+ } catch (err) {
139
+ controller.error(err);
140
+ } finally {
141
+ await finish();
142
+ }
143
+ },
144
+ cancel() {
145
+ void finish();
146
+ },
147
+ });
148
+ return new Response(body, {
149
+ status: 200,
150
+ headers: {
151
+ "content-type": "text/event-stream; charset=utf-8",
152
+ "cache-control": "no-cache",
153
+ connection: "keep-alive",
154
+ },
155
+ });
156
+ }
@@ -459,7 +459,7 @@ function buildVersionMetrics(input: {
459
459
  costs: [],
460
460
  latencies: [],
461
461
  evals: [],
462
- outcomes: { ok: 0, provider_error: 0, schema_invalid: 0 },
462
+ outcomes: { ok: 0, provider_error: 0, schema_invalid: 0, budget_exceeded: 0 },
463
463
  overBudget: 0,
464
464
  budget: meta?.budget ?? null,
465
465
  };
@@ -514,7 +514,10 @@ function buildVersionMetrics(input: {
514
514
  const out: PromptVersionMetrics[] = [];
515
515
  for (const acc of map.values()) {
516
516
  const totalOutcomes =
517
- acc.outcomes.ok + acc.outcomes.provider_error + acc.outcomes.schema_invalid;
517
+ acc.outcomes.ok +
518
+ acc.outcomes.provider_error +
519
+ acc.outcomes.schema_invalid +
520
+ acc.outcomes.budget_exceeded;
518
521
  out.push({
519
522
  prompt: acc.prompt,
520
523
  version: acc.version,
@@ -834,6 +834,7 @@ const AiListOut = z.object({
834
834
  ok: z.number(),
835
835
  provider_error: z.number(),
836
836
  schema_invalid: z.number(),
837
+ budget_exceeded: z.number(),
837
838
  }),
838
839
  }),
839
840
  ),
@@ -244,7 +244,12 @@ export async function serveConsole(
244
244
  new Response("WebSocket upgrade failed", { status: 400 }),
245
245
  );
246
246
  }
247
- return fetchHandler(req);
247
+ return (async () => {
248
+ const res = await fetchHandler(req);
249
+ const ct = (res.headers.get("content-type") ?? "").split(";")[0]?.trim() ?? "";
250
+ if (/^text\/event-stream$/i.test(ct)) srv.timeout(req, 0);
251
+ return res;
252
+ })();
248
253
  },
249
254
  websocket: {
250
255
  open: live.open,
@@ -259,6 +264,15 @@ export async function serveConsole(
259
264
  boundHost.includes(":") && !boundHost.startsWith("[") ? `[${boundHost}]` : boundHost;
260
265
  const url = new URL(`http://${hostForUrl}:${boundPort}/`);
261
266
 
267
+ const closeIdle = (
268
+ server as typeof server & { closeIdleConnections(): void }
269
+ ).closeIdleConnections.bind(server);
270
+ const onPressure = (): void => {
271
+ closeIdle();
272
+ };
273
+ const proc = process as NodeJS.EventEmitter;
274
+ proc.on("memoryPressure", onPressure);
275
+
262
276
  return {
263
277
  console: handle,
264
278
  url,
@@ -266,9 +280,10 @@ export async function serveConsole(
266
280
  hostname: boundHost,
267
281
  fetch: fetchHandler,
268
282
  stop(closeActive = false) {
269
- server.stop(closeActive);
283
+ proc.off("memoryPressure", onPressure);
270
284
  void handle.app.stop();
271
285
  void persistence?.close();
286
+ return server.stop(closeActive);
272
287
  },
273
288
  };
274
289
  }
@@ -0,0 +1 @@
1
+ import{Cr as e,F as t,L as n,P as r,wr as i}from"./shortcut-keys-DO4IsVqv.js";import{A as a,f as o}from"./xyflow-D7n4g6go.js";import{t as s}from"./dagre.esm-ZwcdTuZZ.js";import{D as c,E as l,T as u,b as d,o as f,w as p,y as m}from"./http-method-CJCBYL2j.js";function h(e){let t=e.indexOf(`.`);return t===-1?e:e.slice(0,t)}function g(e){let t=e.indexOf(`.`);return t===-1?e:e.slice(t+1)}function _(e){let t=e?.flows??{},n=new Map;for(let e of Object.keys(t)){let r=t[e]?.effects?.calls??[];for(let t of r){let r=n.get(t)??[];r.push(e),n.set(t,r)}}for(let[e,t]of n)t.sort((e,t)=>e.localeCompare(t)),n.set(e,t);return n}function v(e,t){return _(e).get(t)??[]}function y(e){return e.startsWith(`sql:`)?{id:e,kind:`store`,label:e.slice(4),facet:`sql`}:e.startsWith(`kv:`)?{id:e,kind:`store`,label:e.slice(3),facet:`kv`}:e.startsWith(`files:`)?{id:e,kind:`store`,label:e.slice(6),facet:`files`}:e.startsWith(`index:`)?{id:e,kind:`store`,label:e.slice(6),facet:`index`}:e.startsWith(`signal:`)?{id:e,kind:`signal`,label:e.slice(7)}:e.startsWith(`ai:`)?{id:e,kind:`ai`,label:e.slice(3)}:e.startsWith(`vault:`)?{id:e,kind:`vault`,label:e.slice(6)}:e.startsWith(`channel:`)?{id:e,kind:`channel`,label:e.slice(8)}:e.startsWith(`gate:`)?{id:e,kind:`gate`,label:e.slice(5)}:e.startsWith(`clock:`)?{id:e,kind:`clock`,label:e.slice(6)}:null}function b(e,t,n,r,i=!1){let a=m[r];return{id:e,source:t,target:n,type:`smoothstep`,animated:i,data:{kind:r},style:{stroke:a,strokeWidth:r===`calls`?2.5:2.25},pathOptions:{borderRadius:28},zIndex:d.edge,markerEnd:{type:o.ArrowClosed,width:14,height:14,color:a}}}function x(e){let t=e?.flows??{},n=new Set(Object.keys(t)),r=[],i=new Map;for(let e of[...n].sort()){let t=h(e),n=i.get(t)??[];n.push(e),i.set(t,n)}let a=new Map,o=new Map;for(let e of n){let n=t[e];if(!n)continue;if(n.trigger?.signal){let t=`signal:${n.trigger.signal}`,i=y(t);i&&a.set(t,i),r.push(b(`e:${t}->flow:${e}`,t,`flow:${e}`,`trigger`))}if(n.trigger?.cron||n.trigger?.every){let t=`clock:${e}`,i=n.trigger.cron??n.trigger.every??e;a.set(t,{id:t,kind:`clock`,label:i,facet:n.trigger.cron?`cron`:`every`}),r.push(b(`e:${t}->flow:${e}`,t,`flow:${e}`,`trigger`))}for(let t of n.gates??[]){let n=`gate:${t}`;a.set(n,{id:n,kind:`gate`,label:t}),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}-gates->${n}`,`flow:${e}`,n,`gates`))}let i=n.effects;if(i){for(let t of i.reads??[]){let n=y(t);n&&(a.set(t,n),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}-reads->${t}`,`flow:${e}`,t,`reads`)))}for(let t of i.writes??[]){let n=y(t);n&&(a.set(t,n),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}-writes->${t}`,`flow:${e}`,t,`writes`)))}for(let t of i.emits??[]){let n=`signal:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`emits`)))}for(let t of i.asks??[]){let n=`ai:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`asks`)))}for(let t of i.sends??[]){let n=`channel:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`sends`)))}for(let t of i.secrets??[]){let n=`vault:${t}`,i=y(n);i&&(a.set(n,i),o.set(n,(o.get(n)??0)+1),r.push(b(`e:flow:${e}->${n}`,`flow:${e}`,n,`secrets`)))}for(let t of i.calls??[]){let n=c(t);if(n){let t=l(n.server);a.set(t,{id:t,kind:`ai`,label:n.server}),o.set(t,(o.get(t)??0)+1),r.push(b(`e:flow:${e}->${t}`,`flow:${e}`,t,`calls`,!0));continue}r.push(b(`e:flow:${e}->flow:${t}`,`flow:${e}`,`flow:${t}`,`calls`,!0))}}}return{nodes:S(i,t,a,o),edges:r,flowIds:n}}function S(e,t,n,r){let i=new s.graphlib.Graph({compound:!0});i.setGraph({rankdir:`LR`,align:`UL`,nodesep:16,ranksep:88,edgesep:12,marginx:8,marginy:8}),i.setDefaultEdgeLabel(()=>({}));for(let[t,n]of[...e.entries()].sort()){i.setNode(`unit:${t}`,{});for(let e of n)i.setNode(`flow:${e}`,{...p.flow}),i.setParent(`flow:${e}`,`unit:${t}`)}for(let e of n.values())i.setNode(e.id,{...p[e.kind]});let a=new Set;for(let n of e.values())for(let e of n){let n=t[e];if(!n)continue;let r=(e,t)=>{let n=`${e}->${t}`;a.has(n)||!i.hasNode(e)||!i.hasNode(t)||(a.add(n),i.setEdge(e,t))};n.trigger?.signal&&r(`signal:${n.trigger.signal}`,`flow:${e}`),(n.trigger?.cron||n.trigger?.every)&&r(`clock:${e}`,`flow:${e}`);for(let t of n.gates??[])r(`flow:${e}`,`gate:${t}`);let o=n.effects;if(o){for(let t of o.reads??[])r(`flow:${e}`,t);for(let t of o.writes??[])r(`flow:${e}`,t);for(let t of o.emits??[])r(`flow:${e}`,`signal:${t}`);for(let t of o.asks??[])r(`flow:${e}`,`ai:${t}`);for(let t of o.sends??[])r(`flow:${e}`,`channel:${t}`);for(let t of o.secrets??[])r(`flow:${e}`,`vault:${t}`);for(let t of o.calls??[]){let n=c(t);n?r(`flow:${e}`,l(n.server)):r(`flow:${e}`,`flow:${t}`)}}}s.layout(i);let o=[],{headerH:f,padX:m,padBottom:h}=u;for(let[n,r]of[...e.entries()].sort()){let e=`unit:${n}`,a=i.node(e);if(!a)continue;let s=a.x??0,c=a.y??0,l=r.length*p.flow.height+Math.max(0,r.length-1)*10,u=p.flow.width+m*2,_=f+l+h,v=s-u/2,y=c-_/2;o.push({id:e,type:`unit`,position:{x:v,y},data:{kind:`unit`,label:n,refId:e,badge:String(r.length)},selectable:!1,draggable:!1,zIndex:d.unit,width:u,height:_,style:{width:u,height:_}}),r.forEach((r,i)=>{let a=t[r];a&&o.push({id:`flow:${r}`,type:`flow`,position:{x:m,y:f+i*(p.flow.height+10)},parentId:e,extent:`parent`,zIndex:d.leaf,data:{kind:`flow`,label:g(r),refId:r,unit:n,plane:a.plane??`user`,badge:a.plane??`user`},draggable:!1,width:p.flow.width,height:p.flow.height,style:{width:p.flow.width,height:p.flow.height}})})}let _=[...n.values()].sort((e,t)=>e.kind.localeCompare(t.kind)||e.label.localeCompare(t.label));for(let e of _){let t=i.node(e.id),n=p[e.kind],a=r.get(e.id)??0;o.push({id:e.id,type:e.kind,position:{x:(t?.x??0)-n.width/2,y:(t?.y??0)-n.height/2},data:{kind:e.kind,label:e.label,refId:e.id,...e.facet===void 0?{}:{facet:e.facet},badge:e.facet??(a>0?String(a):e.kind)},draggable:!1,zIndex:d.leaf,width:n.width,height:n.height,style:{width:n.width,height:n.height}})}return o}function C(e,t,n,r={}){let i=t.size>0||n.size>0;return e.map(e=>{if(e.data.kind===`unit`||e.data.kind===`law`)return e;let a=e.data.kind===`flow`?t.has(e.data.refId):n.has(e.id);return{...e,data:{...e.data,highlighted:a,dimmed:i&&!a,active:r.activeNodeId!=null&&e.id===r.activeNodeId,focused:r.focusedNodeId!=null&&e.id===r.focusedNodeId}}})}function w(e,t){let n=new Map(t.map(e=>[e.id,e]));return t.some(e=>e.data.highlighted===!0)?e.map(e=>{let t=n.get(e.source),r=n.get(e.target),i=t?.data.highlighted===!0&&r?.data.highlighted===!0,a=m[e.data?.kind??`reads`];return{...e,animated:i?!0:e.animated,style:{...e.style,stroke:a,opacity:i?1:.32,strokeWidth:i?2.75:1.75},markerEnd:e.markerEnd&&typeof e.markerEnd==`object`?{...e.markerEnd,color:a}:e.markerEnd}}):e.map(e=>({...e,style:{...e.style,opacity:1}}))}var T=100;function E(e,t){return e.filter(e=>t.has(e.flow)).sort((e,t)=>t.startedAt-e.startedAt).slice(0,T)}var D=a();function O({cache:a,dataSlot:o}){let s=f(a);return(0,D.jsxs)(r,{children:[(0,D.jsx)(n,{render:t=>(0,D.jsx)(`span`,{...t,className:e(`flex w-4 shrink-0 items-center justify-center`,s.className),"data-slot":o,"data-cache":a,"aria-label":s.label,children:(0,D.jsx)(i,{icon:s.icon,className:`size-3`,"aria-hidden":!0})})}),(0,D.jsx)(t,{side:`top`,children:s.label})]})}export{w as a,h as c,C as i,E as n,x as o,g as r,v as s,O as t};
@@ -0,0 +1 @@
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{Ai as t,Cr as n,Do as r,E as i,F as a,L as o,P as s,S as c,_r as l,ar as u,br as d,cr as f,gr as p,hr as m,kr as h,mr as g,qr as _,si as v,vr as y,wr as b,zr as x}from"./shortcut-keys-DO4IsVqv.js";import{r as S}from"./react-dom-Bph1y7z7.js";import{A as C,a as w,c as T,d as E,o as D,p as O,r as k,s as A,t as ee}from"./xyflow-D7n4g6go.js";import{n as te,t as ne}from"./react-B1ML8gxg.js";import{t as re}from"./duration-tone-oiRxPVsZ.js";import{a as ie,i as ae,n as oe,o as se,r as ce,t as le}from"./trace-detail-sheet-DFLFfUUX.js";import{r as ue}from"./preload-helper-oH4irX4C.js";import{t as de,u as fe}from"./index-Ce6WKWKM.js";import{a as pe,c as me,d as j,f as he,g as ge,h as _e,l as ve,m as ye,o as be,p as xe,s as Se,u as Ce}from"./collapsible-DYb0xU8C.js";import{a as we,c as Te,i as Ee,l as De,o as Oe,s as ke}from"./highlighted-json-CvDPvveV.js";import{C as M,D as Ae,E as je,S as N,_ as Me,b as P,g as Ne,h as Pe,w as Fe,x as F,y as I}from"./http-method-CJCBYL2j.js";import{a as Ie,c as L,i as Le,n as Re,o as ze,r as Be,t as Ve}from"./cache-glyph-BanhLsEY.js";var R=e(S(),1),z=[`flow`,`signal`,`store`,`clock`,`gate`,`vault`,`channel`,`ai`];function B(e,t,n){return{x:F.cx+t*Math.cos(e)-n.width/2,y:F.cy+t*Math.sin(e)-n.height/2}}function V(e){if(e<=0)return[];let t=2*Math.PI/e;return Array.from({length:e},(e,n)=>-Math.PI/2+n*t)}var He=2*Math.PI/z.length;function H(e,t,n=F.typeRing){if(t<=0)return[];if(t===1)return[e];let r=(N.type.width+10)/n,i=Math.min(r*(t-1),He*.7);return Array.from({length:t},(n,r)=>e-i/2+r/(t-1)*i)}function Ue(e,t){if(t<=0)return[];let n=F.typeRing,r=F.typeRing+F.typeRow;if(t===1)return[{angle:e,radius:n}];if(t===4)return Ge(e,n,r);if(t<=3)return H(e,t,n).map(e=>({angle:e,radius:n}));let i=Math.ceil(t/2),a=t-i;return[...H(e,i,n).map(e=>({angle:e,radius:n})),...H(e,a,r).map(e=>({angle:e,radius:r}))]}function We(e){return Math.abs(Math.cos(e))*N.type.height+Math.abs(Math.sin(e))*N.type.width}function Ge(e,t,n){let r=(We(e)+24)/t;return[{angle:e-r/2,radius:t},{angle:e+r/2,radius:t},{angle:e-r/2,radius:n},{angle:e+r/2,radius:n}]}function Ke(e){let t=new Set([`flow`]),n=e.trigger;(n?.cron||n?.every)&&t.add(`clock`),n?.signal&&t.add(`signal`),(e.gates?.length??0)>0&&t.add(`gate`);let r=e.effects;return((r?.reads?.length??0)>0||(r?.writes?.length??0)>0)&&t.add(`store`),(r?.emits?.length??0)>0&&t.add(`signal`),(r?.sends?.length??0)>0&&t.add(`channel`),(r?.asks?.length??0)>0&&t.add(`ai`),(r?.secrets?.length??0)>0&&t.add(`vault`),z.filter(e=>t.has(e))}function qe(e){let t=new Set([`flow`]);(e.trigger===`cron`||e.trigger===`every`)&&t.add(`clock`),e.trigger===`signal`&&t.add(`signal`),e.gates.length>0&&t.add(`gate`);for(let n of e.effects)switch(n.kind){case`read`:case`write`:t.add(`store`);break;case`emit`:t.add(`signal`);break;case`send`:t.add(`channel`);break;case`ask`:t.add(`ai`);break;case`secret`:t.add(`vault`)}return z.filter(e=>t.has(e))}function Je(e,t){let n=new Map,r=(e,t,r)=>{n.has(e)||n.set(e,r===void 0?{id:e,label:t}:{id:e,label:t,badge:r})};switch(t){case`flow`:for(let t of Object.keys(e.flows??{}).sort())r(`flow:${t}`,Be(t),L(t));break;case`signal`:for(let t of Object.keys(e.signals??{}).sort())r(`signal:${t}`,t,`signal`);for(let t of Object.values(e.flows??{})){t.trigger?.signal&&r(`signal:${t.trigger.signal}`,t.trigger.signal,`signal`);for(let e of t.effects?.emits??[])r(`signal:${e}`,e,`signal`)}break;case`store`:for(let[t,n]of Object.entries(e.stores??{})){let e=n.facet;for(let t of Object.keys(n.tables??{}).sort())r(`${e}:${t}`,t,e);let i=n.namespaces&&n.namespaces.length>0?n.namespaces:[];e===`kv`&&i.length===0&&r(`kv:${t}`,t,`kv`);for(let e of[...i].sort())r(`kv:${e}`,e,`kv`);for(let e of[...n.buckets??[]].sort())r(`files:${e}`,e,`files`);for(let e of[...n.indexes??[]].sort())r(`index:${e}`,e,`index`)}for(let t of Object.values(e.flows??{}))for(let e of[...t.effects?.reads??[],...t.effects?.writes??[]]){let t=Ye(e);t&&r(t.id,t.label,t.badge)}break;case`clock`:for(let[t,n]of Object.entries(e.clocks??{}).sort(([e],[t])=>e.localeCompare(t)))r(`clock:${t}`,t,n.cron?`cron`:n.every?`every`:`clock`);for(let[t,n]of Object.entries(e.flows??{}))n.trigger?.cron&&r(`clock:${t}`,n.trigger.cron,`cron`),n.trigger?.every&&r(`clock:${t}`,n.trigger.every,`every`);break;case`gate`:for(let t of Object.keys(e.gates??{}).sort())r(`gate:${t}`,t,`gate`);for(let t of Object.values(e.flows??{}))for(let e of t.gates??[])r(`gate:${e}`,e,`gate`);break;case`vault`:for(let t of Object.keys(e.vault??{}).sort())r(`vault:${t}`,t,`vault`);for(let t of Object.values(e.flows??{}))for(let e of t.effects?.secrets??[])r(`vault:${e}`,e,`vault`);break;case`channel`:for(let t of Object.keys(e.channels??{}).sort())r(`channel:${t}`,t,`channel`);for(let t of Object.values(e.flows??{}))for(let e of t.effects?.sends??[])r(`channel:${e}`,e,`channel`);break;case`ai`:for(let t of Object.keys(e.ai?.prompts??{}).sort())r(`ai:${t}`,t,`prompt`);for(let t of Object.keys(e.ai?.agents??{}).sort())r(`ai:${t}`,t,`agent`);for(let t of Object.values(e.flows??{}))for(let e of t.effects?.asks??[])r(`ai:${e}`,e,`prompt`)}return[...n.values()].sort((e,t)=>e.label.localeCompare(t.label))}function Ye(e){return e.startsWith(`sql:`)?{id:e,label:e.slice(4),badge:`sql`}:e.startsWith(`kv:`)?{id:e,label:e.slice(3),badge:`kv`}:e.startsWith(`files:`)?{id:e,label:e.slice(6),badge:`files`}:e.startsWith(`index:`)?{id:e,label:e.slice(6),badge:`index`}:null}var Xe={flow:Pe.map(e=>({kind:e,label:Ne[e].label})),signal:[{kind:`once`,label:`once`},{kind:`broadcast`,label:`broadcast`},{kind:`live`,label:`live`}],store:[{kind:`sql`,label:`SQL`},{kind:`kv`,label:`KV`},{kind:`files`,label:`Files`},{kind:`index`,label:`Index`}],clock:[{kind:`cron`,label:`cron`},{kind:`every`,label:`every`}],gate:[{kind:`policy`,label:`policy`},{kind:`scope`,label:`scope`},{kind:`rate`,label:`rate`},{kind:`flag`,label:`flag`}],vault:[{kind:`secret`,label:`secret`},{kind:`config`,label:`config`},{kind:`env`,label:`env`}],channel:[{kind:`email`,label:`email`},{kind:`sms`,label:`SMS`},{kind:`whatsapp`,label:`WA`},{kind:`push`,label:`Push`}],ai:[{kind:`model`,label:`model`},{kind:`prompt`,label:`prompt`},{kind:`embed`,label:`embed`},{kind:`agent`,label:`agent`}]};function Ze(e,t){return Xe[t].map(e=>({id:`type:${t}:${e.kind}`,label:e.label,badge:e.kind}))}function Qe(e,t){return t?.kind===`rate`||e.startsWith(`rate:`)?`rate`:e.startsWith(`flag:`)?`flag`:(t?.scopes?.length??0)>0?`scope`:`policy`}function $e(e){return e?.sensitive===!1?`config`:`secret`}function et(e,t){let n=t.split(`@`)[0]??t;return e.ai?.agents?.[n]?`agent`:e.ai?.models?.[n]?`model`:`prompt`}function tt(e,t,n){let r=`type:${n}:`;switch(n){case`flow`:return[`${r}${Me(t.trigger)}`];case`store`:{let e=new Set;for(let n of[...t.effects?.reads??[],...t.effects?.writes??[]]){let t=Ye(n);t?.badge&&e.add(t.badge)}return[...e].map(e=>`${r}${e}`)}case`signal`:{let n=[...t.trigger?.signal?[t.trigger.signal]:[],...t.effects?.emits??[]],i=new Set;for(let t of n){let n=e.signals?.[t]?.delivery;n&&i.add(n)}return[...i].map(e=>`${r}${e}`)}case`clock`:{let e=[];return t.trigger?.cron&&e.push(`${r}cron`),t.trigger?.every&&e.push(`${r}every`),e}case`gate`:return[...new Set((t.gates??[]).map(t=>Qe(t,e.gates?.[t])))].map(e=>`${r}${e}`);case`vault`:return[...new Set((t.effects?.secrets??[]).map(t=>$e(e.vault?.[t])))].map(e=>`${r}${e}`);case`channel`:{let n=new Set;for(let r of t.effects?.sends??[]){let t=e.channels?.[r]?.medium;t&&t!==`any`&&n.add(t)}return[...n].map(e=>`${r}${e}`)}case`ai`:return[...new Set((t.effects?.asks??[]).map(t=>et(e,t)))].map(e=>`${r}${e}`)}}function nt(e){let t=e?.flows??{},n=new Map;for(let e of Object.keys(t).sort()){let t=L(e),r=n.get(t)??[];r.push(e),n.set(t,r)}let r=new Map,i=new Map,a=new Map;for(let[e,o]of n){let n=new Set;for(let i of o){let o=t[i];if(o)for(let t of Ke(o)){n.add(t);let o=`${e}\0${t}`;r.set(o,(r.get(o)??0)+1);let s=a.get(t)??new Set;s.add(i),a.set(t,s)}}i.set(e,n)}let o=[...n.entries()].sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>({unit:e,flowCount:t.length,elements:z.filter(t=>i.get(e)?.has(t)),live:0,errors:0})),s=z.map(t=>({element:t,resourceCount:e?Je(e,t).length:0,flowCount:a.get(t)?.size??0,live:0,errors:0})),c=[];for(let e of o)for(let t of e.elements)c.push({unit:e.unit,element:t,flowCount:r.get(`${e.unit}\0${t}`)??0});return{units:o,hubs:s,couplings:c}}function rt(e,t){let n=new Map,r=new Map,i=new Map,a=new Map;for(let e of t){let t=e.unit??L(e.flow);n.set(t,(n.get(t)??0)+1),e.error&&r.set(t,(r.get(t)??0)+1);for(let t of qe(e))i.set(t,(i.get(t)??0)+1),e.error&&a.set(t,(a.get(t)??0)+1)}return{couplings:e.couplings,units:e.units.map(e=>({...e,live:n.get(e.unit)??0,errors:r.get(e.unit)??0})),hubs:e.hubs.map(e=>({...e,live:i.get(e.element)??0,errors:a.get(e.element)??0}))}}function it(e,t=[],n=null){if(!e||Object.keys(e.flows??{}).length===0)return{nodes:[],edges:[],units:[],hubs:[]};let r=rt(nt(e),t),i=n?.element,a=r.hubs.find(e=>e.element===`flow`)?.live??0,o=r.hubs.find(e=>e.element===`flow`)?.errors??0,s=[],c=[];s.push(at(`orbit:elements`,F.elementRing)),s.push(at(`orbit:types`,F.typeRing)),s.push(at(`orbit:spokes`,F.spokeRing)),s.push({id:`law:oke`,type:`law`,position:{x:F.cx-N.law.width/2,y:F.cy-N.law.height/2},data:{kind:`law`,label:e.app,refId:`oke`,badge:String(r.units.reduce((e,t)=>e+t.flowCount,0)),live:a,errors:o},selectable:!1,draggable:!1,zIndex:P.leaf,width:N.law.width,height:N.law.height,style:{width:N.law.width,height:N.law.height,overflow:`visible`}});let l=V(z.length);if(r.hubs.forEach((e,t)=>{let n=l[t]??0,r=N.hub;s.push({id:`element:${e.element}`,type:`element`,position:B(n,F.elementRing,r),data:{kind:`element`,label:j[e.element].symbol,refId:e.element,badge:String(e.resourceCount),live:e.live,errors:e.errors,dimmed:i!=null&&e.element!==i},draggable:!1,zIndex:P.leaf,width:r.width,height:r.height,style:{width:r.width,height:r.height}}),c.push(U(`element:${e.element}`,`law:oke`,e.element,1,!0))}),!i||i===`flow`){let t=N.type;r.hubs.forEach((n,r)=>{let i=l[r]??0,a=Ze(e,n.element),o=Ue(i,a.length);a.forEach((e,r)=>{let a=o[r]??{angle:i,radius:F.typeRing};s.push({id:e.id,type:`typeChip`,position:B(a.angle,a.radius,t),data:{kind:n.element,label:e.label,refId:e.id,...e.badge===void 0?{}:{badge:e.badge,facet:e.badge}},draggable:!1,zIndex:P.leaf,width:t.width,height:t.height,style:{width:t.width,height:t.height}}),c.push(U(e.id,`element:${n.element}`,n.element,1))})})}if(i&&i!==`flow`){let t=Je(e,i),n=Fe.store,r=V(t.length);t.forEach((e,t)=>{let a=r[t]??0;s.push({id:e.id,type:i,position:B(a,F.spokeRing,n),data:{kind:i,label:e.label,refId:e.id,...e.badge===void 0?{}:{badge:e.badge,facet:e.badge}},draggable:!1,zIndex:P.leaf,width:n.width,height:n.height,style:{width:n.width,height:n.height}}),c.push(U(e.id,`element:${i}`,i,1))})}else{let t=N.unit,n=V(r.units.length);r.units.forEach((e,r)=>{let i=n[r]??0;s.push({id:`unit:${e.unit}`,type:`unitChip`,position:B(i,F.spokeRing,t),data:{kind:`unit`,label:e.unit,refId:e.unit,badge:String(e.flowCount),elements:e.elements.filter(e=>e!==`flow`),live:e.live,errors:e.errors},draggable:!1,zIndex:P.leaf,width:t.width,height:t.height,style:{width:t.width,height:t.height}})});let a=new Map;for(let t of Object.keys(e.flows??{}).sort()){let e=L(t),n=a.get(e)??[];n.push(t),a.set(e,n)}for(let t of r.units){let n=new Map,r=new Set;for(let o of a.get(t.unit)??[]){let t=e.flows?.[o];if(t)for(let a of Ke(t)){if(i===`flow`&&a!==`flow`)continue;let o=tt(e,t,a);o.length===0&&r.add(a);for(let e of o)n.set(e,(n.get(e)??0)+1)}}for(let[e,r]of n){let n=e.slice(5).split(`:`)[0];!n||!(n in M)||c.push(U(`unit:${t.unit}`,e,n,r))}for(let e of r)c.push(U(`unit:${t.unit}`,`element:${e}`,e,1))}}return{nodes:s,edges:c,units:r.units,hubs:r.hubs}}function at(e,t){let n=t*2;return{id:e,type:`orbit`,position:{x:F.cx-t,y:F.cy-t},data:{kind:`law`,label:``,refId:e},selectable:!1,draggable:!1,zIndex:P.edge,width:n,height:n,style:{width:n,height:n}}}function ot(e,t){return t===`law:oke`?`trunk`:e.startsWith(`type:`)&&t.startsWith(`element:`)?`bind`:`spoke`}function st(e){return e===`trunk`?.14:e===`bind`?.2:0}function U(e,t,n,r,i=!1){let a=i?`trunk`:ot(e,t),o=a===`trunk`?1.15:1+Math.min(1.25,Math.log2(1+r)*.45);return{id:`couple:${e}->${t}`,source:e,target:t,sourceHandle:`center`,targetHandle:`center`,type:`straight`,data:{kind:`couple`},style:{stroke:I.couple,strokeWidth:o,opacity:st(a)},zIndex:P.edge}}function ct(e){if(e.startsWith(`element:`)){let t=e.slice(8);return t in M?t:null}if(e.startsWith(`type:`)){let t=e.slice(5).split(`:`)[0];return t&&t in M?t:null}return null}function lt(e,t){for(let n of[t,e]){let e=ct(n);if(e)return M[e].accent}return I.couple}function ut(e,t){let n=new Set,r=new Set,i=(e,t)=>{r.add(`couple:${e}->${t}`)};if(!e)return{nodeIds:n,edgeIds:r};for(let r of t){let t=e.flows?.[r];if(!t)continue;let a=`unit:${L(r)}`;n.add(a);for(let r of Ke(t)){let o=`element:${r}`;n.add(o),n.add(`law:oke`),i(o,`law:oke`);let s=tt(e,t,r);s.length===0&&i(a,o);for(let e of s)n.add(e),i(a,e),i(e,o)}}return{nodeIds:n,edgeIds:r}}function dt(e,t,n={}){let r=n.hoverNodeId??null,i=n.highlightedFlowIds??new Set,a=n.highlightedNodeIds??new Set,o=ut(n.manifest,i),s=o.nodeIds.size>0||a.size>0,c=r!=null,l=r==null?null:ft(r,t);return{nodes:e.map(e=>{if(e.type===`orbit`)return{...e,data:{...e.data,highlighted:!1,dimmed:!1}};let t=o.nodeIds.has(e.id)||a.has(e.id)||i.has(e.data.refId),n=l?.has(e.id)===!0;return{...e,data:{...e.data,highlighted:t||c&&e.id===r,dimmed:e.id===`law:oke`?!1:s&&!t||c&&!n}}}),edges:t.map(e=>{let t=l!=null&&l.has(e.source)&&l.has(e.target),n=s&&o.edgeIds.has(e.id),r=c?t:n,i=ot(e.source,e.target),a=c||s?r?1:st(i)*.35:st(i);return{...e,animated:r,style:{...e.style,stroke:r?lt(e.source,e.target):I.couple,opacity:a,strokeWidth:r?2.25:e.style?.strokeWidth}}})}}function W(e,t){let n=[];for(let r of e)r.source===t?n.push(r.target):r.target===t&&n.push(r.source);return n}function ft(e,t){let n=new Set([e]),r=e=>n.add(e);if(e.startsWith(`unit:`)){for(let n of W(t,e)){if(r(n),n.startsWith(`type:`)){for(let e of W(t,n))if(e.startsWith(`element:`)){r(e);for(let n of W(t,e))n===`law:oke`&&r(n)}}if(n.startsWith(`element:`))for(let e of W(t,n))e===`law:oke`&&r(e)}return n}if(e.startsWith(`type:`)){for(let n of W(t,e))r(n);let i=[...n].find(e=>e.startsWith(`element:`));if(i)for(let e of W(t,i))e===`law:oke`&&r(e);return n}if(e.startsWith(`element:`)||e===`law:oke`)for(let n of W(t,e))r(n);return n}var G=C(),pt={flow:j.flow.icon,signal:j.signal.icon,store:j.store.icon,clock:j.clock.icon,gate:j.gate.icon,vault:j.vault.icon,channel:j.channel.icon,ai:j.ai.icon},mt={flow:`rounded-xl`,store:`rounded-md`,signal:`rounded-full`,clock:`rounded-lg`,gate:`rounded-md`,vault:`rounded-md`,channel:`rounded-xl`,ai:`rounded-2xl`};function K(e,t){return n(`group relative flex h-full w-full items-center gap-2.5 border-2 px-2.5 text-xs transition-[opacity,filter,box-shadow,border-color] duration-200`,mt[t],e.dimmed&&`opacity-30 saturate-[0.35]`,e.highlighted&&`z-10`,e.focused&&`z-10`)}function q(e,t){let n=M[e],r=`color-mix(in oklab, ${n.accent} 20%, var(--card))`;return t.highlighted||t.focused?{borderColor:n.accent,background:`color-mix(in oklab, ${n.accent} 26%, var(--card))`,boxShadow:`0 0 0 1px ${n.accent}, 0 0 22px ${n.glow}`}:{borderColor:`color-mix(in oklab, ${n.accent} 78%, var(--border))`,background:r,boxShadow:`inset 3px 0 0 ${n.accent}`}}function J({data:e,kind:t,className:n,style:r,children:i,...a}){let o=te(),s=M[t];return(0,G.jsx)(ne.div,{className:n,style:r,initial:!1,whileHover:o?void 0:{scale:1.04},whileTap:o?void 0:{scale:.97},animate:{scale:o?1:e.active?[1,1.08,1]:e.highlighted?1.02:1,boxShadow:e.active?`0 0 0 2px ${s.accent}, 0 0 30px ${s.glow}`:void 0},transition:e.active?{duration:.5,ease:`easeInOut`}:{type:`spring`,stiffness:400,damping:28},...a,children:i})}function ht({kind:e,size:t=`sm`}){let r=M[e];return(0,G.jsx)(`span`,{className:n(`flex shrink-0 items-center justify-center border`,t===`md`?`size-9`:`size-7`,e===`signal`?`rounded-full`:e===`store`||e===`gate`||e===`vault`?`rounded-md`:`rounded-full`),style:{color:r.accent,background:r.well,borderColor:`color-mix(in oklab, ${r.accent} 55%, transparent)`},"aria-hidden":!0,children:(0,G.jsx)(b,{icon:pt[e],size:t===`md`?17:15,strokeWidth:1.9})})}function gt({text:e}){return(0,G.jsx)(`span`,{className:`rounded border border-border/70 bg-background/50 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-[0.16em] text-muted-foreground`,children:e})}function _t({type:e,kind:t}){let n=M[t];return(0,G.jsx)(w,{type:e,position:e===`source`?O.Right:O.Left,className:`!size-2 !border-0`,style:{background:n.accent}})}function Y({type:e}){return(0,G.jsx)(w,{id:`center`,type:e,position:e===`source`?O.Right:O.Left,isConnectable:!1,className:`oke-center-handle !top-1/2 !left-1/2 !size-px !-translate-x-1/2 !-translate-y-1/2 !border-0 !bg-transparent !opacity-0`})}function vt({live:e,errors:t}){return e<=0?null:(0,G.jsx)(`span`,{className:n(`size-2 shrink-0 rounded-full`,t>0?`bg-rose-400`:`bg-emerald-400`,e>0&&`animate-pulse`),title:t>0?`${e} live · ${t} failed`:`${e} live`})}function yt({elements:e}){return e.length===0?null:(0,G.jsx)(`span`,{className:`mt-0.5 flex items-center gap-1`,"aria-hidden":!0,children:e.map(e=>(0,G.jsx)(`span`,{className:`size-1.5 rounded-full`,style:{background:M[e].accent},title:j[e].label},e))})}function bt({data:e}){return(0,G.jsx)(`div`,{className:`h-full w-full rounded-xl border border-dashed border-foreground/25 bg-muted/35 px-3 pt-1.5`,children:(0,G.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,G.jsx)(`div`,{className:`text-[10px] font-semibold uppercase tracking-[0.2em] text-muted-foreground`,children:e.label}),e.badge?(0,G.jsx)(gt,{text:e.badge}):null]})})}function xt({data:e}){let t=e.kind in M?e.kind:`flow`;return(0,G.jsxs)(J,{data:e,kind:t,className:n(K(e,t),`justify-center gap-0 rounded-full px-2`),style:q(t,e),"data-slot":`type-chip`,"data-type":e.refId,children:[(0,G.jsx)(Y,{type:`source`}),(0,G.jsx)(Y,{type:`target`}),(0,G.jsx)(`div`,{className:`min-w-0 truncate text-center text-[10px] leading-none font-medium tracking-wide text-foreground`,children:e.label})]})}function St({data:e}){return(0,G.jsxs)(J,{data:e,kind:`flow`,className:n(K(e,`flow`),`rounded-full px-2.5`),style:q(`flow`,e),"data-slot":`unit-chip`,"data-unit":e.refId,children:[(0,G.jsx)(Y,{type:`source`}),(0,G.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,G.jsx)(`div`,{className:`truncate font-medium tracking-wide text-foreground uppercase`,children:e.label}),(0,G.jsx)(vt,{live:e.live??0,errors:e.errors??0})]}),(0,G.jsx)(yt,{elements:e.elements??[]})]}),e.badge?(0,G.jsx)(gt,{text:e.badge}):null]})}function Ct({data:e}){let t=Dt(e.refId)??`flow`,r=M[t];return(0,G.jsxs)(J,{data:e,kind:t,className:n(K(e,t),`flex-col justify-center gap-0.5 rounded-full px-1.5 text-center`),style:{...q(t,e),boxShadow:e.highlighted?`0 0 0 1px ${r.accent}, 0 0 22px ${r.glow}`:`0 0 0 1px color-mix(in oklab, ${r.accent} 55%, transparent)`},"data-slot":`element-hub`,"data-element":t,children:[(0,G.jsx)(Y,{type:`target`}),(0,G.jsx)(Y,{type:`source`}),(0,G.jsx)(`span`,{className:`text-[18px] font-semibold tracking-tight text-foreground`,title:j[t].label,children:e.label})]})}function wt(e){return e>=40?1.05:e>=12?1.55:2.2}function Tt({data:e}){let t=te(),r=e.live??0,i=e.errors??0,[a,o]=(0,R.useState)(0),s=(0,R.useRef)(r);(0,R.useEffect)(()=>{r>s.current&&o(e=>e+1),s.current=r},[r]);let c=r>0,l=wt(r),u=i>0?`var(--color-rose-400)`:`var(--foreground)`;return(0,G.jsxs)(`div`,{className:n(`relative flex h-full w-full items-center justify-center overflow-visible`,e.highlighted&&`z-10`),"data-slot":`law-hub`,"data-live":r,children:[(0,G.jsx)(Y,{type:`target`}),!t&&c?(0,G.jsxs)(G.Fragment,{children:[(0,G.jsx)(`span`,{"aria-hidden":!0,className:`oke-law-ripple`,style:{animationDuration:`${l}s`,color:u}}),(0,G.jsx)(`span`,{"aria-hidden":!0,className:`oke-law-ripple`,style:{animationDuration:`${l}s`,animationDelay:`${l/2}s`,color:u}})]}):null,a>0&&!t?(0,G.jsx)(`span`,{"aria-hidden":!0,className:`oke-law-hit`,style:{color:u}},a):null,(0,G.jsx)(ne.div,{className:`flex h-full w-full items-center justify-center rounded-full border-4 bg-card px-4 text-center`,style:{borderColor:`color-mix(in oklab, var(--foreground) 82%, var(--border))`,boxShadow:e.highlighted?`0 0 0 1px ${u}, 0 0 36px color-mix(in oklab, ${u} 28%, transparent)`:`inset 0 0 28px color-mix(in oklab, var(--foreground) 7%, transparent), 0 0 22px color-mix(in oklab, ${u} ${c?16:6}%, transparent)`},animate:t||!c?{scale:1}:{scale:[1,1.045,1]},transition:t||!c?{duration:0}:{duration:l,repeat:1/0,ease:`easeInOut`},children:(0,G.jsx)(de,{className:`h-7 w-auto text-foreground`})})]})}function Et(){return(0,G.jsx)(`div`,{className:`pointer-events-none h-full w-full rounded-full border border-dashed border-foreground/15`,"data-slot":`orbit`})}function Dt(e){return e in M?e:null}function X({data:e,kind:t,slot:n}){return(0,G.jsxs)(J,{data:e,kind:t,className:K(e,t),style:q(t,e),"data-slot":n,"data-flow-id":t===`flow`?e.refId:void 0,"data-highlighted":e.highlighted?`true`:`false`,children:[(0,G.jsx)(_t,{type:`target`,kind:t}),(0,G.jsx)(Y,{type:`source`}),(0,G.jsx)(ht,{kind:t}),(0,G.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,G.jsx)(`div`,{className:`truncate font-medium text-foreground`,children:e.label}),(0,G.jsx)(`div`,{className:`mt-0.5 flex items-center gap-1.5`,children:(0,G.jsx)(gt,{text:e.badge??e.plane??e.facet??t})})]}),t===`flow`||t===`signal`?(0,G.jsx)(_t,{type:`source`,kind:t}):null]})}function Ot({data:e}){return(0,G.jsx)(X,{data:e,kind:`flow`,slot:`flow-node`})}function kt({data:e}){return(0,G.jsx)(X,{data:e,kind:`store`,slot:`store-node`})}function At({data:e}){return(0,G.jsx)(X,{data:e,kind:`signal`,slot:`signal-node`})}function jt({data:e}){return(0,G.jsx)(X,{data:e,kind:`ai`,slot:`ai-node`})}function Mt({data:e}){return(0,G.jsx)(X,{data:e,kind:`clock`,slot:`clock-node`})}function Nt({data:e}){return(0,G.jsx)(X,{data:e,kind:`gate`,slot:`gate-node`})}function Pt({data:e}){return(0,G.jsx)(X,{data:e,kind:`vault`,slot:`vault-node`})}function Ft({data:e}){return(0,G.jsx)(X,{data:e,kind:`channel`,slot:`channel-node`})}var It={unit:bt,unitChip:St,typeChip:xt,element:Ct,law:Tt,orbit:Et,flow:Ot,store:kt,signal:At,ai:jt,clock:Mt,gate:Nt,vault:Pt,channel:Ft};function Lt(e,t){let n=e.flows??{},r=new Set;if(t.kind===`unit`){for(let e of Object.keys(n))L(e)===t.unit&&r.add(e);let e=[];for(let t of r)for(let r of n[t]?.effects?.calls??[])Ae(r)||e.push(r);for(let t of e)r.add(t)}else if(t.kind===`flow`){r.add(t.flowId);let e=n[t.flowId];for(let t of e?.effects?.calls??[])Ae(t)||r.add(t);for(let[e,i]of Object.entries(n))i.effects?.calls?.includes(t.flowId)&&r.add(e)}else for(let[e,i]of Object.entries(n))Rt(i,e,t.nodeId)&&r.add(e);let i={};for(let e of r){let t=n[e];t&&(i[e]=t)}return{...e,flows:i}}function Rt(e,t,n){if(n===`flow:${t}`||n===`clock:${t}`&&(e.trigger?.cron||e.trigger?.every)||e.trigger?.signal&&n===`signal:${e.trigger.signal}`||e.gates?.some(e=>n===`gate:${e}`))return!0;let r=e.effects;return r?!!(r.reads?.some(e=>e===n)||r.writes?.some(e=>e===n)||r.emits?.some(e=>n===`signal:${e}`)||r.sends?.some(e=>n===`channel:${e}`)||r.asks?.some(e=>n===`ai:${e}`)||r.secrets?.some(e=>n===`vault:${e}`)||r.calls?.some(e=>{let t=Ae(e);return t?n===je(t.server):n===`flow:${e}`})):!1}var zt=[`!=`,`>=`,`<=`,`=`,`>`,`<`],Bt={clauses:[]},Vt=[`flow`,`unit`,`trigger`,`plane`,`tenant`,`principal`,`cache`,`replica`,`error`,`buildVersion`,`promptVersion`,`duration`];function Ht(e){if(!e||!e.trim())return Bt;let t=e.split(/\s+AND\s+/i).map(e=>e.trim()).filter(Boolean),n=[];for(let e of t){let t=$t(e);t&&n.push(t)}return{clauses:n}}function Z(e,t){return{clauses:[...e.clauses.filter(e=>e.dimension!==t.dimension),t]}}function Ut(e,t){return{clauses:e.clauses.filter(e=>e.dimension!==t)}}function Wt(e,t){return e.dimension===t.dimension&&e.op===t.op&&e.value===t.value}function Gt(e,t){return e.clauses.some(e=>Wt(e,t))}function Kt(e,t){return Gt(e,t)?Ut(e,t.dimension):Z(e,t)}function qt(e){let t=nn(e.dimension,e.value);return`${e.dimension} ${e.op} ${t}`}function Jt(e,t){for(let n of t.clauses)if(!rn(e,n))return!1;return!0}function Yt(e,t){return t.clauses.length===0?[...e]:e.filter(e=>Jt(e,t))}function Xt(e){let t=/^(-?\d+(?:\.\d+)?)\s*(ms|s|m)?$/i.exec(e.trim());if(!t)return;let n=Number(t[1]),r=(t[2]??`ms`).toLowerCase();if(r===`ms`)return n;if(r===`s`)return n*1e3;if(r===`m`)return n*6e4}function Zt(e,t){switch(t){case`flow`:return e.flow;case`unit`:return e.unit??null;case`trigger`:return e.trigger;case`plane`:return e.plane;case`tenant`:return e.tenant??null;case`principal`:return e.principal??null;case`cache`:return e.cache;case`replica`:return e.replica??null;case`replicaLagMs`:case`replica_lag_ms`:return e.replicaLagMs??null;case`error`:case`error_code`:return e.error??null;case`buildVersion`:case`build_version`:return e.buildVersion??null;case`promptVersion`:case`prompt_version`:return e.promptVersion??null;case`cost`:return e.cost??null;case`duration`:case`duration_ms`:return e.durationMs;case`gates`:return e.gates.join(`,`);default:return e.dimensions[t]}}function Qt(e){let t=new Set(Vt);for(let n of e)for(let e of Object.keys(n.dimensions))t.add(e);return[...t].sort()}function $t(e){let t=null,n=-1;for(let r of zt){let i=e.indexOf(` ${r} `);if(i!==-1){t=r,n=i;break}}if(t===null||n<0)return null;let r=e.slice(0,n).trim(),i=e.slice(n+t.length+2).trim();if(!r||!i)return null;let a=en(r,i);return a===void 0?null:{dimension:r,op:t,value:a}}function en(e,t){return e===`duration`||e===`duration_ms`?Xt(t):t===`true`?!0:t===`false`?!1:t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1):/^-?\d+(\.\d+)?$/.test(t)?Number(t):t}function tn(e,t){return nn(e,t)}function nn(e,t){if(e===`duration`||e===`duration_ms`){let e=typeof t==`number`?t:Number(t);return Number.isFinite(e)?e>=6e4&&e%6e4==0?`${e/6e4}m`:e>=1e3&&e%1e3==0?`${e/1e3}s`:`${e}ms`:String(t)}return typeof t==`string`&&/\s/.test(t)?`"${t}"`:String(t)}function rn(e,t){let n=Zt(e,t.dimension);if(n==null)return t.op===`!=`;let r=t.value;if(t.op===`=`)return an(n,r);if(t.op===`!=`)return!an(n,r);let i=Q(n),a=Q(r);return i===void 0||a===void 0?!1:t.op===`>`?i>a:t.op===`<`?i<a:t.op===`>=`?i>=a:t.op===`<=`&&i<=a}function an(e,t){if(typeof e==`number`||typeof t==`number`){let n=Q(e),r=Q(t);if(n!==void 0&&r!==void 0)return n===r}return String(e)===String(t)}function Q(e){if(typeof e==`number`&&Number.isFinite(e))return e;if(typeof e==`boolean`)return;let t=Number(e);return Number.isFinite(t)?t:void 0}var on=new Set(Object.keys(j));function sn(e){if(e.startsWith(`flow:`))return{kind:`flow`,flowId:e.slice(5)};if(e.startsWith(`signal:`))return{kind:`signal`,signal:e.slice(7)};if(e.startsWith(`unit:`))return{kind:`unit`,unit:e.slice(5)};if(e.startsWith(`element:`)){let t=e.slice(8);return on.has(t)?{kind:`element`,element:t}:null}if(e.startsWith(`type:`)){let t=e.slice(5).split(`:`)[0];return t&&on.has(t)?{kind:`element`,element:t}:null}return e.startsWith(`sql:`)||e.startsWith(`kv:`)||e.startsWith(`files:`)||e.startsWith(`index:`)||e.startsWith(`vault:`)||e.startsWith(`channel:`)||e.startsWith(`gate:`)||e.startsWith(`clock:`)||e.startsWith(`ai:`)?{kind:`resource`,nodeId:e}:null}function cn(e){switch(e.kind){case`flow`:return e.flowId;case`signal`:return`signal:${e.signal}`;case`unit`:return e.unit;case`element`:return j[e.element].label;case`resource`:return e.nodeId}}function ln(e,t){return t?.kind===`flow`?Z(e,{dimension:`flow`,op:`=`,value:t.flowId}):t?.kind===`unit`?Z(e,{dimension:`unit`,op:`=`,value:t.unit}):e}function un(e,t,n){if(t.kind===`flow`)return Jt(e,{clauses:[{dimension:`flow`,op:`=`,value:t.flowId}]});if(t.kind===`unit`)return(e.unit??L(e.flow))===t.unit;if(t.kind===`element`)return t.element===`flow`||qe(e).includes(t.element);if(t.kind===`resource`)return dn(e,t.nodeId,n);let r=n?.flows??{};for(let[n,i]of Object.entries(r))if(n===e.flow&&(i.trigger?.signal===t.signal||i.effects?.emits?.includes(t.signal)))return!0;return!1}function dn(e,t,n){let r=t.includes(`:`)?t.slice(t.indexOf(`:`)+1):t;if(e.effects.some(e=>e.resource===t||e.resource===r)||e.gates.some(e=>t===`gate:${e}`))return!0;let i=n?.flows?.[e.flow];return!!(i&&Rt(i,e.flow,t))}function fn(e,t,n){return t?e.filter(e=>un(e,t,n)):[...e]}function pn(e){return e?e.kind===`unit`||e.kind===`flow`||e.kind===`resource`?e:e.kind===`signal`?{kind:`resource`,nodeId:`signal:${e.signal}`}:null:null}function mn({manifest:e,runs:t=[],graphFilter:n,highlightedFlowIds:r,highlightedNodeIds:i,follow:a,activeNodeId:o=null,focusedNodeId:s=null,orchestraLabel:c=null,onNodeClick:l,onPaneClick:u}){let{fitView:d}=E(),{theme:f}=ue(),[p,m]=(0,R.useState)(null),h=f===`system`?window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`:f,g=pn(n),_=n?.kind===`element`?n.element:null,v=g===null,y=(0,R.useMemo)(()=>it(e,t,_?{kind:`element`,element:_}:null),[e,t,_]),b=(0,R.useMemo)(()=>ze(!g||!e?e:Lt(e,g)),[e,g]),x=(0,R.useMemo)(()=>dt(y.nodes,y.edges,{hoverNodeId:p,highlightedFlowIds:r,highlightedNodeIds:i,manifest:e}),[y.nodes,y.edges,p,r,i,e]),S=(0,R.useMemo)(()=>Le(b.nodes,r,i,{activeNodeId:o,focusedNodeId:s}),[b.nodes,r,i,o,s]),C=(0,R.useMemo)(()=>Ie(b.edges,S),[b.edges,S]),w=v?x.nodes:S,O=v?x.edges:C;return(0,R.useEffect)(()=>{d({duration:280,padding:.18})},[v,n,e,d]),(0,R.useEffect)(()=>{if(!a||v||r.size===0)return;let e=[...r].map(e=>`flow:${e}`);d({nodes:e.map(e=>({id:e})),duration:300,padding:.2})},[a,v,r,d]),(0,G.jsxs)(`div`,{className:`relative h-full w-full`,children:[n?(0,G.jsxs)(`button`,{type:`button`,"data-slot":`flow-graph-map`,onClick:()=>u?.(),className:`absolute top-2 left-2 z-10 inline-flex max-w-[min(100%-1rem,20rem)] items-center gap-1.5 truncate rounded-md border border-border/70 bg-card/90 px-2 py-1 text-[10px] font-medium text-muted-foreground shadow-sm backdrop-blur-sm transition-colors hover:border-border hover:text-foreground`,children:[(0,G.jsx)(`span`,{className:`text-foreground`,children:`Map`}),(0,G.jsx)(`span`,{"aria-hidden":!0,children:`/`}),(0,G.jsx)(`span`,{className:`truncate`,children:cn(n)})]}):(0,G.jsx)(`div`,{className:`pointer-events-none absolute top-2 left-2 z-10 text-[10px] font-medium tracking-wide text-muted-foreground uppercase`,children:c?(0,G.jsxs)(G.Fragment,{children:[`Orchestra `,(0,G.jsx)(`span`,{className:`text-foreground normal-case`,children:c})]}):`Hover a unit — spokes light the elements it touches`}),(0,G.jsxs)(T,{nodes:w,edges:O,nodeTypes:It,colorMode:h,fitView:!0,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,proOptions:{hideAttribution:!0},minZoom:.15,maxZoom:1.6,defaultEdgeOptions:{type:`smoothstep`,zIndex:P.edge},zIndexMode:`manual`,onNodeClick:(e,t)=>l?.(t.id),onPaneClick:()=>u?.(),onNodeMouseEnter:(e,t)=>m(t.id),onNodeMouseLeave:()=>m(null),children:[(0,G.jsx)(ee,{gap:24,size:1,color:`color-mix(in oklab, var(--foreground) 14%, transparent)`}),(0,G.jsx)(k,{showInteractive:!1}),(0,G.jsx)(D,{pannable:!0,zoomable:!0,ariaLabel:`Flow graph overview`,bgColor:`var(--card)`,maskColor:`color-mix(in oklab, var(--background) 55%, transparent)`,nodeColor:hn,nodeStrokeColor:gn,nodeStrokeWidth:12,nodeBorderRadius:10})]})]})}function hn(e){if(e.type===`orbit`)return`transparent`;let t=e.data.kind;if(t===`law`)return`color-mix(in oklab, var(--foreground) 45%, transparent)`;if(t===`unit`)return`color-mix(in oklab, var(--foreground) 8%, transparent)`;if(t===`element`){let t=e.data.refId;return M[t]?.accent??`#64748B`}return t in M?M[t].accent:`#64748B`}function gn(e){return e.data.kind===`unit`?`color-mix(in oklab, var(--foreground) 32%, transparent)`:`transparent`}function _n(e){let{leading:t,...n}=e;return(0,G.jsxs)(`div`,{className:`flex h-full min-h-0 w-full flex-col`,"data-slot":`flow-graph`,children:[t?(0,G.jsxs)(`header`,{className:m,children:[t,(0,G.jsx)(`span`,{className:`w-px shrink-0 self-stretch bg-border/60`,"aria-hidden":!0})]}):null,(0,G.jsx)(`div`,{className:`min-h-0 flex-1`,children:(0,G.jsx)(A,{children:(0,G.jsx)(mn,{...n})})})]})}var vn=`orch-`;function yn(e){return e.startsWith(vn)}function bn(e,t){return e&&t}function xn(e,t=Math.random){let n=e.filter(e=>!yn(e.id)&&e.flow.length>0);return n.length===0?null:n[Math.floor(t()*n.length)]??null}function Sn(e,t,n){let r=t-e.startedAt,i=e.flow.replaceAll(`.`,`-`);return{...e,id:`${vn}${n}-${i}`,parentId:null,startedAt:t,endedAt:t+e.durationMs,effects:e.effects.map(e=>({...e,timestamp:e.timestamp+r})),logs:e.logs.map(e=>({...e,at:e.at+r}))}}function Cn(e=Math.random){return 1800+Math.floor(e()*1600)}var wn=1400;function Tn(e){let t=r(),[n,i]=(0,R.useState)(null),a=(0,R.useRef)(0),o=(0,R.useRef)(null),s=(0,R.useRef)(null),c=(0,R.useRef)(e.paused);return c.current=e.paused,(0,R.useEffect)(()=>{if(!bn(!1,e.enabled))return;let n=()=>{o.current&&=(clearTimeout(o.current),null)},r=()=>{if(c.current||document.hidden)return;let e=xn(t.getQueryData(Oe)??[]);if(!e)return;a.current+=1;let r=Sn(e,Date.now(),a.current);t.setQueryData(Oe,e=>De(e??[],r)),i({flowId:r.flow,runId:r.id}),n(),o.current=setTimeout(()=>{i(null),o.current=null},wn)},l=e=>{s.current=setTimeout(()=>{r(),l(Cn())},e)};l(700);let u=()=>{document.hidden&&(i(null),n())};return document.addEventListener(`visibilitychange`,u),()=>{document.removeEventListener(`visibilitychange`,u),s.current&&clearTimeout(s.current),n(),i(null)}},[e.enabled,t]),e.paused?null:n}function En(e,t){let n=new Set;if(!t)return n;let r=new Map,i=new Map;for(let t of e)r.set(t.id,t);for(let t of e){if(!t.parentId)continue;let e=i.get(t.parentId)??[];e.push(t),i.set(t.parentId,e)}let a=r.get(t);if(!a)return n;let o=a,s=new Set;for(;o&&!s.has(o.id);)s.add(o.id),n.add(o.flow),o=o.parentId?r.get(o.parentId):void 0;let c=[a];for(;c.length>0;){let e=c.shift();if(!e)break;for(let t of i.get(e.id)??[])s.has(t.id)||(s.add(t.id),n.add(t.flow),c.push(t))}return n}var Dn=[{id:`signal`,label:`Signal`,expr:`trigger = signal`},{id:`clock`,label:`Clock`,expr:`trigger = cron`},{id:`cache-miss`,label:`Cache miss`,expr:`cache = miss`},{id:`slow`,label:`Slow`,expr:`duration > 100ms`}],On=`h-7 min-w-0 rounded-none border-0 bg-transparent px-0 font-mono text-[11px] text-foreground shadow-none outline-none focus-visible:ring-0 dark:bg-transparent`,$=`rounded-none border-0 bg-transparent px-1.5 py-1 text-[11px] text-foreground/70 shadow-none transition-colors hover:bg-muted/50 hover:text-foreground`,kn=`grid grid-cols-[minmax(0,1fr)_1.25rem_minmax(0,1fr)_1.25rem] items-center gap-x-1`;function An({query:e,runs:t,onChange:r}){let a=(0,R.useMemo)(()=>Qt(t),[t]),o=(0,R.useMemo)(()=>[...new Set([...Vt,...a])].sort(),[a]),[s,c]=(0,R.useState)(`trigger`),[l,u]=(0,R.useState)(`=`),[d,f]=(0,R.useState)(`signal`),[p,m]=(0,R.useState)(!1),h=()=>{let t=Ht(`${s} ${l} ${d}`).clauses[0];t&&(r(Z(e,t)),m(!1))};return(0,G.jsxs)(`div`,{className:`flex flex-col gap-1.5 border-b border-border/60 px-2 py-1.5`,"data-slot":`traces-advanced-filters`,children:[e.clauses.length>0?(0,G.jsx)(`ul`,{"aria-label":`Active filters`,className:`flex flex-col gap-0.5`,children:e.clauses.map(t=>(0,G.jsx)(`li`,{children:(0,G.jsx)(jn,{clause:t,onRemove:()=>r(Ut(e,t.dimension))})},t.dimension))}):null,p?(0,G.jsxs)(`div`,{className:kn,"data-slot":`traces-advanced-composer`,children:[(0,G.jsx)(`select`,{"aria-label":`Filter dimension`,className:On,value:s,onChange:e=>c(e.target.value),children:o.map(e=>(0,G.jsx)(`option`,{value:e,children:e},e))}),(0,G.jsx)(`select`,{"aria-label":`Filter operator`,className:n(On,`text-center text-foreground/70`),value:l,onChange:e=>u(e.target.value),children:[`=`,`!=`,`>`,`<`,`>=`,`<=`].map(e=>(0,G.jsx)(`option`,{value:e,children:e},e))}),(0,G.jsx)(i,{"aria-label":`Filter value`,flat:!0,className:`h-7 px-0 font-mono text-[11px]`,value:d,onChange:e=>f(e.target.value),onKeyDown:e=>{e.key===`Enter`&&h()}}),(0,G.jsx)(`button`,{type:`button`,className:$,onClick:h,children:`Add`})]}):null,(0,G.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-2.5 gap-y-1`,children:[Dn.map(t=>{let i=Ht(t.expr).clauses[0],a=i!==void 0&&Gt(e,i);return(0,G.jsx)(`button`,{type:`button`,"aria-pressed":a,disabled:i===void 0,onClick:()=>{i&&r(Kt(e,i))},className:n($,a?`font-medium text-foreground`:`text-foreground/70`),children:t.label},t.id)}),(0,G.jsx)(`button`,{type:`button`,"aria-expanded":p,className:n($,`ml-auto`,p&&`text-foreground`),onClick:()=>m(e=>!e),children:p?`Cancel`:`Add clause`}),e.clauses.length>0?(0,G.jsx)(`button`,{type:`button`,className:$,onClick:()=>r(Ht(``)),children:`Clear`}):null]})]})}function jn({clause:e,onRemove:t}){let r=qt(e);return(0,G.jsxs)(`div`,{className:kn,"data-slot":`traces-advanced-clause`,children:[(0,G.jsx)(`span`,{className:`truncate font-mono text-[11px] text-foreground/80`,children:e.dimension}),(0,G.jsx)(`span`,{className:`text-center font-mono text-[11px] text-foreground/65`,"aria-hidden":!0,children:e.op}),(0,G.jsx)(`span`,{className:`truncate font-mono text-[11px] text-foreground`,children:tn(e.dimension,e.value)}),(0,G.jsx)(`button`,{type:`button`,className:n($,`flex size-5 items-center justify-center text-foreground/55 hover:text-destructive`),"aria-label":`Remove ${r}`,onClick:t,children:(0,G.jsx)(b,{icon:x,className:`size-3`})})]})}var Mn={query:``,status:`all`,advanced:Bt};function Nn(e,t){let n=t.trim().toLowerCase();return!n||[e.flow,e.unit??``,e.trigger,e.cache,e.id,e.error??``,e.errorMessage??``].some(e=>e.toLowerCase().includes(n))}function Pn(e,t){return Yt(e.filter(e=>!(!Nn(e,t.query)||t.status===`errors`&&e.error===null)),t.advanced)}function Fn(e,t=Date.now()){let n=t-e;return n<1e3?`just now`:n<6e4?`${Math.floor(n/1e3)}s ago`:n<36e5?`${Math.floor(n/6e4)}m ago`:`${Math.floor(n/36e5)}h ago`}function In(e,t=Date.now()){let n=Fn(e.startedAt,t),r=e.error!==null;return{text:n,title:r?e.errorMessage?`${e.error} — ${e.errorMessage}`:e.error??n:n,failed:r}}function Ln({run:e,selected:t,onSelect:r,copyText:i=async e=>{await navigator.clipboard.writeText(e)}}){let l=In(e),u=l.failed,d=oe(e.trigger),f=e.cache,[p,m]=(0,R.useState)(null),h=async t=>{t.stopPropagation();try{await i(ce(e)),m(`Copied run id`)}catch{m(`Copy failed`)}};return(0,G.jsxs)(`div`,{"data-slot":`trace-row`,"data-run-id":e.id,"data-selected":t?`true`:`false`,"data-failed":u?`true`:`false`,"data-cache":e.cache,className:n(`group relative flex w-full items-stretch border-b border-border/60 text-xs transition-colors`,`hover:bg-muted/50 focus-within:bg-muted/50`,t&&`bg-muted/70`,u&&`bg-destructive/[0.04]`),children:[(0,G.jsx)(`span`,{"aria-hidden":!0,className:n(`absolute inset-y-0 left-0 w-0.5`,t&&!u&&`bg-sky-500`,u&&`bg-destructive`)}),(0,G.jsxs)(`button`,{type:`button`,"aria-pressed":t,onClick:()=>r(e.id),className:`flex min-w-0 flex-1 items-center gap-2 py-1.5 pr-1 pl-0 text-left outline-none`,children:[(0,G.jsx)(`span`,{className:n(`ml-2.5 size-1.5 shrink-0 rounded-full`,u?`bg-destructive`:`bg-emerald-500`),"aria-hidden":!0}),(0,G.jsx)(`span`,{className:`shrink-0 text-muted-foreground`,title:d.label,"aria-hidden":!0,children:(0,G.jsx)(b,{icon:d.icon,className:`size-3.5`})}),(0,G.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-medium text-foreground`,children:e.flow}),(0,G.jsx)(Ve,{cache:f,dataSlot:`trace-row-cache`}),(0,G.jsx)(`span`,{className:n(`w-10 shrink-0 text-right tabular-nums font-medium`,re(e.durationMs)),children:Ee(e.durationMs)}),(0,G.jsx)(`span`,{className:`w-14 shrink-0 truncate text-right tabular-nums text-muted-foreground`,title:l.title,"data-slot":`trace-row-meta`,children:l.text})]}),(0,G.jsx)(`div`,{className:n(`flex shrink-0 items-center gap-0.5 pr-1.5 opacity-0 transition-opacity`,`group-hover:opacity-100 group-focus-within:opacity-100`,p&&`opacity-100`),children:(0,G.jsxs)(s,{children:[(0,G.jsx)(o,{render:e=>(0,G.jsx)(c,{...e,type:`button`,variant:`ghost`,size:`icon-xs`,"aria-label":`Copy run ID`,"data-slot":`trace-copy-id`,onClick:t=>{e.onClick?.(t),h(t)},children:(0,G.jsx)(b,{icon:_,className:`size-3`})})}),(0,G.jsx)(a,{side:`top`,children:`Copy run ID`})]})}),p?(0,G.jsx)(`span`,{className:`sr-only`,role:`status`,children:p}):null]})}var Rn=[{value:`all`,label:`All`,icon:t},{value:`errors`,label:`Errors`,icon:h}];function zn({runs:e,selectedRunId:t,onSelect:r,liveStatus:i,manifest:c,graphFilter:f,onGraphFilterChange:h,focusEffectIndex:g,onFocusEffectChange:_,playbackKey:x,onReplayStart:S,selectedRun:C}){let[w,T]=(0,R.useState)(Mn),[E,D]=(0,R.useState)(!1);(0,R.useEffect)(()=>{(f?.kind===`flow`||f?.kind===`unit`)&&T(e=>({...e,advanced:ln(e.advanced,f)}))},[f]);let O=(0,R.useMemo)(()=>fn(Pn(e,w),f,c),[e,w,f,c]),k=(0,R.useMemo)(()=>C===void 0?t?e.find(e=>e.id===t)??null:null:C,[C,e,t]),A=w.advanced.clauses.length>0,ee=e=>{T(t=>({...t,query:e}))},te=e=>{T(t=>({...t,status:e}))};return(0,G.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col overflow-hidden`,"data-slot":`traces-pane`,children:[(0,G.jsxs)(`div`,{className:`shrink-0 border-b border-border/60`,children:[(0,G.jsxs)(`div`,{className:n(d,`border-b-0`),children:[(0,G.jsx)(Ce,{value:w.query,onChange:e=>ee(e.target.value),placeholder:`Search traces…`,"aria-label":`Search traces`,"data-slot":`traces-search`}),(0,G.jsxs)(`div`,{className:`flex shrink-0 items-stretch pr-0.5`,children:[e.length>0?(0,G.jsxs)(s,{children:[(0,G.jsx)(o,{render:e=>(0,G.jsxs)(`button`,{...e,type:`button`,"aria-expanded":E,"aria-controls":`traces-advanced-panel`,"aria-label":A?`Advanced filters, ${w.advanced.clauses.length} active`:`Advanced filters`,"data-slot":`traces-advanced-toggle`,onClick:t=>{e.onClick?.(t),D(e=>!e)},className:n(u,`relative`,(E||A)&&`text-foreground`),children:[(0,G.jsx)(b,{icon:v,className:`size-3`,"aria-hidden":!0}),A?(0,G.jsx)(`span`,{className:`absolute -top-0.5 -inset-e-0.5 flex size-3.5 items-center justify-center rounded-full bg-foreground text-[8px] font-medium text-background`,"aria-hidden":!0,children:w.advanced.clauses.length}):null]})}),(0,G.jsx)(a,{side:`bottom`,children:`Advanced`})]}):null,e.length>0?(0,G.jsx)(`span`,{className:`mx-0.5 h-3 w-px bg-border/60`,"aria-hidden":!0}):null,(0,G.jsxs)(`div`,{className:`flex items-center gap-1.5 pr-0.5 text-[10px] text-muted-foreground`,children:[(0,G.jsx)(`span`,{className:i===`open`?`size-1.5 rounded-full bg-emerald-500`:`size-1.5 rounded-full bg-muted-foreground`,"aria-hidden":!0}),i===`open`?`live`:`polling`]})]})]}),e.length>0?(0,G.jsx)(`div`,{className:n(m,`border-t border-b-0`),"data-slot":`traces-filters`,children:(0,G.jsx)(`div`,{className:`flex shrink-0 items-stretch`,role:`group`,"aria-label":`Status filter`,children:Rn.map(({value:e,label:t,icon:r})=>{let i=w.status===e;return(0,G.jsxs)(`button`,{type:`button`,"aria-pressed":i,onClick:()=>te(e),className:n(l,`font-semibold tracking-[0.08em] uppercase`,i?e===`errors`?`text-destructive`:p:y),children:[(0,G.jsx)(b,{icon:r,className:`size-3`,"aria-hidden":!0}),t]},e)})})}):null,e.length>0&&f?(0,G.jsxs)(`button`,{type:`button`,"data-slot":`traces-graph-filter`,onClick:()=>h(null),title:`Clear graph filter`,className:`mx-2 mb-1.5 inline-flex max-w-full items-center gap-1 self-start truncate rounded-md border border-sky-500/40 bg-sky-500/10 px-2 py-0.5 text-[10px] font-medium text-sky-700 transition-colors hover:bg-sky-500/20 dark:text-sky-400`,children:[(0,G.jsx)(`span`,{className:`truncate`,children:cn(f)}),(0,G.jsx)(`span`,{"aria-hidden":!0,children:`×`})]}):null]}),e.length>0&&E?(0,G.jsx)(`div`,{id:`traces-advanced-panel`,children:(0,G.jsx)(An,{query:w.advanced,runs:e,onChange:e=>{T(t=>({...t,advanced:e}))}})}):null,(0,G.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto`,children:e.length===0?(0,G.jsx)(pe,{className:`border-none`,children:(0,G.jsxs)(Se,{children:[(0,G.jsx)(me,{variant:`icon`,children:(0,G.jsx)(b,{icon:j.flow.icon})}),(0,G.jsx)(ve,{children:`No traces yet`}),(0,G.jsx)(be,{children:`No runs for the flows on this graph yet. Trigger a flow to see live activity here.`})]})}):O.length===0?(0,G.jsx)(pe,{className:`border-none`,children:(0,G.jsxs)(Se,{children:[(0,G.jsx)(ve,{children:`No matching traces`}),(0,G.jsx)(be,{children:`Nothing in this list matches the current search, status, or advanced filters.`})]})}):O.map(e=>(0,G.jsx)(Ln,{run:e,selected:e.id===t,onSelect:e=>r(e===t?null:e)},e.id))}),(0,G.jsx)(le,{run:k,onClose:()=>r(null),focusEffectIndex:g,onFocusEffectChange:_,playbackKey:x,onReplayStart:S})]})}function Bn(){let e=Te(),t=ke(),n=we(!0),{selectedRunId:r,selectedFlowId:i,follow:a,setSelectedRun:o,setSelectedFlow:s}=fe(),c=he(),l=(0,G.jsx)(ge,{open:c.open,onToggle:c.toggle,noun:`traces`,controlsId:`overview-traces`,dataSlot:`overview-traces-toggle`}),[u,d]=(0,R.useState)(null),[p,m]=(0,R.useState)(null),[h,_]=(0,R.useState)(0),[v,y]=(0,R.useState)(null),b=(0,R.useRef)(null),x=(0,R.useMemo)(()=>new Set(Object.keys(e.data?.flows??{})),[e.data]),S=(0,R.useMemo)(()=>Re(t.data??[],x),[t.data,x]),C=Tn({enabled:!!e.data&&S.length>0,paused:r!=null||u!=null});(0,R.useEffect)(()=>{i&&d(e=>e?.kind===`flow`&&e.flowId===i?e:{kind:`flow`,flowId:i})},[i]);let w=(0,R.useCallback)(e=>{d(e),e?.kind===`flow`?s(e.flowId):s(null)},[s]),T=(0,R.useMemo)(()=>{let e=En(t.data??[],r);return e.size>0?e:i?new Set([i]):C?.flowId?new Set([C.flowId]):e},[t.data,r,i,C?.flowId]),E=(0,R.useMemo)(()=>{let t=new Set,n=e.data?.flows??{};for(let e of T){let r=n[e];if(r){r.trigger?.signal&&t.add(`signal:${r.trigger.signal}`),(r.trigger?.cron||r.trigger?.every)&&t.add(`clock:${e}`);for(let e of r.gates??[])t.add(`gate:${e}`);for(let e of r.effects?.reads??[])t.add(e);for(let e of r.effects?.writes??[])t.add(e);for(let e of r.effects?.emits??[])t.add(`signal:${e}`);for(let e of r.effects?.sends??[])t.add(`channel:${e}`);for(let e of r.effects?.asks??[])t.add(`ai:${e}`);for(let e of r.effects?.secrets??[])t.add(`vault:${e}`)}}return t},[T,e.data]),D=(0,R.useMemo)(()=>r?t.data?.find(e=>e.id===r)??null:null,[t.data,r]),O=(0,R.useCallback)(e=>{let t=sn(e);t&&w(u&&u.kind===t.kind&&JSON.stringify(u)===JSON.stringify(t)?null:t)},[w,u]),k=(0,R.useCallback)(()=>{w(null)},[w]),A=(0,R.useCallback)(()=>{_(e=>e+1)},[]);return(0,R.useEffect)(()=>{if(h===0||!D)return;let n=se(En(t.data??[],D.id),e.data??null);if(n.length===0)return;let r=ie(D.durationMs),i=performance.now();return y(n[0]??null),b.current=setInterval(()=>{let e=Math.min(1,(performance.now()-i)/r);y(ae(n,e)),e>=1&&b.current&&(clearInterval(b.current),b.current=null,setTimeout(()=>y(null),400))},60),()=>{b.current&&=(clearInterval(b.current),null),y(null)}},[h,D,t.data,e.data]),(0,G.jsx)(`div`,{className:f,"data-slot":`flows-page`,children:(0,G.jsxs)(_e,{orientation:`horizontal`,className:`min-h-0 flex-1`,children:[(0,G.jsx)(ye,{panelRef:c.panelRef,collapsible:!0,collapsedSize:0,defaultSize:g.start.defaultSize,minSize:g.start.minSize,maxSize:`50%`,onResize:c.onResize,className:`min-h-0`,children:(0,G.jsx)(`div`,{id:`overview-traces`,className:`h-full min-h-0 overflow-hidden`,"data-slot":`overview-traces`,children:(0,G.jsx)(zn,{runs:S,selectedRunId:r,onSelect:o,liveStatus:n,manifest:e.data??null,graphFilter:u,onGraphFilterChange:w,focusEffectIndex:p,onFocusEffectChange:m,playbackKey:h,onReplayStart:A,selectedRun:D})})}),c.open?(0,G.jsx)(xe,{withHandle:!0}):null,(0,G.jsx)(ye,{defaultSize:g.end.defaultSize,minSize:g.end.minSize,className:`min-h-0`,children:(0,G.jsx)(`div`,{className:`h-full min-h-0 overflow-hidden`,children:(0,G.jsx)(_n,{manifest:e.data??null,runs:S,graphFilter:u,highlightedFlowIds:T,highlightedNodeIds:E,orchestraLabel:C?.flowId??null,follow:a,activeNodeId:v,onNodeClick:O,onPaneClick:k,leading:l})})})]})})}export{Bn as FlowsPage};
@@ -0,0 +1 @@
1
+ import{$r as e,Ar as t,Cr as n,Dr as r,Hi as i,Ii as a,Rr as o,Ui as s,Vi as c,Xr as l,ca as u,ci as d,dr as f,hr as ee,li as p,mi as te,na as ne,ni as re,nr as m,oa as h,or as g,ta as _,ti as v,ui as y,wr as b,xr as x,yi as S}from"./shortcut-keys-DO4IsVqv.js";import{A as C}from"./xyflow-D7n4g6go.js";import{d as w}from"./collapsible-DYb0xU8C.js";import{i as T}from"./highlighted-json-CvDPvveV.js";var E=C();function D(e){if(!e.startsWith(`mcp:`))return null;let t=e.slice(4),n=t.indexOf(`/`);return n<=0||n===t.length-1?null:{server:t.slice(0,n),tool:t.slice(n+1)}}function O(e){return`mcp:${e}`}var k={flow:{accent:`#38BDF8`,glow:`rgba(56, 189, 248, 0.45)`,well:`rgba(56, 189, 248, 0.14)`},signal:{accent:`#FBBF24`,glow:`rgba(251, 191, 36, 0.4)`,well:`rgba(251, 191, 36, 0.14)`},store:{accent:`#34D399`,glow:`rgba(52, 211, 153, 0.45)`,well:`rgba(52, 211, 153, 0.14)`},clock:{accent:`#818CF8`,glow:`rgba(129, 140, 248, 0.45)`,well:`rgba(129, 140, 248, 0.14)`},gate:{accent:`#A78BFA`,glow:`rgba(167, 139, 250, 0.45)`,well:`rgba(167, 139, 250, 0.14)`},vault:{accent:`#94A3B8`,glow:`rgba(148, 163, 184, 0.4)`,well:`rgba(148, 163, 184, 0.14)`},channel:{accent:`#C084FC`,glow:`rgba(192, 132, 252, 0.45)`,well:`rgba(192, 132, 252, 0.14)`},ai:{accent:`#FB7185`,glow:`rgba(251, 113, 133, 0.45)`,well:`rgba(251, 113, 133, 0.14)`}},A={reads:`#2DD4BF`,writes:`#FB923C`,emits:`#FBBF24`,calls:`#60A5FA`,asks:`#FB7185`,sends:`#C084FC`,secrets:`#94A3B8`,gates:`#A78BFA`,trigger:`#FBBF24`,couple:`#64748B`},j={flow:{width:188,height:52},store:{width:168,height:48},signal:{width:168,height:48},ai:{width:168,height:48},clock:{width:168,height:48},gate:{width:168,height:48},vault:{width:168,height:48},channel:{width:168,height:48}},M={law:{width:140,height:140},hub:{width:56,height:56},type:{width:64,height:26},unit:{width:128,height:40}},N={cx:900,cy:900,elementRing:280,typeRing:418,typeRow:88,spokeRing:840},P={headerH:26,padX:10,padBottom:10},F={edge:0,unit:1,leaf:2},I=[`http`,`signal`,`cron`,`every`,`cdc`,`internal`],L={http:{icon:t,label:`HTTP`,wellClass:`border-sky-500/35 bg-sky-500/10 text-sky-600 dark:text-sky-400`},signal:{icon:w.signal.icon,label:`Signal`,wellClass:`border-amber-500/35 bg-amber-500/10 text-amber-700 dark:text-amber-400`},cron:{icon:o,label:`Cron`,wellClass:`border-violet-500/35 bg-violet-500/10 text-violet-700 dark:text-violet-400`},every:{icon:_,label:`Every`,wellClass:`border-teal-500/35 bg-teal-500/10 text-teal-700 dark:text-teal-400`},cdc:{icon:w.store.icon,label:`CDC`,wellClass:`border-emerald-500/35 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400`},internal:{icon:te,label:`Call-only`,wellClass:`border-zinc-500/35 bg-zinc-500/10 text-zinc-600 dark:text-zinc-400`}};function R(e){return e?.http?`http`:e?.signal?`signal`:e?.cron?`cron`:e?.every?`every`:e?.cdc?`cdc`:`internal`}function z(e){let t=R(e),n=L[t],r=null;return t===`http`&&e?.http?r=`${e.http.method} ${e.http.path}`:t===`signal`&&e?.signal?r=e.signal:t===`cron`&&e?.cron?r=e.cron:t===`every`&&e?.every?r=e.every:t===`cdc`&&e?.cdc&&(r=e.cdc.table),{kind:t,icon:n.icon,label:n.label,detail:r,wellClass:n.wellClass}}var B={policy:i,scope:S,rate:l,flag:d,public:h};function V(e,t,n){return t===`rate`||e.startsWith(`rate:`)?`rate`:e.startsWith(`flag:`)?`flag`:e===`public`?`public`:(n?.length??0)>0?`scope`:t===`policy`||t===`all`?`policy`:null}function H(e){return e?B[e]:i}function U(e,t){let n=t?.gates;return e.map(e=>{let t=n?.[e];return{name:e,kind:t?.kind??null,variant:V(e,t?.kind,t?.scopes),description:t?.description??null}})}var W=`#A78BFA`;function G({gate:e}){let t=e.variant??`undeclared`,n=[e.variant,e.description].filter(Boolean).join(` · `)||`undeclared`;return(0,E.jsxs)(`li`,{className:f,title:n,"data-slot":`trace-gate-row`,children:[(0,E.jsx)(b,{icon:H(e.variant),className:g,style:{color:W},"aria-hidden":!0}),(0,E.jsxs)(`span`,{className:`min-w-0 flex-1 truncate font-mono text-xs`,children:[(0,E.jsx)(`span`,{className:`text-muted-foreground`,children:t}),(0,E.jsxs)(`span`,{className:`text-foreground/90`,children:[` `,e.name]})]})]})}function K({gates:e,heading:t=`Gates`}){return e.length===0?null:(0,E.jsxs)(`section`,{className:`flex flex-col`,"data-slot":`gate-list`,"aria-label":t,children:[(0,E.jsxs)(`div`,{className:ee,children:[(0,E.jsx)(`h3`,{className:n(x,`flex items-center px-2`),children:t}),(0,E.jsx)(`span`,{className:n(m,`flex items-center`),children:e.length})]}),(0,E.jsx)(`ul`,{children:e.map(e=>(0,E.jsx)(G,{gate:e},e.name))})]})}var q={read:`Read`,write:`Write`,emit:`Emit`,send:`Send`,ask:`Ask`,secret:`Secret`,call:`Call`};function J(e,t){return`${t} ${t===1?{read:`read`,write:`write`,emit:`emit`,send:`send`,ask:`ask`,secret:`secret`,call:`call`}[e]:{read:`reads`,write:`writes`,emit:`emits`,send:`sends`,ask:`asks`,secret:`secrets`,call:`calls`}[e]}`}function Y(e){switch(e){case`read`:return A.reads;case`write`:return A.writes;case`emit`:return A.emits;case`call`:return A.calls;case`ask`:return A.asks;case`send`:return A.sends;case`secret`:return A.secrets}}function X(e,t){if(t&&D(t))return w.ai.icon;switch(e){case`read`:case`write`:return w.store.icon;case`emit`:return w.signal.icon;case`call`:return w.flow.icon;case`ask`:return w.ai.icon;case`send`:return w.channel.icon;case`secret`:return w.vault.icon}}var ie=[`read`,`write`,`emit`,`call`,`ask`,`send`,`secret`];function Z(e){return e.startsWith(`sql:`)}function Q(e){return e.startsWith(`computed:`)}function ae(e){let t=[{key:`duration`,label:T(e.durationMs),shortLabel:T(e.durationMs),variant:`duration`,detail:`Handler duration from the run ledger (${T(e.durationMs)}).`}];e.trigger===`http`&&t.push({key:`api`,label:`1 API call`,shortLabel:`1 API`,variant:`api`,detail:`HTTP trigger invocation for this run (not counted as an effect).`});let n=e.gates.length;n>0&&t.push({key:`gates`,label:`${n} ${n===1?`gate`:`gates`}`,shortLabel:`${n} gate${n===1?``:`s`}`,variant:`gate`,detail:`Evaluated on this run: ${e.gates.join(`, `)}.`});let r=e.effects.filter(e=>Q(e.resource)).length;r>0&&t.push({key:`cache`,label:`${r} cache ${r===1?`read`:`reads`}`,shortLabel:`${r} cache`,variant:`cache`,detail:`${r} effect${r===1?``:`s`} targeting computed:… cache keys.`});let i=e.effects.filter(e=>Z(e.resource)).length;i>0&&t.push({key:`db`,label:`${i} DB ${i===1?`query`:`queries`}`,shortLabel:`${i} DB`,variant:`db`,detail:`${i} effect${i===1?``:`s`} targeting sql:… store resources.`});let a=le(e.effects);for(let e of ie){let n=a.get(e)??0;n!==0&&t.push({key:e,label:J(e,n),shortLabel:J(e,n),variant:e,detail:`${n} non-SQL ${e} effect${n===1?``:`s`} on the run ledger.`})}let o=e.logs.length;return o>0&&t.push({key:`logs`,label:`${o} log ${o===1?`line`:`lines`}`,shortLabel:`${o} log${o===1?``:`s`}`,variant:`logs`,detail:`${o} ${o===1?`entry`:`entries`} in run.logs.`}),t}function oe(e){let t=D(e);return t?`Call ${t.server} → ${t.tool}`:null}function se(e){return D(e)!==null}function ce(e){return Q(e.resource)?`Cache read`:Z(e.resource)?e.kind===`write`?`DB write`:`DB query`:e.kind===`call`&&se(e.resource)?`MCP call`:{read:`Read`,write:`Write`,emit:`Emit`,send:`Send`,ask:`Ask`,secret:`Secret`,call:`Call`}[e.kind]}function le(e){let t=new Map;for(let n of e)Z(n.resource)||Q(n.resource)||t.set(n.kind,(t.get(n.kind)??0)+1);return t}function $(e){switch(e){case`hit`:return{icon:p,label:`Cache hit`,className:`text-sky-500 dark:text-sky-400`};case`miss`:return{icon:y,label:`Cache miss`,className:`text-amber-600 dark:text-amber-400`};case`none`:return{icon:ne,label:`Cache not applicable`,className:`text-muted-foreground/40`}}}function ue(e,t,n){let r=e?.flows?.[t],i=r?.trigger;return i?.http?{method:i.http.method,path:i.http.path,headline:`${i.http.method} ${i.http.path}`}:i?.signal?{method:null,path:null,headline:`Signal · ${i.signal}`}:i?.cron?{method:null,path:null,headline:`Cron · ${i.cron}`}:i?.every?{method:null,path:null,headline:`Every · ${i.every}`}:i?.cdc?{method:null,path:null,headline:`CDC · ${i.cdc.table}`}:n===`http`?{method:null,path:null,headline:`HTTP`}:n===`internal`||!r?.trigger?{method:null,path:null,headline:`Call-only`}:{method:null,path:null,headline:n}}function de(e){switch((e??``).toUpperCase()){case`GET`:return 0;case`POST`:return 1;case`QUERY`:return 2;case`PUT`:case`PATCH`:return 3;case`DELETE`:return 4;case`HEAD`:return 5;case`OPTIONS`:return 6;default:return e?7:8}}function fe(n){switch(n.toUpperCase()){case`GET`:return u;case`QUERY`:return c;case`POST`:return r;case`PUT`:return v;case`PATCH`:return a;case`DELETE`:return e;case`HEAD`:return re;case`OPTIONS`:return s;default:return t}}function pe(e){switch(e.toUpperCase()){case`GET`:return`border-emerald-500/35 bg-emerald-500/15 text-emerald-700 dark:text-emerald-400`;case`POST`:return`border-sky-500/35 bg-sky-500/15 text-sky-700 dark:text-sky-400`;case`PUT`:return`border-amber-500/35 bg-amber-500/15 text-amber-800 dark:text-amber-400`;case`PATCH`:return`border-violet-500/35 bg-violet-500/15 text-violet-700 dark:text-violet-400`;case`DELETE`:return`border-rose-500/35 bg-rose-500/15 text-rose-700 dark:text-rose-400`;case`HEAD`:return`border-slate-500/35 bg-slate-500/15 text-slate-700 dark:text-slate-300`;case`OPTIONS`:return`border-zinc-500/35 bg-zinc-500/15 text-zinc-700 dark:text-zinc-300`;case`QUERY`:return`border-emerald-500/35 bg-emerald-500/15 text-emerald-700 dark:text-emerald-400`;default:return`border-border bg-muted text-muted-foreground`}}function me(e){switch(e.toUpperCase()){case`GET`:return`bg-emerald-500`;case`POST`:return`bg-sky-500`;case`PUT`:return`bg-amber-500`;case`PATCH`:return`bg-violet-500`;case`DELETE`:return`bg-rose-500`;case`HEAD`:return`bg-slate-400`;case`OPTIONS`:return`bg-zinc-400`;case`QUERY`:return`bg-emerald-500`;default:return`bg-muted-foreground`}}export{k as C,D,O as E,M as S,P as T,R as _,ue as a,F as b,ae as c,Y as d,X as f,L as g,I as h,de as i,oe as l,U as m,fe as n,$ as o,K as p,me as r,ce as s,pe as t,q as u,z as v,j as w,N as x,A as y};