@workflow/web 4.1.0-beta.44 → 4.1.0-beta.46

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 (22) hide show
  1. package/README.md +1 -1
  2. package/build/client/assets/{highlighted-body-B3W2YXNL-BAmp2St7.js → highlighted-body-B3W2YXNL-CCnn-bn-.js} +1 -1
  3. package/build/client/assets/home-ClC-EMyL.js +40 -0
  4. package/build/client/assets/manifest-7a6ad03e.js +1 -0
  5. package/build/client/assets/{mermaid-3ZIDBTTL-CrmlsXj3.js → mermaid-3ZIDBTTL-D95wSBpg.js} +3 -3
  6. package/build/client/assets/{root-DXnpwJxc.js → root-Dae_xV-y.js} +1 -1
  7. package/build/client/assets/run-detail-Brs1Rm25.js +37 -0
  8. package/build/client/assets/workflow-graph-viewer-BZlGoIt2.js +161 -0
  9. package/build/server/assets/{app-DiZXH6x4.js → app-oogZ8ZwV.js} +1 -1
  10. package/build/server/assets/{highlighted-body-B3W2YXNL-CmDnR6fu.js → highlighted-body-B3W2YXNL-z6TbPMtP.js} +2 -2
  11. package/build/server/assets/{index-cxStGfMq.js → index-BL4Kw0eA.js} +2 -2
  12. package/build/server/assets/{mermaid-3ZIDBTTL-CxsJnUQo.js → mermaid-3ZIDBTTL-XSKOerl0.js} +2 -2
  13. package/build/server/assets/{server-build-CZMYXF52.js → server-build-BnrnOzxz.js} +422 -1853
  14. package/build/server/assets/{token-C7BfiMAN.js → token-Ct_osLcf.js} +2 -2
  15. package/build/server/assets/{token-util-CxDoe-ao.js → token-util-DQ6afx9q.js} +2 -2
  16. package/build/server/index.js +1 -1
  17. package/package.json +3 -3
  18. package/build/client/assets/home-CFxVErsy.js +0 -35
  19. package/build/client/assets/manifest-beaac576.js +0 -1
  20. package/build/client/assets/run-detail-C6LG6p9l.js +0 -37
  21. package/build/client/assets/use-workflow-graph-DGcT3V07.js +0 -166
  22. /package/build/client/assets/{use-workflow-graph-yls6qlc0.css → workflow-graph-viewer-yls6qlc0.css} +0 -0
@@ -14,7 +14,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
14
14
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
15
15
  var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
16
16
  var _a2, _root, _hasMagic, _uflag, _parts, _parent, _parentIndex, _negs, _filledNegs, _options, _toString, _emptyExt, _AST_instances, fillNegs_fn, _AST_static, parseAST_fn, canAdoptWithSpace_fn, canAdopt_fn, canAdoptType_fn, adoptWithSpace_fn, adopt_fn, canUsurpType_fn, canUsurp_fn, usurp_fn, flatten_fn, partsToRegExp_fn, parseGlob_fn, _Minimatch_instances, matchGlobstar_fn, matchGlobStarBodySections_fn, matchOne_fn, _reader;
17
- import { a as requireReact, S as ServerRouter, c as createReadableStreamFromReadable, r as reactExports, g as getDefaultExportFromCjs, R as React, b as ReactExports, w as withComponentProps, M as Meta, L as Links, d as ScrollRestoration, e as Scripts, O as Outlet, u as useNavigate, f as useSearchParams, h as Link$1, i as useLocation, j as useParams } from "./app-DiZXH6x4.js";
17
+ import { a as requireReact, S as ServerRouter, c as createReadableStreamFromReadable, r as reactExports, g as getDefaultExportFromCjs, R as React, b as ReactExports, w as withComponentProps, M as Meta, L as Links, d as ScrollRestoration, e as Scripts, O as Outlet, u as useNavigate, f as useSearchParams, h as Link$1, i as useLocation, j as useParams } from "./app-oogZ8ZwV.js";
18
18
  import require$$0$4, { PassThrough } from "node:stream";
19
19
  import require$$0 from "util";
20
20
  import require$$1 from "crypto";
@@ -64899,7 +64899,7 @@ var tn = f("block", "before:content-[counter(line)]", "before:inline-block", "be
64899
64899
  var et = ({ className: e, language: t, style: o, isIncomplete: n, ...s2 }) => jsxRuntimeExports.jsx("div", { className: f("my-4 flex w-full flex-col gap-2 rounded-xl border border-border bg-sidebar p-2", e), "data-incomplete": n || void 0, "data-language": t, "data-streamdown": "code-block", style: { contentVisibility: "auto", containIntrinsicSize: "auto 200px", ...o }, ...s2 });
64900
64900
  var Se = reactExports.createContext({ code: "" }), de$1 = () => reactExports.useContext(Se);
64901
64901
  var ot = ({ language: e }) => jsxRuntimeExports.jsx("div", { className: "flex h-8 items-center text-muted-foreground text-xs", "data-language": e, "data-streamdown": "code-block-header", children: jsxRuntimeExports.jsx("span", { className: "ml-1 font-mono lowercase", children: e }) });
64902
- var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-CmDnR6fu.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
64902
+ var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-z6TbPMtP.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
64903
64903
  let i = reactExports.useMemo(() => e.replace(cn$1, ""), [e]), c = reactExports.useMemo(() => ({ bg: "transparent", fg: "inherit", tokens: i.split(`
64904
64904
  `).map((a2) => [{ content: a2, color: "inherit", bgColor: "transparent", htmlStyle: {}, offset: 0 }]) }), [i]);
64905
64905
  return jsxRuntimeExports.jsx(Se.Provider, { value: { code: e }, children: jsxRuntimeExports.jsxs(et, { isIncomplete: s2, language: t, children: [jsxRuntimeExports.jsx(ot, { language: t }), n ? jsxRuntimeExports.jsx("div", { className: "pointer-events-none sticky top-2 z-10 -mt-10 flex h-8 items-center justify-end", children: jsxRuntimeExports.jsx("div", { className: "pointer-events-auto flex shrink-0 items-center gap-2 rounded-md border border-sidebar bg-sidebar/80 px-1.5 py-1 supports-[backdrop-filter]:bg-sidebar/70 supports-[backdrop-filter]:backdrop-blur", "data-streamdown": "code-block-actions", children: n }) }) : null, jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: jsxRuntimeExports.jsx(Qe, { className: o, language: t, result: c, ...r2 }), children: jsxRuntimeExports.jsx(dn, { className: o, code: i, language: t, raw: c, ...r2 }) })] }) });
@@ -65221,7 +65221,7 @@ var Dt = ({ children: e, className: t, onDownload: o, onError: n }) => {
65221
65221
  }, []), jsxRuntimeExports.jsxs("div", { className: "relative", ref: i, children: [jsxRuntimeExports.jsx("button", { className: f("cursor-pointer p-1 text-muted-foreground transition-all hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", t), disabled: c, onClick: () => r2(!s2), title: "Download table", type: "button", children: e != null ? e : jsxRuntimeExports.jsx(Z, { size: 14 }) }), s2 ? jsxRuntimeExports.jsxs("div", { className: "absolute top-full right-0 z-10 mt-1 min-w-[120px] overflow-hidden rounded-md border border-border bg-background shadow-lg", children: [jsxRuntimeExports.jsx("button", { className: "w-full px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40", onClick: () => a2("csv"), title: "Download table as CSV", type: "button", children: "CSV" }), jsxRuntimeExports.jsx("button", { className: "w-full px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40", onClick: () => a2("markdown"), title: "Download table as Markdown", type: "button", children: "Markdown" })] }) : null] });
65222
65222
  };
65223
65223
  var Vt = ({ children: e, className: t, showControls: o, ...n }) => jsxRuntimeExports.jsxs("div", { className: "my-4 flex flex-col gap-2 rounded-lg border border-border bg-sidebar p-2", "data-streamdown": "table-wrapper", children: [o ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-1", children: [jsxRuntimeExports.jsx(Ht, {}), jsxRuntimeExports.jsx(Dt, {})] }) : null, jsxRuntimeExports.jsx("div", { className: "border-collapse overflow-x-auto overscroll-y-auto rounded-md border border-border bg-background", children: jsxRuntimeExports.jsx("table", { className: f("w-full divide-y divide-border", t), "data-streamdown": "table", ...n, children: e }) })] });
65224
- var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-CxsJnUQo.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
65224
+ var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-XSKOerl0.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
65225
65225
  function ke(e, t) {
65226
65226
  if (!(e != null && e.position || t != null && t.position)) return true;
65227
65227
  if (!(e != null && e.position && (t != null && t.position))) return false;
@@ -70254,8 +70254,8 @@ function TraceViewerWithContextMenu({ trace: trace2, run, isLive, onWakeUpSleep,
70254
70254
  const getMenuItems = reactExports.useCallback((menu) => {
70255
70255
  var _a3, _b;
70256
70256
  const items = [];
70257
- const isRunActive = !run.completedAt;
70258
- if (menu.resourceType === "sleep" && menu.isActive && isRunActive && onWakeUpSleep) {
70257
+ const isRunActive2 = !run.completedAt;
70258
+ if (menu.resourceType === "sleep" && menu.isActive && isRunActive2 && onWakeUpSleep) {
70259
70259
  items.push({
70260
70260
  label: "Wake Up Sleep",
70261
70261
  icon: jsxRuntimeExports.jsx(Clock, { className: "h-3.5 w-3.5" }),
@@ -70278,7 +70278,7 @@ function TraceViewerWithContextMenu({ trace: trace2, run, isLive, onWakeUpSleep,
70278
70278
  }
70279
70279
  });
70280
70280
  }
70281
- if (menu.resourceType === "hook" && isRunActive && onResolveHook) {
70281
+ if (menu.resourceType === "hook" && isRunActive2 && onResolveHook) {
70282
70282
  const span = spanLookup.get(menu.spanId);
70283
70283
  const hookData = (_a3 = span == null ? void 0 : span.attributes) == null ? void 0 : _a3.data;
70284
70284
  const isDisposed = Boolean(hookData == null ? void 0 : hookData.disposedAt) || Boolean((_b = span == null ? void 0 : span.events) == null ? void 0 : _b.some((e) => e.name === "hook_disposed")) || resolvedHookIds.has(menu.spanId);
@@ -70295,7 +70295,7 @@ function TraceViewerWithContextMenu({ trace: trace2, run, isLive, onWakeUpSleep,
70295
70295
  });
70296
70296
  }
70297
70297
  }
70298
- if (menu.resourceType === "run" && isRunActive && onCancelRun) {
70298
+ if (menu.resourceType === "run" && isRunActive2 && onCancelRun) {
70299
70299
  items.push({
70300
70300
  label: "Cancel Run",
70301
70301
  icon: jsxRuntimeExports.jsx(CircleX, { className: "h-3.5 w-3.5" }),
@@ -92369,8 +92369,8 @@ function requireGetVercelOidcToken() {
92369
92369
  }
92370
92370
  try {
92371
92371
  const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
92372
- await import("./token-util-CxDoe-ao.js").then((n) => n.t),
92373
- await import("./token-C7BfiMAN.js").then((n) => n.t)
92372
+ await import("./token-util-DQ6afx9q.js").then((n) => n.t),
92373
+ await import("./token-Ct_osLcf.js").then((n) => n.t)
92374
92374
  ]);
92375
92375
  if (!token || isExpired(getTokenPayload(token), options == null ? void 0 : options.expirationBufferMs)) {
92376
92376
  await refreshToken(options);
@@ -120005,6 +120005,12 @@ function createEventsStorage(basedir, tag) {
120005
120005
  };
120006
120006
  await writeJSON(taggedPath(basedir, "hooks", data.correlationId, tag), hook);
120007
120007
  } else if (data.eventType === "hook_disposed") {
120008
+ const hookLockName = tag ? `${data.correlationId}.disposed.${tag}` : `${data.correlationId}.disposed`;
120009
+ const lockPath = path$3.join(basedir, ".locks", "hooks", hookLockName);
120010
+ const claimed = await writeExclusive(lockPath, "");
120011
+ if (!claimed) {
120012
+ throw new EntityConflictError(`Hook "${data.correlationId}" already disposed`);
120013
+ }
120008
120014
  const hookPath = taggedPath(basedir, "hooks", data.correlationId, tag);
120009
120015
  const existingHook = await readJSONWithFallback(basedir, "hooks", data.correlationId, HookSchema, tag);
120010
120016
  if (existingHook) {
@@ -120245,6 +120251,30 @@ function deserializeChunk(serialized) {
120245
120251
  const chunk = Buffer.from(serialized.subarray(1));
120246
120252
  return { eof, chunk };
120247
120253
  }
120254
+ async function listChunkFilesForStream(chunksDir, name2, tag) {
120255
+ const listPromises = [
120256
+ listFilesByExtension(chunksDir, ".bin"),
120257
+ listFilesByExtension(chunksDir, ".json")
120258
+ ];
120259
+ if (tag) {
120260
+ listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120261
+ }
120262
+ const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120263
+ const taggedBinFiles = taggedResults[0] ?? [];
120264
+ const extMap = /* @__PURE__ */ new Map();
120265
+ for (const f2 of jsonFiles)
120266
+ extMap.set(f2, ".json");
120267
+ const tagSfx = tag ? `.${tag}` : "";
120268
+ for (const f2 of binFiles) {
120269
+ if (tag && f2.endsWith(tagSfx))
120270
+ continue;
120271
+ extMap.set(f2, ".bin");
120272
+ }
120273
+ for (const f2 of taggedBinFiles)
120274
+ extMap.set(f2, `.${tag}.bin`);
120275
+ const files = [...extMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120276
+ return { files, extMap };
120277
+ }
120248
120278
  function createStreamer$1(basedir, tag) {
120249
120279
  const tagSuffix = tag ? `.${tag}` : "";
120250
120280
  const streamEmitter = new EventEmitter();
@@ -120335,27 +120365,7 @@ function createStreamer$1(basedir, tag) {
120335
120365
  async getStreamChunks(name2, _runId, options) {
120336
120366
  const limit = (options == null ? void 0 : options.limit) ?? 100;
120337
120367
  const chunksDir = path$3.join(basedir, "streams", "chunks");
120338
- const listPromises = [
120339
- listFilesByExtension(chunksDir, ".bin"),
120340
- listFilesByExtension(chunksDir, ".json")
120341
- ];
120342
- if (tag) {
120343
- listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120344
- }
120345
- const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120346
- const taggedBinFiles = taggedResults[0] ?? [];
120347
- const fileExtMap = /* @__PURE__ */ new Map();
120348
- for (const f2 of jsonFiles)
120349
- fileExtMap.set(f2, ".json");
120350
- const tagSfx = tag ? `.${tag}` : "";
120351
- for (const f2 of binFiles) {
120352
- if (tag && f2.endsWith(tagSfx))
120353
- continue;
120354
- fileExtMap.set(f2, ".bin");
120355
- }
120356
- for (const f2 of taggedBinFiles)
120357
- fileExtMap.set(f2, `.${tag}.bin`);
120358
- const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120368
+ const { files: chunkFiles, extMap: fileExtMap } = await listChunkFilesForStream(chunksDir, name2, tag);
120359
120369
  let startIndex = 0;
120360
120370
  if (options == null ? void 0 : options.cursor) {
120361
120371
  try {
@@ -120410,27 +120420,7 @@ function createStreamer$1(basedir, tag) {
120410
120420
  },
120411
120421
  async getStreamInfo(name2, _runId) {
120412
120422
  const chunksDir = path$3.join(basedir, "streams", "chunks");
120413
- const listPromises = [
120414
- listFilesByExtension(chunksDir, ".bin"),
120415
- listFilesByExtension(chunksDir, ".json")
120416
- ];
120417
- if (tag) {
120418
- listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120419
- }
120420
- const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120421
- const taggedBinFiles = taggedResults[0] ?? [];
120422
- const fileExtMap = /* @__PURE__ */ new Map();
120423
- for (const f2 of jsonFiles)
120424
- fileExtMap.set(f2, ".json");
120425
- const tagSfx = tag ? `.${tag}` : "";
120426
- for (const f2 of binFiles) {
120427
- if (tag && f2.endsWith(tagSfx))
120428
- continue;
120429
- fileExtMap.set(f2, ".bin");
120430
- }
120431
- for (const f2 of taggedBinFiles)
120432
- fileExtMap.set(f2, `.${tag}.bin`);
120433
- const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120423
+ const { files: chunkFiles, extMap: fileExtMap } = await listChunkFilesForStream(chunksDir, name2, tag);
120434
120424
  let streamDone = false;
120435
120425
  let dataCount = 0;
120436
120426
  for (const file2 of chunkFiles) {
@@ -120482,27 +120472,7 @@ function createStreamer$1(basedir, tag) {
120482
120472
  removeListeners = closeListener;
120483
120473
  streamEmitter.on(`chunk:${name2}`, chunkListener);
120484
120474
  streamEmitter.on(`close:${name2}`, closeListener);
120485
- const listPromises = [
120486
- listFilesByExtension(chunksDir, ".bin"),
120487
- listFilesByExtension(chunksDir, ".json")
120488
- ];
120489
- if (tag) {
120490
- listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120491
- }
120492
- const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120493
- const taggedBinFiles = taggedResults[0] ?? [];
120494
- const fileExtMap = /* @__PURE__ */ new Map();
120495
- for (const f2 of jsonFiles)
120496
- fileExtMap.set(f2, ".json");
120497
- const tagSuffix2 = tag ? `.${tag}` : "";
120498
- for (const f2 of binFiles) {
120499
- if (tag && f2.endsWith(tagSuffix2))
120500
- continue;
120501
- fileExtMap.set(f2, ".bin");
120502
- }
120503
- for (const f2 of taggedBinFiles)
120504
- fileExtMap.set(f2, `.${tag}.bin`);
120505
- const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120475
+ const { files: chunkFiles, extMap: fileExtMap } = await listChunkFilesForStream(chunksDir, name2, tag);
120506
120476
  let dataChunkCount = chunkFiles.length;
120507
120477
  if (typeof startIndex === "number" && startIndex < 0 && chunkFiles.length > 0) {
120508
120478
  const lastFile = chunkFiles[chunkFiles.length - 1];
@@ -120580,7 +120550,7 @@ function createLocalWorld(args) {
120580
120550
  const basedir = mergedConfig.dataDir;
120581
120551
  const hooksDir = path$3.join(basedir, "hooks");
120582
120552
  const taggedHookFiles = await listTaggedFiles(hooksDir, tag);
120583
- const { HookSchema: HookSchema2 } = await import("./index-cxStGfMq.js");
120553
+ const { HookSchema: HookSchema2 } = await import("./index-BL4Kw0eA.js");
120584
120554
  await Promise.all(taggedHookFiles.map(async (hookFile) => {
120585
120555
  const hook = await readJSON(path$3.join(hooksDir, hookFile), HookSchema2);
120586
120556
  if (hook == null ? void 0 : hook.token) {
@@ -125212,6 +125182,11 @@ function requireSeedrandom() {
125212
125182
  return seedrandom;
125213
125183
  }
125214
125184
  requireSeedrandom();
125185
+ const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
125186
+ const BASE64_LOOKUP = new Uint8Array(128).fill(255);
125187
+ for (let i = 0; i < BASE64_CHARS.length; i++) {
125188
+ BASE64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i;
125189
+ }
125215
125190
  async function getHookByTokenWithKey(token) {
125216
125191
  var _a3;
125217
125192
  const world = getWorld();
@@ -125295,7 +125270,7 @@ async function resumeHook$2(tokenOrHook, payload, encryptionKeyOverride) {
125295
125270
  });
125296
125271
  });
125297
125272
  }
125298
- const version = "4.2.0-beta.72";
125273
+ const version = "4.2.0-beta.74";
125299
125274
  const ulid = monotonicFactory();
125300
125275
  async function start$1(workflow, argsOrOptions, options) {
125301
125276
  return await waitedUntil(() => {
@@ -126812,15 +126787,45 @@ async function resumeHook$1(worldEnv, token, payload) {
126812
126787
  });
126813
126788
  }
126814
126789
  }
126815
- async function readStreamServerAction(env2, streamId, startIndex) {
126790
+ const CHUNKS_PAGE_SIZE = 500;
126791
+ async function readStreamChunksServerAction(env2, streamId, runId, startCursor) {
126816
126792
  try {
126817
126793
  const world = await getWorldFromEnv(env2);
126818
- return await world.readFromStream(streamId, startIndex);
126794
+ const allChunks = [];
126795
+ let pageCursor = startCursor;
126796
+ let streamDone = false;
126797
+ let resumeCursor = startCursor ?? null;
126798
+ do {
126799
+ const result = await world.getStreamChunks(streamId, runId, {
126800
+ limit: CHUNKS_PAGE_SIZE,
126801
+ cursor: pageCursor
126802
+ });
126803
+ for (const chunk of result.data) {
126804
+ allChunks.push(chunk.data);
126805
+ }
126806
+ streamDone = result.done;
126807
+ if (result.cursor) {
126808
+ resumeCursor = result.cursor;
126809
+ }
126810
+ pageCursor = result.cursor ?? void 0;
126811
+ } while (pageCursor);
126812
+ let totalSize = 0;
126813
+ for (const chunk of allChunks) {
126814
+ totalSize += chunk.length;
126815
+ }
126816
+ const body2 = new Uint8Array(totalSize);
126817
+ let offset2 = 0;
126818
+ for (const chunk of allChunks) {
126819
+ body2.set(chunk, offset2);
126820
+ offset2 += chunk.length;
126821
+ }
126822
+ return { buffer: body2, cursor: resumeCursor, done: streamDone };
126819
126823
  } catch (error2) {
126820
- const actionError = createServerActionError(error2, "world.readFromStream", {
126821
- streamId,
126822
- startIndex
126823
- });
126824
+ const actionError = createServerActionError(
126825
+ error2,
126826
+ "world.getStreamChunks",
126827
+ { streamId, runId }
126828
+ );
126824
126829
  if (!actionError.success) {
126825
126830
  return actionError.error;
126826
126831
  }
@@ -133010,9 +133015,13 @@ function useWorkflowTraceViewerData(env2, runId, options = {}) {
133010
133015
  function isServerActionError(value) {
133011
133016
  return typeof value === "object" && value !== null && "message" in value && "layer" in value && "cause" in value && "request" in value;
133012
133017
  }
133013
- async function readStream(_env, streamId, startIndex, signal) {
133018
+ async function readStream(_env, streamId, runId, signal, cursor) {
133014
133019
  try {
133015
- const url2 = `/api/stream/${encodeURIComponent(streamId)}${startIndex != null ? `?startIndex=${startIndex}` : ""}`;
133020
+ const params = new URLSearchParams({ runId });
133021
+ if (cursor) {
133022
+ params.set("cursor", cursor);
133023
+ }
133024
+ const url2 = `/api/stream/${encodeURIComponent(streamId)}?${params.toString()}`;
133016
133025
  const response2 = await fetch(url2, { signal });
133017
133026
  if (!response2.ok) {
133018
133027
  const errorData = await response2.json().catch(() => null);
@@ -133035,7 +133044,13 @@ async function readStream(_env, streamId, startIndex, signal) {
133035
133044
  layer: "client"
133036
133045
  });
133037
133046
  }
133038
- return response2.body;
133047
+ const responseCursor = response2.headers.get("X-Stream-Cursor");
133048
+ const streamDone = response2.headers.get("X-Stream-Done") === "true";
133049
+ return {
133050
+ body: response2.body,
133051
+ cursor: responseCursor,
133052
+ done: streamDone
133053
+ };
133039
133054
  } catch (error2) {
133040
133055
  if (error2 instanceof WorkflowWebAPIError) {
133041
133056
  throw error2;
@@ -133054,8 +133069,11 @@ function useWorkflowStreams(env2, runId, refreshInterval = STREAMS_REFRESH_INTER
133054
133069
  const [streams, setStreams] = reactExports.useState([]);
133055
133070
  const [loading, setLoading] = reactExports.useState(true);
133056
133071
  const [error2, setError] = reactExports.useState(null);
133072
+ const hasFetchedRef = reactExports.useRef(false);
133057
133073
  const fetchData = reactExports.useCallback(async () => {
133058
- setLoading(true);
133074
+ if (!hasFetchedRef.current) {
133075
+ setLoading(true);
133076
+ }
133059
133077
  setError(null);
133060
133078
  try {
133061
133079
  const result = await listStreams(env2, runId);
@@ -133063,10 +133081,12 @@ function useWorkflowStreams(env2, runId, refreshInterval = STREAMS_REFRESH_INTER
133063
133081
  } catch (err) {
133064
133082
  setError(err instanceof Error ? err : new Error(String(err)));
133065
133083
  } finally {
133084
+ hasFetchedRef.current = true;
133066
133085
  setLoading(false);
133067
133086
  }
133068
133087
  }, [env2, runId]);
133069
133088
  reactExports.useEffect(() => {
133089
+ hasFetchedRef.current = false;
133070
133090
  fetchData();
133071
133091
  }, [fetchData]);
133072
133092
  reactExports.useEffect(() => {
@@ -135201,8 +135221,8 @@ function useRunActions({
135201
135221
  const handleCancel = reactExports.useCallback(async () => {
135202
135222
  var _a3;
135203
135223
  if (cancelling) return;
135204
- const isRunActive = runStatus === "pending" || runStatus === "running";
135205
- if (!isRunActive) {
135224
+ const isRunActive2 = runStatus === "pending" || runStatus === "running";
135225
+ if (!isRunActive2) {
135206
135226
  toast.error("Cannot cancel", {
135207
135227
  description: "Only active runs can be cancelled"
135208
135228
  });
@@ -135286,7 +135306,7 @@ function RunActionsDropdownItems({
135286
135306
  if (stopPropagation) e.stopPropagation();
135287
135307
  handleCancel();
135288
135308
  };
135289
- const isRunActive = runStatus === "pending" || runStatus === "running";
135309
+ const isRunActive2 = runStatus === "pending" || runStatus === "running";
135290
135310
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
135291
135311
  /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenuItem, { onClick: onReplay, disabled: rerunning, children: [
135292
135312
  /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCw, { className: "h-4 w-4 mr-2" }),
@@ -135324,7 +135344,7 @@ function RunActionsDropdownItems({
135324
135344
  DropdownMenuItem,
135325
135345
  {
135326
135346
  onClick: onCancel,
135327
- disabled: !isRunActive || cancelling,
135347
+ disabled: !isRunActive2 || cancelling,
135328
135348
  children: [
135329
135349
  /* @__PURE__ */ jsxRuntimeExports.jsx(CircleX, { className: "h-4 w-4 mr-2" }),
135330
135350
  cancelling ? "Cancelling..." : "Cancel"
@@ -135351,10 +135371,10 @@ function RunActionsButtons({
135351
135371
  handleReenqueue,
135352
135372
  handleWakeUp
135353
135373
  } = useRunActions({ env: env2, runId, runStatus, events: events2, callbacks });
135354
- const isRunActive = runStatus === "pending" || runStatus === "running";
135355
- const canCancel = isRunActive;
135356
- const canRerun = !loading && !isRunActive;
135357
- const rerunDisabledReason = loading ? "Loading run data..." : isRunActive ? "Cannot re-run while workflow is still running" : "";
135374
+ const isRunActive2 = runStatus === "pending" || runStatus === "running";
135375
+ const canCancel = isRunActive2;
135376
+ const canRerun = !loading && !isRunActive2;
135377
+ const rerunDisabledReason = loading ? "Loading run data..." : isRunActive2 ? "Cannot re-run while workflow is still running" : "";
135358
135378
  const cancelDisabledReason = runStatus === "completed" ? "Run has already completed" : runStatus === "failed" ? "Run has already failed" : runStatus === "cancelled" ? "Run has already been cancelled" : "";
135359
135379
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
135360
135380
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
@@ -145714,17 +145734,12 @@ const baseNodeTypes = {
145714
145734
  parallelGroup: ParallelGroupComponent,
145715
145735
  diamondNode: DiamondNodeComponent
145716
145736
  };
145717
- const nodeTypes$1 = baseNodeTypes;
145737
+ const nodeTypes = baseNodeTypes;
145718
145738
  const defaultSelfLoopStyle = {
145719
145739
  strokeColor: "#6b7280",
145720
145740
  // gray-500
145721
145741
  labelBgClass: "bg-gray-200 dark:bg-gray-700 text-black dark:text-gray-200 border-gray-400 dark:border-gray-500"
145722
145742
  };
145723
- const executionSelfLoopStyle = {
145724
- strokeColor: "#a855f7",
145725
- // purple-500
145726
- labelBgClass: "bg-purple-200 dark:bg-purple-900/50 text-black dark:text-purple-200 border-purple-400 dark:border-purple-600"
145727
- };
145728
145743
  function createSelfLoopEdge(style2 = defaultSelfLoopStyle) {
145729
145744
  return function SelfLoopEdge2({
145730
145745
  id: id2,
@@ -145780,14 +145795,9 @@ function createSelfLoopEdge(style2 = defaultSelfLoopStyle) {
145780
145795
  };
145781
145796
  }
145782
145797
  const SelfLoopEdge = createSelfLoopEdge(defaultSelfLoopStyle);
145783
- const edgeTypes$1 = {
145798
+ const edgeTypes = {
145784
145799
  selfLoop: SelfLoopEdge
145785
145800
  };
145786
- function createEdgeTypes(selfLoopStyle = defaultSelfLoopStyle) {
145787
- return {
145788
- selfLoop: createSelfLoopEdge(selfLoopStyle)
145789
- };
145790
- }
145791
145801
  function getNodeBackgroundColor(nodeKind) {
145792
145802
  if (nodeKind === "workflow_start" || nodeKind === "workflow_end") {
145793
145803
  return "var(--node-bg-start)";
@@ -146020,7 +146030,7 @@ function consolidateEdges(edges, nodes) {
146020
146030
  }
146021
146031
  return consolidatedEdges;
146022
146032
  }
146023
- function convertToReactFlowNodes$1(workflow) {
146033
+ function convertToReactFlowNodes(workflow) {
146024
146034
  var _a3;
146025
146035
  const { nodes, groupNodes } = calculateEnhancedLayout(workflow);
146026
146036
  const nodeToParent = /* @__PURE__ */ new Map();
@@ -146146,7 +146156,7 @@ function convertToReactFlowNodes$1(workflow) {
146146
146156
  });
146147
146157
  return reactFlowNodes;
146148
146158
  }
146149
- function convertToReactFlowEdges$1(workflow) {
146159
+ function convertToReactFlowEdges(workflow) {
146150
146160
  const { additionalEdges } = calculateEnhancedLayout(workflow);
146151
146161
  const transformedOriginalEdges = workflow.edges.map((e) => {
146152
146162
  if (e.type === "loop") {
@@ -146249,18 +146259,18 @@ function convertToReactFlowEdges$1(workflow) {
146249
146259
  }
146250
146260
  function WorkflowGraphViewer({ workflow }) {
146251
146261
  const initialNodes = reactExports.useMemo(
146252
- () => convertToReactFlowNodes$1(workflow),
146262
+ () => convertToReactFlowNodes(workflow),
146253
146263
  [workflow]
146254
146264
  );
146255
146265
  const initialEdges = reactExports.useMemo(
146256
- () => convertToReactFlowEdges$1(workflow),
146266
+ () => convertToReactFlowEdges(workflow),
146257
146267
  [workflow]
146258
146268
  );
146259
146269
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
146260
146270
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
146261
146271
  reactExports.useEffect(() => {
146262
- setNodes(convertToReactFlowNodes$1(workflow));
146263
- setEdges(convertToReactFlowEdges$1(workflow));
146272
+ setNodes(convertToReactFlowNodes(workflow));
146273
+ setEdges(convertToReactFlowEdges(workflow));
146264
146274
  }, [workflow, setNodes, setEdges]);
146265
146275
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full w-full border rounded-lg bg-background relative overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
146266
146276
  index,
@@ -146269,8 +146279,8 @@ function WorkflowGraphViewer({ workflow }) {
146269
146279
  edges,
146270
146280
  onNodesChange,
146271
146281
  onEdgesChange,
146272
- nodeTypes: nodeTypes$1,
146273
- edgeTypes: edgeTypes$1,
146282
+ nodeTypes,
146283
+ edgeTypes,
146274
146284
  fitView: true,
146275
146285
  minZoom: 0.1,
146276
146286
  maxZoom: 2,
@@ -148211,732 +148221,61 @@ function BreadcrumbSeparator({
148211
148221
  }
148212
148222
  );
148213
148223
  }
148214
- const PRIMITIVE_LABELS = {
148215
- sleep: "sleep",
148216
- createHook: "createHook",
148217
- createWebhook: "createWebhook",
148218
- awaitWebhook: "awaitWebhook"
148219
- };
148220
- function normalizeStepName(name2) {
148221
- return name2.replace(/\/\/\.\.\//g, "//");
148222
- }
148223
- function createStepExecution(attemptStep, graphNodeId, idx, totalAttempts) {
148224
- let status;
148225
- switch (attemptStep.status) {
148226
- case "completed":
148227
- status = "completed";
148228
- break;
148229
- case "failed":
148230
- status = idx < totalAttempts - 1 ? "retrying" : "failed";
148231
- break;
148232
- case "running":
148233
- status = "running";
148234
- break;
148235
- case "cancelled":
148236
- status = "cancelled";
148237
- break;
148238
- case "pending":
148239
- default:
148240
- status = "pending";
148241
- break;
148242
- }
148243
- const duration2 = attemptStep.completedAt && attemptStep.startedAt ? new Date(attemptStep.completedAt).getTime() - new Date(attemptStep.startedAt).getTime() : void 0;
148244
- return {
148245
- nodeId: graphNodeId,
148246
- stepId: attemptStep.stepId,
148247
- attemptNumber: attemptStep.attempt,
148248
- status,
148249
- startedAt: attemptStep.startedAt ? new Date(attemptStep.startedAt).toISOString() : void 0,
148250
- completedAt: attemptStep.completedAt ? new Date(attemptStep.completedAt).toISOString() : void 0,
148251
- duration: duration2,
148252
- input: attemptStep.input,
148253
- output: attemptStep.output,
148254
- error: attemptStep.error ? {
148255
- message: attemptStep.error.message,
148256
- stack: attemptStep.error.stack || ""
148257
- } : void 0
148258
- };
148259
- }
148260
- function extractFunctionName(stepId) {
148261
- const parts = stepId.split("//");
148262
- return parts.length >= 3 ? parts[parts.length - 1] : null;
148263
- }
148264
- function buildNodeIndex(nodes) {
148265
- const byStepId = /* @__PURE__ */ new Map();
148266
- const byFunctionName = /* @__PURE__ */ new Map();
148267
- const primitivesByLabel = /* @__PURE__ */ new Map();
148268
- const agentNodes = [];
148269
- const toolNodes = /* @__PURE__ */ new Map();
148270
- for (const node2 of nodes) {
148271
- if (node2.data.stepId) {
148272
- const normalizedStepId = normalizeStepName(node2.data.stepId);
148273
- const existing = byStepId.get(normalizedStepId) || [];
148274
- existing.push(node2);
148275
- byStepId.set(normalizedStepId, existing);
148276
- const functionName = extractFunctionName(normalizedStepId);
148277
- if (functionName) {
148278
- const existingByName = byFunctionName.get(functionName) || [];
148279
- existingByName.push(node2);
148280
- byFunctionName.set(functionName, existingByName);
148281
- }
148282
- }
148283
- if (node2.data.nodeKind === "primitive") {
148284
- const label = node2.data.label;
148285
- const existing = primitivesByLabel.get(label) || [];
148286
- existing.push(node2);
148287
- primitivesByLabel.set(label, existing);
148288
- }
148289
- if (node2.data.nodeKind === "agent") {
148290
- agentNodes.push(node2);
148291
- }
148292
- if (node2.data.nodeKind === "tool") {
148293
- const label = node2.data.label;
148294
- const toolName = label.replace(/ \(tool\)$/, "");
148295
- const existing = toolNodes.get(toolName) || [];
148296
- existing.push(node2);
148297
- toolNodes.set(toolName, existing);
148298
- if (node2.data.stepId) {
148299
- const functionName = extractFunctionName(
148300
- normalizeStepName(node2.data.stepId)
148301
- );
148302
- if (functionName) {
148303
- const existingByName = toolNodes.get(functionName) || [];
148304
- if (!existingByName.includes(node2)) {
148305
- existingByName.push(node2);
148306
- toolNodes.set(functionName, existingByName);
148307
- }
148308
- }
148309
- }
148310
- }
148311
- }
148312
- return { byStepId, byFunctionName, primitivesByLabel, agentNodes, toolNodes };
148313
- }
148314
- function calculateEdgeTraversals(executionPath, graph, nodeExecutions) {
148315
- var _a3, _b, _c, _d;
148316
- const edgeTraversals = /* @__PURE__ */ new Map();
148317
- const executedNodes = new Set(executionPath);
148318
- const parallelGroups = /* @__PURE__ */ new Map();
148319
- for (const node2 of graph.nodes) {
148320
- const groupId = (_a3 = node2.metadata) == null ? void 0 : _a3.parallelGroupId;
148321
- if (groupId) {
148322
- const existing = parallelGroups.get(groupId) || { nodes: [] };
148323
- existing.nodes.push(node2);
148324
- existing.method = (_b = node2.metadata) == null ? void 0 : _b.parallelMethod;
148325
- parallelGroups.set(groupId, existing);
148326
- }
148327
- }
148328
- const raceWinners = /* @__PURE__ */ new Map();
148329
- for (const [groupId, group] of parallelGroups) {
148330
- if (group.method === "race") {
148331
- let winnerNodeId;
148332
- let earliestCompletion;
148333
- for (const node2 of group.nodes) {
148334
- const executions = nodeExecutions.get(node2.id);
148335
- if (executions) {
148336
- for (const exec of executions) {
148337
- if (exec.status === "completed" && exec.completedAt) {
148338
- const completedAt = new Date(exec.completedAt);
148339
- if (!earliestCompletion || completedAt < earliestCompletion) {
148340
- earliestCompletion = completedAt;
148341
- winnerNodeId = node2.id;
148342
- }
148343
- }
148344
- }
148345
- }
148346
- }
148347
- if (winnerNodeId) {
148348
- raceWinners.set(groupId, winnerNodeId);
148349
- }
148350
- }
148351
- }
148352
- const markEdgeTraversed = (edge) => {
148353
- const existing = edgeTraversals.get(edge.id);
148354
- if (existing) {
148355
- existing.traversalCount++;
148356
- } else {
148357
- edgeTraversals.set(edge.id, {
148358
- edgeId: edge.id,
148359
- traversalCount: 1,
148360
- timings: []
148361
- });
148362
- }
148363
- };
148364
- for (const edge of graph.edges) {
148365
- const sourceNode = graph.nodes.find((n) => n.id === edge.source);
148366
- const targetNode = graph.nodes.find((n) => n.id === edge.target);
148367
- if (!sourceNode || !targetNode) continue;
148368
- const sourceExecuted = executedNodes.has(edge.source);
148369
- const targetExecuted = executedNodes.has(edge.target);
148370
- if (!sourceExecuted && !targetExecuted) continue;
148371
- if (edge.type === "conditional") {
148372
- if (sourceExecuted && targetExecuted) {
148373
- markEdgeTraversed(edge);
148374
- }
148375
- continue;
148376
- }
148377
- const sourceGroupId = (_c = sourceNode.metadata) == null ? void 0 : _c.parallelGroupId;
148378
- const sourceMethod = (_d = sourceNode.metadata) == null ? void 0 : _d.parallelMethod;
148379
- if (sourceGroupId && sourceMethod === "race") {
148380
- const winner = raceWinners.get(sourceGroupId);
148381
- if (winner === edge.source && targetExecuted) {
148382
- markEdgeTraversed(edge);
148383
- }
148384
- } else if (sourceExecuted && targetExecuted) {
148385
- markEdgeTraversed(edge);
148386
- } else if (sourceExecuted && edge.type === "parallel") {
148387
- if (targetExecuted) {
148388
- markEdgeTraversed(edge);
148389
- }
148390
- }
148391
- }
148392
- return edgeTraversals;
148393
- }
148394
- function initializeStartNode(run, graph, executionPath, nodeExecutions) {
148395
- const startNode = graph.nodes.find(
148396
- (n) => n.data.nodeKind === "workflow_start"
148397
- );
148398
- if (startNode) {
148399
- executionPath.push(startNode.id);
148400
- nodeExecutions.set(startNode.id, [
148401
- {
148402
- nodeId: startNode.id,
148403
- attemptNumber: 1,
148404
- status: "completed",
148405
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
148406
- completedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0
148407
- // No duration for control flow nodes (start/end/conditional)
148408
- }
148409
- ]);
148410
- }
148411
- }
148412
- function addEndNodeExecution(run, graph, executionPath, nodeExecutions) {
148413
- const endNode = graph.nodes.find((n) => n.data.nodeKind === "workflow_end");
148414
- if (!endNode || executionPath.includes(endNode.id)) {
148415
- return;
148416
- }
148417
- let endNodeStatus;
148418
- switch (run.status) {
148419
- case "completed":
148420
- endNodeStatus = "completed";
148421
- break;
148422
- case "failed":
148423
- endNodeStatus = "failed";
148424
- break;
148425
- case "cancelled":
148426
- endNodeStatus = "cancelled";
148427
- break;
148428
- case "running":
148429
- endNodeStatus = "running";
148430
- break;
148431
- case "pending":
148432
- default:
148433
- return;
148434
- }
148435
- executionPath.push(endNode.id);
148436
- nodeExecutions.set(endNode.id, [
148437
- {
148438
- nodeId: endNode.id,
148439
- attemptNumber: 1,
148440
- status: endNodeStatus,
148441
- startedAt: run.completedAt ? new Date(run.completedAt).toISOString() : void 0,
148442
- completedAt: run.completedAt ? new Date(run.completedAt).toISOString() : void 0
148443
- // No duration for control flow nodes (start/end/conditional)
148444
- }
148445
- ]);
148446
- }
148447
- function processStepGroup(stepGroup, stepName, nodesByStepId, nodesByFunctionName, occurrenceCount, nodeExecutions, executionPath) {
148448
- const normalizedStepName = normalizeStepName(stepName);
148449
- const occurrenceIndex = occurrenceCount.get(normalizedStepName) || 0;
148450
- occurrenceCount.set(normalizedStepName, occurrenceIndex + 1);
148451
- let nodesWithStepId = nodesByStepId.get(normalizedStepName) || [];
148452
- let matchStrategy = "step-id";
148453
- if (nodesWithStepId.length === 0) {
148454
- const functionName = extractFunctionName(normalizedStepName);
148455
- if (functionName) {
148456
- nodesWithStepId = nodesByFunctionName.get(functionName) || [];
148457
- matchStrategy = "function-name";
148458
- }
148459
- }
148460
- const graphNode = nodesWithStepId.length === 1 ? nodesWithStepId[0] : nodesWithStepId[occurrenceIndex];
148461
- console.log("[Graph Mapper] Processing step group:", {
148462
- stepName,
148463
- normalizedStepName,
148464
- attempts: stepGroup.length,
148465
- occurrenceIndex,
148466
- totalNodesWithStepId: nodesWithStepId.length,
148467
- selectedNode: graphNode == null ? void 0 : graphNode.id,
148468
- allNodesWithStepId: nodesWithStepId.map((n) => n.id),
148469
- matchStrategy,
148470
- strategy: nodesWithStepId.length === 1 ? "single-node-multiple-invocations" : "occurrence-based"
148471
- });
148472
- if (!graphNode) {
148473
- return void 0;
148474
- }
148475
- const executions = stepGroup.map(
148476
- (attemptStep, idx) => createStepExecution(attemptStep, graphNode.id, idx, stepGroup.length)
148477
- );
148478
- if (nodesWithStepId.length === 1) {
148479
- const existing = nodeExecutions.get(graphNode.id) || [];
148480
- nodeExecutions.set(graphNode.id, [...existing, ...executions]);
148481
- } else {
148482
- nodeExecutions.set(graphNode.id, executions);
148483
- }
148484
- if (!executionPath.includes(graphNode.id)) {
148485
- executionPath.push(graphNode.id);
148486
- }
148487
- const latestExecution = executions[executions.length - 1];
148488
- return latestExecution.status === "running" ? graphNode.id : void 0;
148489
- }
148490
- function processPrimitiveEvents(events2, primitivesByLabel, nodeExecutions, executionPath) {
148491
- const occurrenceCount = /* @__PURE__ */ new Map();
148492
- const eventsByCorrelation = /* @__PURE__ */ new Map();
148493
- for (const event of events2) {
148494
- if (!event.correlationId) continue;
148495
- const existing = eventsByCorrelation.get(event.correlationId) || [];
148496
- existing.push(event);
148497
- eventsByCorrelation.set(event.correlationId, existing);
148498
- }
148499
- let currentNode;
148500
- const sleepNodes = primitivesByLabel.get(PRIMITIVE_LABELS.sleep) || [];
148501
- const sleepCorrelations = /* @__PURE__ */ new Set();
148502
- for (const event of events2) {
148503
- if (event.eventType === "wait_created" && event.correlationId) {
148504
- sleepCorrelations.add(event.correlationId);
148505
- }
148506
- }
148507
- const sortedSleepCorrelations = Array.from(sleepCorrelations).sort((a2, b2) => {
148508
- var _a3, _b;
148509
- const eventsA = eventsByCorrelation.get(a2) || [];
148510
- const eventsB = eventsByCorrelation.get(b2) || [];
148511
- const timeA = (_a3 = eventsA.find(
148512
- (e) => e.eventType === "wait_created"
148513
- )) == null ? void 0 : _a3.createdAt;
148514
- const timeB = (_b = eventsB.find(
148515
- (e) => e.eventType === "wait_created"
148516
- )) == null ? void 0 : _b.createdAt;
148517
- if (!timeA || !timeB) return 0;
148518
- return new Date(timeA).getTime() - new Date(timeB).getTime();
148519
- });
148520
- for (const correlationId of sortedSleepCorrelations) {
148521
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148522
- const createdEvent = correlationEvents.find(
148523
- (e) => e.eventType === "wait_created"
148524
- );
148525
- const completedEvent = correlationEvents.find(
148526
- (e) => e.eventType === "wait_completed"
148527
- );
148528
- if (!createdEvent) continue;
148529
- const occurrenceIndex = occurrenceCount.get(PRIMITIVE_LABELS.sleep) || 0;
148530
- occurrenceCount.set(PRIMITIVE_LABELS.sleep, occurrenceIndex + 1);
148531
- const graphNode = sleepNodes.length === 1 ? sleepNodes[0] : sleepNodes[occurrenceIndex];
148532
- if (!graphNode) continue;
148533
- let status = "running";
148534
- if (completedEvent) {
148535
- status = "completed";
148536
- }
148537
- const startedAt = new Date(createdEvent.createdAt).toISOString();
148538
- const completedAt = completedEvent ? new Date(completedEvent.createdAt).toISOString() : void 0;
148539
- const duration2 = completedEvent ? new Date(completedEvent.createdAt).getTime() - new Date(createdEvent.createdAt).getTime() : void 0;
148540
- const execution = {
148541
- nodeId: graphNode.id,
148542
- attemptNumber: 1,
148543
- status,
148544
- startedAt,
148545
- completedAt,
148546
- duration: duration2
148547
- };
148548
- const existing = nodeExecutions.get(graphNode.id) || [];
148549
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148550
- if (!executionPath.includes(graphNode.id)) {
148551
- executionPath.push(graphNode.id);
148552
- }
148553
- if (status === "running") {
148554
- currentNode = graphNode.id;
148555
- }
148556
- }
148557
- const hookNodes = [
148558
- ...primitivesByLabel.get(PRIMITIVE_LABELS.createHook) || [],
148559
- ...primitivesByLabel.get(PRIMITIVE_LABELS.createWebhook) || []
148560
- ];
148561
- const hookCorrelations = /* @__PURE__ */ new Set();
148562
- for (const event of events2) {
148563
- if (event.eventType === "hook_created" && event.correlationId) {
148564
- hookCorrelations.add(event.correlationId);
148565
- }
148566
- }
148567
- const sortedHookCorrelations = Array.from(hookCorrelations).sort((a2, b2) => {
148568
- var _a3, _b;
148569
- const eventsA = eventsByCorrelation.get(a2) || [];
148570
- const eventsB = eventsByCorrelation.get(b2) || [];
148571
- const timeA = (_a3 = eventsA.find(
148572
- (e) => e.eventType === "hook_created"
148573
- )) == null ? void 0 : _a3.createdAt;
148574
- const timeB = (_b = eventsB.find(
148575
- (e) => e.eventType === "hook_created"
148576
- )) == null ? void 0 : _b.createdAt;
148577
- if (!timeA || !timeB) return 0;
148578
- return new Date(timeA).getTime() - new Date(timeB).getTime();
148579
- });
148580
- let hookOccurrenceIndex = 0;
148581
- for (const correlationId of sortedHookCorrelations) {
148582
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148583
- const createdEvent = correlationEvents.find(
148584
- (e) => e.eventType === "hook_created"
148224
+ const FRAME_HEADER_SIZE = 4;
148225
+ const ENCRYPTED_PLACEHOLDER = "[Encrypted]";
148226
+ const POLL_INTERVAL_MS = 3e3;
148227
+ function isRunActive(status) {
148228
+ return status === "pending" || status === "running";
148229
+ }
148230
+ const MAX_DISPLAY_ENTRIES = 200;
148231
+ const MAX_DISPLAY_DEPTH = 6;
148232
+ function sanitizeForDisplay(value, depth = 0) {
148233
+ if (value === null || value === void 0) return value;
148234
+ if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
148235
+ const ta2 = value;
148236
+ const name2 = ta2.constructor.name;
148237
+ const preview = Array.from(
148238
+ { length: Math.min(ta2.length, 8) },
148239
+ (_2, i) => ta2[i]
148585
148240
  );
148586
- if (!createdEvent) continue;
148587
- const graphNode = hookNodes.length === 1 ? hookNodes[0] : hookNodes[hookOccurrenceIndex];
148588
- hookOccurrenceIndex++;
148589
- if (!graphNode) continue;
148590
- const status = "completed";
148591
- const startedAt = new Date(createdEvent.createdAt).toISOString();
148592
- const completedAt = new Date(createdEvent.createdAt).toISOString();
148593
- const execution = {
148594
- nodeId: graphNode.id,
148595
- attemptNumber: 1,
148596
- status,
148597
- startedAt,
148598
- completedAt,
148599
- duration: 0
148600
- };
148601
- const existing = nodeExecutions.get(graphNode.id) || [];
148602
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148603
- if (!executionPath.includes(graphNode.id)) {
148604
- executionPath.push(graphNode.id);
148605
- }
148241
+ const suffix = ta2.length > 8 ? ", …" : "";
148242
+ return `${name2}(${ta2.length}) [${preview.join(", ")}${suffix}]`;
148606
148243
  }
148607
- const awaitWebhookNodes = primitivesByLabel.get(PRIMITIVE_LABELS.awaitWebhook) || [];
148608
- const receivedHookCorrelations = /* @__PURE__ */ new Set();
148609
- for (const event of events2) {
148610
- if (event.eventType === "hook_received" && event.correlationId) {
148611
- receivedHookCorrelations.add(event.correlationId);
148612
- }
148613
- }
148614
- let awaitWebhookIndex = 0;
148615
- for (const correlationId of sortedHookCorrelations) {
148616
- const graphNode = awaitWebhookNodes.length === 1 ? awaitWebhookNodes[0] : awaitWebhookNodes[awaitWebhookIndex];
148617
- awaitWebhookIndex++;
148618
- if (!graphNode) continue;
148619
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148620
- const createdEvent = correlationEvents.find(
148621
- (e) => e.eventType === "hook_created"
148622
- );
148623
- const receivedEvent = correlationEvents.find(
148624
- (e) => e.eventType === "hook_received"
148625
- );
148626
- let status;
148627
- let startedAt;
148628
- let completedAt;
148629
- let duration2 = 0;
148630
- if (receivedEvent) {
148631
- status = "completed";
148632
- startedAt = createdEvent ? new Date(createdEvent.createdAt).toISOString() : new Date(receivedEvent.createdAt).toISOString();
148633
- completedAt = new Date(receivedEvent.createdAt).toISOString();
148634
- duration2 = new Date(completedAt).getTime() - new Date(startedAt).getTime();
148635
- } else if (createdEvent) {
148636
- status = "running";
148637
- startedAt = new Date(createdEvent.createdAt).toISOString();
148638
- } else {
148639
- status = "pending";
148640
- }
148641
- const execution = {
148642
- nodeId: graphNode.id,
148643
- attemptNumber: 1,
148644
- status,
148645
- startedAt,
148646
- completedAt,
148647
- duration: duration2
148648
- };
148649
- const existing = nodeExecutions.get(graphNode.id) || [];
148650
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148651
- if (!executionPath.includes(graphNode.id)) {
148652
- executionPath.push(graphNode.id);
148653
- }
148244
+ if (value instanceof ArrayBuffer) {
148245
+ return `ArrayBuffer(${value.byteLength})`;
148654
148246
  }
148655
- return currentNode;
148656
- }
148657
- function processAgentAndToolNodes(run, steps, agentNodes, toolNodes, nodeExecutions, executionPath, allNodes) {
148658
- var _a3;
148659
- let agentStatus = "pending";
148660
- if (run.status === "completed") {
148661
- agentStatus = "completed";
148662
- } else if (run.status === "failed") {
148663
- agentStatus = "failed";
148664
- } else if (run.status === "running") {
148665
- agentStatus = "running";
148666
- }
148667
- for (const agentNode of agentNodes) {
148668
- const execution = {
148669
- nodeId: agentNode.id,
148670
- attemptNumber: 1,
148671
- status: agentStatus,
148672
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
148673
- completedAt: run.completedAt && (agentStatus === "completed" || agentStatus === "failed") ? new Date(run.completedAt).toISOString() : void 0
148674
- };
148675
- nodeExecutions.set(agentNode.id, [execution]);
148676
- if (!executionPath.includes(agentNode.id)) {
148677
- executionPath.push(agentNode.id);
148678
- }
148679
- }
148680
- for (const step of steps) {
148681
- const functionName = extractFunctionName(step.stepName);
148682
- if (!functionName) continue;
148683
- const matchingToolNodes = toolNodes.get(functionName);
148684
- if (!matchingToolNodes || matchingToolNodes.length === 0) continue;
148685
- const toolNode = matchingToolNodes[0];
148686
- let status;
148687
- switch (step.status) {
148688
- case "completed":
148689
- status = "completed";
148690
- break;
148691
- case "failed":
148692
- status = "failed";
148693
- break;
148694
- case "running":
148695
- status = "running";
148696
- break;
148697
- case "cancelled":
148698
- status = "cancelled";
148699
- break;
148700
- case "pending":
148701
- default:
148702
- status = "pending";
148703
- break;
148704
- }
148705
- const duration2 = step.completedAt && step.startedAt ? new Date(step.completedAt).getTime() - new Date(step.startedAt).getTime() : void 0;
148706
- const execution = {
148707
- nodeId: toolNode.id,
148708
- stepId: step.stepId,
148709
- attemptNumber: step.attempt,
148710
- status,
148711
- startedAt: step.startedAt ? new Date(step.startedAt).toISOString() : void 0,
148712
- completedAt: step.completedAt ? new Date(step.completedAt).toISOString() : void 0,
148713
- duration: duration2,
148714
- input: step.input,
148715
- output: step.output,
148716
- error: step.error
148717
- };
148718
- const existing = nodeExecutions.get(toolNode.id) || [];
148719
- nodeExecutions.set(toolNode.id, [...existing, execution]);
148720
- if (!executionPath.includes(toolNode.id)) {
148721
- executionPath.push(toolNode.id);
148722
- }
148247
+ if (depth >= MAX_DISPLAY_DEPTH) {
148248
+ if (Array.isArray(value)) return `Array(${value.length})`;
148249
+ if (typeof value === "object") return "{…}";
148250
+ return value;
148723
148251
  }
148724
- for (const node2 of allNodes) {
148725
- const isToolsCollection = ((_a3 = node2.metadata) == null ? void 0 : _a3.isToolsCollection) === true;
148726
- if (node2.data.nodeKind === "tool" && isToolsCollection && !nodeExecutions.has(node2.id)) {
148727
- const execution = {
148728
- nodeId: node2.id,
148729
- attemptNumber: 1,
148730
- status: agentStatus,
148731
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
148732
- completedAt: run.completedAt && (agentStatus === "completed" || agentStatus === "failed") ? new Date(run.completedAt).toISOString() : void 0
148733
- };
148734
- nodeExecutions.set(node2.id, [execution]);
148735
- if (!executionPath.includes(node2.id)) {
148736
- executionPath.push(node2.id);
148737
- }
148252
+ if (Array.isArray(value)) {
148253
+ if (value.length <= MAX_DISPLAY_ENTRIES) {
148254
+ return value.map((v2) => sanitizeForDisplay(v2, depth + 1));
148738
148255
  }
148256
+ const trimmed = value.slice(0, MAX_DISPLAY_ENTRIES).map((v2) => sanitizeForDisplay(v2, depth + 1));
148257
+ trimmed.push(`… ${value.length - MAX_DISPLAY_ENTRIES} more items`);
148258
+ return trimmed;
148739
148259
  }
148740
- }
148741
- function processConditionalNodes(graph, nodeExecutions, executionPath, run) {
148742
- var _a3, _b, _c;
148743
- const conditionalNodes = graph.nodes.filter(
148744
- (n) => n.data.nodeKind === "conditional"
148745
- );
148746
- const nodesByConditionalId = /* @__PURE__ */ new Map();
148747
- for (const node2 of graph.nodes) {
148748
- const condId = (_a3 = node2.metadata) == null ? void 0 : _a3.conditionalId;
148749
- if (condId) {
148750
- const group = nodesByConditionalId.get(condId) || {
148751
- thenNodes: [],
148752
- elseNodes: []
148753
- };
148754
- if (((_b = node2.metadata) == null ? void 0 : _b.conditionalBranch) === "Then") {
148755
- group.thenNodes.push(node2);
148756
- } else if (((_c = node2.metadata) == null ? void 0 : _c.conditionalBranch) === "Else") {
148757
- group.elseNodes.push(node2);
148758
- }
148759
- nodesByConditionalId.set(condId, group);
148760
- }
148761
- }
148762
- for (const condNode of conditionalNodes) {
148763
- const condIdMatch = condNode.id.match(/^(cond_\d+)_node$/);
148764
- if (!condIdMatch) continue;
148765
- const condId = condIdMatch[1];
148766
- const branches = nodesByConditionalId.get(condId);
148767
- if (!branches) continue;
148768
- const thenExecuted = branches.thenNodes.some(
148769
- (n) => nodeExecutions.has(n.id)
148770
- );
148771
- const elseExecuted = branches.elseNodes.some(
148772
- (n) => nodeExecutions.has(n.id)
148773
- );
148774
- if (thenExecuted || elseExecuted) {
148775
- const allBranchNodes = [...branches.thenNodes, ...branches.elseNodes];
148776
- if (!nodeExecutions.has(condNode.id)) {
148777
- let earliestTime;
148778
- for (const branchNode of allBranchNodes) {
148779
- const execs = nodeExecutions.get(branchNode.id);
148780
- if (execs && execs.length > 0) {
148781
- const firstExec = execs[0];
148782
- if (firstExec.startedAt && (!earliestTime || firstExec.startedAt < earliestTime)) {
148783
- earliestTime = firstExec.startedAt;
148784
- }
148785
- }
148786
- }
148787
- const fallbackTime = run.startedAt ? new Date(run.startedAt).toISOString() : void 0;
148788
- const execution = {
148789
- nodeId: condNode.id,
148790
- attemptNumber: 1,
148791
- status: "completed",
148792
- startedAt: earliestTime || fallbackTime,
148793
- completedAt: earliestTime || fallbackTime
148794
- // No duration for control flow nodes (start/end/conditional)
148795
- };
148796
- nodeExecutions.set(condNode.id, [execution]);
148797
- }
148798
- if (!executionPath.includes(condNode.id)) {
148799
- const branchIndices = allBranchNodes.map((n) => executionPath.indexOf(n.id)).filter((i) => i >= 0);
148800
- if (branchIndices.length > 0) {
148801
- const firstBranchIndex = Math.min(...branchIndices);
148802
- if (firstBranchIndex >= 0 && firstBranchIndex < executionPath.length) {
148803
- executionPath.splice(firstBranchIndex, 0, condNode.id);
148804
- } else {
148805
- executionPath.push(condNode.id);
148806
- }
148807
- } else {
148808
- executionPath.push(condNode.id);
148809
- }
148810
- }
148260
+ if (typeof value === "object") {
148261
+ const keys2 = Object.keys(value);
148262
+ const out = {};
148263
+ const limit = Math.min(keys2.length, MAX_DISPLAY_ENTRIES);
148264
+ for (let i = 0; i < limit; i++) {
148265
+ out[keys2[i]] = sanitizeForDisplay(
148266
+ value[keys2[i]],
148267
+ depth + 1
148268
+ );
148811
148269
  }
148812
- }
148813
- }
148814
- function mapRunToExecution(run, steps, events2, graph) {
148815
- const nodeExecutions = /* @__PURE__ */ new Map();
148816
- const executionPath = [];
148817
- let currentNode;
148818
- console.log("[Graph Mapper] Mapping run to execution:", {
148819
- runId: run.runId,
148820
- workflowName: run.workflowName,
148821
- graphNodes: graph.nodes.length,
148822
- stepsCount: steps.length
148823
- });
148824
- initializeStartNode(run, graph, executionPath, nodeExecutions);
148825
- const sortedSteps = [...steps].sort(
148826
- (a2, b2) => new Date(a2.createdAt).getTime() - new Date(b2.createdAt).getTime()
148827
- );
148828
- console.log(
148829
- "[Graph Mapper] Sorted steps:",
148830
- sortedSteps.map((s2) => ({
148831
- stepId: s2.stepId,
148832
- stepName: s2.stepName,
148833
- attempt: s2.attempt,
148834
- status: s2.status,
148835
- createdAt: s2.createdAt
148836
- }))
148837
- );
148838
- const {
148839
- byStepId: nodesByStepId,
148840
- byFunctionName: nodesByFunctionName,
148841
- primitivesByLabel,
148842
- agentNodes,
148843
- toolNodes
148844
- } = buildNodeIndex(graph.nodes);
148845
- console.log("[Graph Mapper] Graph nodes by stepId:", {
148846
- allGraphNodes: graph.nodes.map((n) => ({
148847
- id: n.id,
148848
- stepId: n.data.stepId,
148849
- normalizedStepId: n.data.stepId ? normalizeStepName(n.data.stepId) : void 0,
148850
- nodeKind: n.data.nodeKind
148851
- })),
148852
- nodesByStepId: Array.from(nodesByStepId.entries()).map(
148853
- ([stepId, nodes]) => ({
148854
- stepId,
148855
- nodeIds: nodes.map((n) => n.id)
148856
- })
148857
- )
148858
- });
148859
- const stepNameOccurrenceCount = /* @__PURE__ */ new Map();
148860
- let currentStepGroup = [];
148861
- let currentStepId = null;
148862
- let currentStepName = null;
148863
- for (let i = 0; i <= sortedSteps.length; i++) {
148864
- const step = sortedSteps[i];
148865
- const isNewInvocation = !step || step.stepId !== currentStepId;
148866
- if (isNewInvocation) {
148867
- if (currentStepGroup.length > 0 && currentStepName) {
148868
- const runningNode = processStepGroup(
148869
- currentStepGroup,
148870
- currentStepName,
148871
- nodesByStepId,
148872
- nodesByFunctionName,
148873
- stepNameOccurrenceCount,
148874
- nodeExecutions,
148875
- executionPath
148876
- );
148877
- if (runningNode) {
148878
- currentNode = runningNode;
148879
- }
148880
- }
148881
- if (step) {
148882
- currentStepGroup = [step];
148883
- currentStepId = step.stepId;
148884
- currentStepName = step.stepName;
148885
- }
148886
- } else {
148887
- currentStepGroup.push(step);
148270
+ if (keys2.length > MAX_DISPLAY_ENTRIES) {
148271
+ out[`… ${keys2.length - MAX_DISPLAY_ENTRIES} more keys`] = "…";
148888
148272
  }
148273
+ return out;
148889
148274
  }
148890
- const primitiveCurrentNode = processPrimitiveEvents(
148891
- events2,
148892
- primitivesByLabel,
148893
- nodeExecutions,
148894
- executionPath
148895
- );
148896
- if (primitiveCurrentNode) {
148897
- currentNode = primitiveCurrentNode;
148898
- }
148899
- processAgentAndToolNodes(
148900
- run,
148901
- sortedSteps,
148902
- agentNodes,
148903
- toolNodes,
148904
- nodeExecutions,
148905
- executionPath,
148906
- graph.nodes
148907
- );
148908
- processConditionalNodes(graph, nodeExecutions, executionPath, run);
148909
- addEndNodeExecution(run, graph, executionPath, nodeExecutions);
148910
- const edgeTraversals = calculateEdgeTraversals(
148911
- executionPath,
148912
- graph,
148913
- nodeExecutions
148914
- );
148915
- const result = {
148916
- runId: run.runId,
148917
- status: run.status,
148918
- nodeExecutions,
148919
- edgeTraversals,
148920
- currentNode,
148921
- executionPath
148922
- };
148923
- console.log("[Graph Mapper] Mapping complete:", {
148924
- executionPath,
148925
- nodeExecutionsCount: nodeExecutions.size,
148926
- nodeExecutions: Array.from(nodeExecutions.entries()).map(
148927
- ([nodeId, execs]) => {
148928
- var _a3;
148929
- return {
148930
- nodeId,
148931
- executionCount: execs.length,
148932
- latestStatus: (_a3 = execs[execs.length - 1]) == null ? void 0 : _a3.status
148933
- };
148934
- }
148935
- )
148936
- });
148937
- return result;
148275
+ return value;
148938
148276
  }
148939
- const FRAME_HEADER_SIZE = 4;
148277
+ const yieldToMain = () => new Promise((resolve2) => setTimeout(resolve2, 0));
148278
+ const YIELD_EVERY_N_FRAMES = 64;
148940
148279
  function detectEncoding(data) {
148941
148280
  if (data.length < FRAME_HEADER_SIZE) return "framed";
148942
148281
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
@@ -148944,17 +148283,75 @@ function detectEncoding(data) {
148944
148283
  if (len > 0 && len <= 10 * 1024 * 1024) return "framed";
148945
148284
  return "legacy";
148946
148285
  }
148947
- function useStreamReader(env2, streamId, runId, encryptionKey) {
148286
+ function useStreamReader(env2, streamId, runId, encryptionKey, runStatus) {
148948
148287
  const [chunks, setChunks] = reactExports.useState([]);
148949
148288
  const [isLive, setIsLive] = reactExports.useState(false);
148950
148289
  const [error2, setError] = reactExports.useState(null);
148951
148290
  const abortControllerRef = reactExports.useRef(null);
148952
148291
  const chunkIdRef = reactExports.useRef(0);
148292
+ const frameCountRef = reactExports.useRef(0);
148293
+ const pollTimerRef = reactExports.useRef(null);
148294
+ const runStatusRef = reactExports.useRef(runStatus);
148295
+ runStatusRef.current = runStatus;
148296
+ const serverCursorRef = reactExports.useRef(null);
148297
+ const processFrame = reactExports.useCallback(
148298
+ async (rawFrame, cryptoKey, revivers) => {
148299
+ let frameData = rawFrame;
148300
+ if (frameData.length >= FRAME_HEADER_SIZE + 4 && !isEncryptedData(frameData)) {
148301
+ const innerView = new DataView(
148302
+ frameData.buffer,
148303
+ frameData.byteOffset,
148304
+ frameData.byteLength
148305
+ );
148306
+ const innerLen = innerView.getUint32(0, false);
148307
+ if (innerLen > 0 && innerLen <= 10 * 1024 * 1024 && innerLen === frameData.length - FRAME_HEADER_SIZE) {
148308
+ frameData = frameData.slice(FRAME_HEADER_SIZE);
148309
+ }
148310
+ }
148311
+ let hydrated;
148312
+ try {
148313
+ if (isEncryptedData(frameData)) {
148314
+ if (!cryptoKey) {
148315
+ return { encrypted: true };
148316
+ }
148317
+ const payload = frameData.slice(4);
148318
+ hydrated = hydrateData(
148319
+ await decrypt(cryptoKey, payload),
148320
+ revivers
148321
+ );
148322
+ } else {
148323
+ hydrated = hydrateData(frameData, revivers);
148324
+ }
148325
+ } catch {
148326
+ hydrated = ENCRYPTED_PLACEHOLDER;
148327
+ }
148328
+ let text2;
148329
+ try {
148330
+ if (typeof hydrated === "string") {
148331
+ text2 = hydrated;
148332
+ } else {
148333
+ const safe = sanitizeForDisplay(hydrated);
148334
+ text2 = JSON.stringify(safe, null, 2);
148335
+ }
148336
+ } catch {
148337
+ text2 = "[Serialization Error]";
148338
+ }
148339
+ const chunkId = chunkIdRef.current++;
148340
+ return { encrypted: false, chunk: { id: chunkId, text: text2 } };
148341
+ },
148342
+ []
148343
+ );
148953
148344
  reactExports.useEffect(() => {
148954
148345
  setChunks([]);
148955
148346
  setError(null);
148956
148347
  chunkIdRef.current = 0;
148957
- if (!streamId) {
148348
+ frameCountRef.current = 0;
148349
+ serverCursorRef.current = null;
148350
+ if (pollTimerRef.current) {
148351
+ clearTimeout(pollTimerRef.current);
148352
+ pollTimerRef.current = null;
148353
+ }
148354
+ if (!streamId || !runId) {
148958
148355
  setIsLive(false);
148959
148356
  return;
148960
148357
  }
@@ -148963,119 +148360,177 @@ function useStreamReader(env2, streamId, runId, encryptionKey) {
148963
148360
  abortControllerRef.current = abortController;
148964
148361
  setIsLive(true);
148965
148362
  const revivers = getWebRevivers();
148966
- const readStreamData = async () => {
148363
+ const parseLegacyLine = (line) => {
148364
+ const chunkId = chunkIdRef.current++;
148365
+ let text2;
148967
148366
  try {
148968
- const rawStream = await readStream(
148969
- env2,
148970
- streamId,
148971
- void 0,
148972
- abortController.signal
148973
- );
148974
- const cryptoKey = encryptionKey ? await importKey(encryptionKey) : void 0;
148975
- const reader = rawStream.getReader();
148976
- const decoder2 = new TextDecoder();
148977
- let buffer = new Uint8Array(0);
148978
- let encoding2 = null;
148979
- let textRemainder = "";
148980
- const appendToBuffer = (data) => {
148981
- const newBuffer = new Uint8Array(buffer.length + data.length);
148982
- newBuffer.set(buffer, 0);
148983
- newBuffer.set(data, buffer.length);
148984
- buffer = newBuffer;
148985
- };
148986
- const addLegacyLine = (line) => {
148987
- if (!mounted || !line) return;
148988
- const chunkId = chunkIdRef.current++;
148989
- let text2;
148990
- try {
148991
- const parsed = JSON.parse(line);
148992
- text2 = JSON.stringify(parsed, null, 2);
148993
- } catch {
148994
- text2 = line;
148995
- }
148996
- setChunks((prev) => [...prev, { id: chunkId, text: text2 }]);
148997
- };
148998
- for (; ; ) {
148999
- if (abortController.signal.aborted) break;
149000
- const { value, done } = await reader.read();
149001
- if (done) {
149002
- if (encoding2 === "legacy" && textRemainder.trim()) {
149003
- addLegacyLine(textRemainder.trim());
149004
- textRemainder = "";
148367
+ const parsed = JSON.parse(line);
148368
+ text2 = JSON.stringify(parsed, null, 2);
148369
+ } catch {
148370
+ text2 = line;
148371
+ }
148372
+ return { id: chunkId, text: text2 };
148373
+ };
148374
+ const fetchAndParse = async (targetBuffer, cryptoKey, options) => {
148375
+ const streamResponse = await readStream(
148376
+ env2,
148377
+ streamId,
148378
+ runId,
148379
+ abortController.signal,
148380
+ options == null ? void 0 : options.cursor
148381
+ );
148382
+ const skipFrames = (options == null ? void 0 : options.skipFrames) ?? 0;
148383
+ const reader = streamResponse.body.getReader();
148384
+ const decoder2 = new TextDecoder();
148385
+ let buffer = new Uint8Array(0);
148386
+ let encoding2 = null;
148387
+ let textRemainder = "";
148388
+ let frameIndex = 0;
148389
+ const appendToBuffer = (data) => {
148390
+ const newBuffer = new Uint8Array(buffer.length + data.length);
148391
+ newBuffer.set(buffer, 0);
148392
+ newBuffer.set(data, buffer.length);
148393
+ buffer = newBuffer;
148394
+ };
148395
+ for (; ; ) {
148396
+ if (abortController.signal.aborted) break;
148397
+ const { value, done } = await reader.read();
148398
+ if (done) {
148399
+ if (encoding2 === "legacy" && textRemainder.trim()) {
148400
+ frameIndex++;
148401
+ if (frameIndex > skipFrames) {
148402
+ targetBuffer.push(parseLegacyLine(textRemainder.trim()));
149005
148403
  }
149006
- if (mounted) setIsLive(false);
149007
- break;
148404
+ textRemainder = "";
149008
148405
  }
149009
- if (encoding2 === null) {
149010
- appendToBuffer(value);
149011
- if (buffer.length >= FRAME_HEADER_SIZE) {
149012
- encoding2 = detectEncoding(buffer);
149013
- }
149014
- if (encoding2 === "legacy") {
149015
- textRemainder = decoder2.decode(buffer, { stream: true });
149016
- buffer = new Uint8Array(0);
149017
- }
149018
- } else if (encoding2 === "legacy") {
149019
- textRemainder += decoder2.decode(value, { stream: true });
149020
- } else {
149021
- appendToBuffer(value);
148406
+ break;
148407
+ }
148408
+ if (encoding2 === null) {
148409
+ appendToBuffer(value);
148410
+ if (buffer.length >= FRAME_HEADER_SIZE) {
148411
+ encoding2 = detectEncoding(buffer);
149022
148412
  }
149023
148413
  if (encoding2 === "legacy") {
149024
- const lines = textRemainder.split("\n");
149025
- textRemainder = lines.pop() ?? "";
149026
- for (const line of lines) {
149027
- const trimmed = line.trim();
149028
- if (trimmed) addLegacyLine(trimmed);
148414
+ textRemainder = decoder2.decode(buffer, { stream: true });
148415
+ buffer = new Uint8Array(0);
148416
+ }
148417
+ } else if (encoding2 === "legacy") {
148418
+ textRemainder += decoder2.decode(value, { stream: true });
148419
+ } else {
148420
+ appendToBuffer(value);
148421
+ }
148422
+ if (encoding2 === "legacy") {
148423
+ const lines = textRemainder.split("\n");
148424
+ textRemainder = lines.pop() ?? "";
148425
+ for (const line of lines) {
148426
+ const trimmed = line.trim();
148427
+ if (trimmed) {
148428
+ frameIndex++;
148429
+ if (frameIndex > skipFrames) {
148430
+ targetBuffer.push(parseLegacyLine(trimmed));
148431
+ }
149029
148432
  }
148433
+ }
148434
+ continue;
148435
+ }
148436
+ let offset2 = 0;
148437
+ let framesInBatch = 0;
148438
+ while (offset2 + FRAME_HEADER_SIZE <= buffer.length) {
148439
+ const view = new DataView(
148440
+ buffer.buffer,
148441
+ buffer.byteOffset + offset2,
148442
+ buffer.byteLength - offset2
148443
+ );
148444
+ const frameLength = view.getUint32(0, false);
148445
+ if (frameLength === 0 || frameLength > 10 * 1024 * 1024) {
148446
+ break;
148447
+ }
148448
+ if (offset2 + FRAME_HEADER_SIZE + frameLength > buffer.length) {
148449
+ break;
148450
+ }
148451
+ const frameData = buffer.slice(
148452
+ offset2 + FRAME_HEADER_SIZE,
148453
+ offset2 + FRAME_HEADER_SIZE + frameLength
148454
+ );
148455
+ offset2 += FRAME_HEADER_SIZE + frameLength;
148456
+ frameIndex++;
148457
+ if (frameIndex <= skipFrames) {
149030
148458
  continue;
149031
148459
  }
149032
- while (buffer.length >= FRAME_HEADER_SIZE) {
149033
- const view = new DataView(
149034
- buffer.buffer,
149035
- buffer.byteOffset,
149036
- buffer.byteLength
149037
- );
149038
- const frameLength = view.getUint32(0, false);
149039
- if (frameLength === 0 || frameLength > 10 * 1024 * 1024) {
149040
- break;
149041
- }
149042
- if (buffer.length < FRAME_HEADER_SIZE + frameLength) {
149043
- break;
149044
- }
149045
- const frameData = buffer.slice(
149046
- FRAME_HEADER_SIZE,
149047
- FRAME_HEADER_SIZE + frameLength
149048
- );
149049
- buffer = buffer.slice(FRAME_HEADER_SIZE + frameLength);
148460
+ const result = await processFrame(frameData, cryptoKey, revivers);
148461
+ if (result.encrypted) {
148462
+ reader.cancel().catch(() => {
148463
+ });
148464
+ return { encrypted: true };
148465
+ }
148466
+ targetBuffer.push(result.chunk);
148467
+ framesInBatch++;
148468
+ if (framesInBatch % YIELD_EVERY_N_FRAMES === 0) {
148469
+ await yieldToMain();
148470
+ if (abortController.signal.aborted || !mounted) break;
148471
+ }
148472
+ }
148473
+ buffer = buffer.slice(offset2);
148474
+ }
148475
+ return {
148476
+ encrypted: false,
148477
+ frameCount: frameIndex,
148478
+ cursor: streamResponse.cursor,
148479
+ done: streamResponse.done
148480
+ };
148481
+ };
148482
+ const readStreamData = async () => {
148483
+ try {
148484
+ const cryptoKey = encryptionKey ? await importKey(encryptionKey) : void 0;
148485
+ const initialChunks = [];
148486
+ const result = await fetchAndParse(initialChunks, cryptoKey);
148487
+ if (result.encrypted) {
148488
+ if (mounted) {
148489
+ setError("This stream is encrypted. Click Decrypt to view.");
148490
+ setIsLive(false);
148491
+ }
148492
+ return;
148493
+ }
148494
+ frameCountRef.current = result.frameCount;
148495
+ serverCursorRef.current = result.cursor;
148496
+ if (!mounted || abortController.signal.aborted) return;
148497
+ setChunks(initialChunks);
148498
+ if (result.done) {
148499
+ setIsLive(false);
148500
+ return;
148501
+ }
148502
+ if (isRunActive(runStatusRef.current)) {
148503
+ const poll = async () => {
148504
+ if (!mounted || abortController.signal.aborted) return;
149050
148505
  try {
149051
- const { format: format2, payload } = decodeFormatPrefix$1(frameData);
149052
- let dataToHydrate;
149053
- if (format2 === SerializationFormat$1.ENCRYPTED) {
149054
- if (!cryptoKey) {
149055
- if (mounted) {
149056
- setError(
149057
- "This stream is encrypted. Click Decrypt to view."
149058
- );
149059
- setIsLive(false);
149060
- }
149061
- reader.cancel().catch(() => {
149062
- });
148506
+ const newChunks = [];
148507
+ const pollResult = await fetchAndParse(newChunks, cryptoKey, {
148508
+ cursor: serverCursorRef.current,
148509
+ skipFrames: frameCountRef.current
148510
+ });
148511
+ if (!pollResult.encrypted) {
148512
+ frameCountRef.current = pollResult.frameCount;
148513
+ if (pollResult.cursor) {
148514
+ serverCursorRef.current = pollResult.cursor;
148515
+ }
148516
+ if (newChunks.length > 0 && mounted) {
148517
+ setChunks((prev) => [...prev, ...newChunks]);
148518
+ }
148519
+ if (pollResult.done) {
148520
+ setIsLive(false);
149063
148521
  return;
149064
148522
  }
149065
- dataToHydrate = await decrypt(cryptoKey, payload);
149066
- } else {
149067
- dataToHydrate = frameData;
149068
- }
149069
- const hydrated = hydrateData(dataToHydrate, revivers);
149070
- if (mounted && hydrated !== void 0 && hydrated !== null) {
149071
- const chunkId = chunkIdRef.current++;
149072
- const text2 = typeof hydrated === "string" ? hydrated : JSON.stringify(hydrated, null, 2);
149073
- setChunks((prev) => [...prev, { id: chunkId, text: text2 }]);
149074
148523
  }
149075
148524
  } catch (err) {
149076
- console.error("Failed to process stream frame:", err);
148525
+ console.warn("Stream poll error:", err);
149077
148526
  }
149078
- }
148527
+ if (mounted && !abortController.signal.aborted) {
148528
+ pollTimerRef.current = setTimeout(poll, POLL_INTERVAL_MS);
148529
+ }
148530
+ };
148531
+ pollTimerRef.current = setTimeout(poll, POLL_INTERVAL_MS);
148532
+ } else {
148533
+ setIsLive(false);
149079
148534
  }
149080
148535
  } catch (err) {
149081
148536
  if (abortController.signal.aborted) return;
@@ -149088,11 +148543,20 @@ function useStreamReader(env2, streamId, runId, encryptionKey) {
149088
148543
  void readStreamData();
149089
148544
  return () => {
149090
148545
  mounted = false;
149091
- if (abortControllerRef.current) {
149092
- abortControllerRef.current.abort();
148546
+ abortController.abort();
148547
+ if (pollTimerRef.current) {
148548
+ clearTimeout(pollTimerRef.current);
148549
+ pollTimerRef.current = null;
149093
148550
  }
149094
148551
  };
149095
- }, [env2, streamId, runId, encryptionKey]);
148552
+ }, [env2, streamId, runId, encryptionKey, processFrame]);
148553
+ reactExports.useEffect(() => {
148554
+ if (!isRunActive(runStatus) && pollTimerRef.current) {
148555
+ clearTimeout(pollTimerRef.current);
148556
+ pollTimerRef.current = null;
148557
+ setIsLive(false);
148558
+ }
148559
+ }, [runStatus]);
149096
148560
  return { chunks, isLive, error: error2 };
149097
148561
  }
149098
148562
  const INITIAL_PAGE_SIZE = 100;
@@ -149229,900 +148693,9 @@ function LiveStatus({ hasError, errorMessage }) {
149229
148693
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: hasError ? `Error updating data: ${errorMessage}` : `Content updates every ${LIVE_UPDATE_INTERVAL_MS$1 / 1e3} seconds` }) })
149230
148694
  ] }) });
149231
148695
  }
149232
- function mapToStatusBadgeStatus(status) {
149233
- if (status === "retrying") return "running";
149234
- return status;
149235
- }
149236
- function ExecutionLoopNodeComponent({ data, selected: selected2 }) {
149237
- var _a3, _b, _c, _d;
149238
- const nodeData = data;
149239
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
149240
- "div",
149241
- {
149242
- className: `relative ${nodeData.className || ""}`,
149243
- style: {
149244
- borderWidth: ((_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.borderWidth) ?? 2,
149245
- borderRadius: 8,
149246
- padding: 12,
149247
- width: 220,
149248
- borderStyle: "solid",
149249
- backgroundColor: (_b = nodeData.nodeStyle) == null ? void 0 : _b.backgroundColor,
149250
- borderColor: ((_c = nodeData.nodeStyle) == null ? void 0 : _c.borderColor) ?? "#9ca3af",
149251
- opacity: (_d = nodeData.nodeStyle) == null ? void 0 : _d.opacity,
149252
- boxShadow: selected2 ? "0 0 0 2px rgba(168, 85, 247, 0.5)" : void 0
149253
- },
149254
- children: [
149255
- nodeData.label,
149256
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149257
- Handle,
149258
- {
149259
- type: "target",
149260
- position: Position.Top,
149261
- className: "!bg-purple-500"
149262
- }
149263
- ),
149264
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149265
- Handle,
149266
- {
149267
- type: "source",
149268
- position: Position.Bottom,
149269
- className: "!bg-purple-500"
149270
- }
149271
- ),
149272
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149273
- Handle,
149274
- {
149275
- type: "source",
149276
- position: Position.Left,
149277
- id: "loop-out",
149278
- className: "!bg-purple-500 !-left-1 !w-[6px] !h-[6px] !min-w-0 !min-h-0",
149279
- style: { top: "30%" }
149280
- }
149281
- ),
149282
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149283
- Handle,
149284
- {
149285
- type: "target",
149286
- position: Position.Left,
149287
- id: "loop-in",
149288
- className: "!bg-purple-500 !-left-1 !w-[6px] !h-[6px] !min-w-0 !min-h-0",
149289
- style: { top: "70%" }
149290
- }
149291
- )
149292
- ]
149293
- }
149294
- );
149295
- }
149296
- function ExecutionNodeComponent({ data, selected: selected2 }) {
149297
- var _a3, _b, _c, _d;
149298
- const nodeData = data;
149299
- const isStart = nodeData.nodeKind === "workflow_start";
149300
- const isEnd = nodeData.nodeKind === "workflow_end";
149301
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
149302
- "div",
149303
- {
149304
- className: `relative ${nodeData.className || ""}`,
149305
- style: {
149306
- borderWidth: ((_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.borderWidth) ?? 2,
149307
- borderRadius: 8,
149308
- padding: 12,
149309
- width: 220,
149310
- borderStyle: "solid",
149311
- backgroundColor: (_b = nodeData.nodeStyle) == null ? void 0 : _b.backgroundColor,
149312
- borderColor: ((_c = nodeData.nodeStyle) == null ? void 0 : _c.borderColor) ?? "#9ca3af",
149313
- opacity: (_d = nodeData.nodeStyle) == null ? void 0 : _d.opacity,
149314
- boxShadow: selected2 ? "0 0 0 2px rgba(59, 130, 246, 0.35)" : void 0
149315
- },
149316
- children: [
149317
- nodeData.label,
149318
- !isStart && /* @__PURE__ */ jsxRuntimeExports.jsx(Handle, { type: "target", position: Position.Top, className: "!bg-muted" }),
149319
- !isEnd && /* @__PURE__ */ jsxRuntimeExports.jsx(
149320
- Handle,
149321
- {
149322
- type: "source",
149323
- position: Position.Bottom,
149324
- className: "!bg-muted"
149325
- }
149326
- )
149327
- ]
149328
- }
149329
- );
149330
- }
149331
- function ExecutionDiamondNodeComponent({ data, selected: selected2 }) {
149332
- var _a3, _b, _c;
149333
- const nodeData = data;
149334
- const size2 = 160;
149335
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
149336
- "div",
149337
- {
149338
- className: `relative flex items-center justify-center ${nodeData.className || ""}`,
149339
- style: {
149340
- width: size2,
149341
- height: size2
149342
- },
149343
- children: [
149344
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149345
- "div",
149346
- {
149347
- style: {
149348
- width: size2 * 0.7,
149349
- height: size2 * 0.7,
149350
- transform: "rotate(45deg)",
149351
- borderWidth: 2,
149352
- borderStyle: "solid",
149353
- borderRadius: 4,
149354
- backgroundColor: (_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.backgroundColor,
149355
- borderColor: ((_b = nodeData.nodeStyle) == null ? void 0 : _b.borderColor) ?? "#ef4444",
149356
- opacity: (_c = nodeData.nodeStyle) == null ? void 0 : _c.opacity,
149357
- boxShadow: selected2 ? "0 0 0 2px rgba(239, 68, 68, 0.5)" : void 0
149358
- }
149359
- }
149360
- ),
149361
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149362
- "div",
149363
- {
149364
- className: "absolute inset-0 flex items-center justify-center pointer-events-auto",
149365
- style: {
149366
- fontSize: 11,
149367
- fontWeight: 600,
149368
- padding: size2 * 0.25
149369
- // Keep text within the diamond's inscribed area
149370
- },
149371
- title: typeof nodeData.label === "string" ? nodeData.label : void 0,
149372
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-center line-clamp-3 overflow-hidden", children: nodeData.label })
149373
- }
149374
- ),
149375
- /* @__PURE__ */ jsxRuntimeExports.jsx(Handle, { type: "target", position: Position.Top, className: "!bg-red-500" }),
149376
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149377
- Handle,
149378
- {
149379
- type: "source",
149380
- position: Position.Bottom,
149381
- id: "bottom",
149382
- className: "!bg-red-500"
149383
- }
149384
- ),
149385
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149386
- Handle,
149387
- {
149388
- type: "source",
149389
- position: Position.Left,
149390
- id: "left",
149391
- className: "!bg-red-500"
149392
- }
149393
- ),
149394
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149395
- Handle,
149396
- {
149397
- type: "source",
149398
- position: Position.Right,
149399
- id: "right",
149400
- className: "!bg-red-500"
149401
- }
149402
- )
149403
- ]
149404
- }
149405
- );
149406
- }
149407
- const nodeTypes = {
149408
- loopNode: ExecutionLoopNodeComponent,
149409
- parallelGroup: ParallelGroupComponent,
149410
- // Imported from shared
149411
- executionNode: ExecutionNodeComponent,
149412
- diamondNode: ExecutionDiamondNodeComponent
149413
- };
149414
- const edgeTypes = createEdgeTypes(executionSelfLoopStyle);
149415
- function getExecutionNodeStyle(nodeKind, executions) {
149416
- const backgroundColor = getNodeBackgroundColor(nodeKind);
149417
- if (!executions || executions.length === 0) {
149418
- return {
149419
- color: "hsl(var(--card-foreground))",
149420
- backgroundColor,
149421
- borderColor: "#9ca3af",
149422
- // gray-400
149423
- opacity: 0.4
149424
- };
149425
- }
149426
- const latestExecution = executions[executions.length - 1];
149427
- let borderColor = "#9ca3af";
149428
- let borderWidth = 2;
149429
- switch (latestExecution.status) {
149430
- case "completed":
149431
- borderColor = "#22c55e";
149432
- break;
149433
- case "failed":
149434
- borderColor = "#ef4444";
149435
- borderWidth = 3;
149436
- break;
149437
- case "running":
149438
- borderColor = "#3b82f6";
149439
- borderWidth = 2;
149440
- break;
149441
- case "retrying":
149442
- borderColor = "#f97316";
149443
- break;
149444
- case "cancelled":
149445
- borderColor = "#eab308";
149446
- break;
149447
- case "pending":
149448
- borderColor = "#9ca3af";
149449
- break;
149450
- }
149451
- return {
149452
- color: "hsl(var(--card-foreground))",
149453
- backgroundColor,
149454
- borderColor,
149455
- borderWidth
149456
- };
149457
- }
149458
- function renderNodeLabel(nodeData, _metadata, executions) {
149459
- const baseLabel = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 w-full overflow-hidden", children: [
149460
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", children: getNodeIcon(nodeData.nodeKind, nodeData.label) }),
149461
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium break-words whitespace-normal leading-tight flex-1 min-w-0", children: nodeData.label })
149462
- ] });
149463
- if (!executions || executions.length === 0) {
149464
- return baseLabel;
149465
- }
149466
- const latestExecution = executions[executions.length - 1];
149467
- const totalAttempts = executions.length;
149468
- const hasRetries = totalAttempts > 1;
149469
- const hasMetadata = hasRetries || latestExecution.duration && latestExecution.duration > 0;
149470
- if (!hasMetadata) return baseLabel;
149471
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
149472
- baseLabel,
149473
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-1 text-xs", children: [
149474
- hasRetries && /* @__PURE__ */ jsxRuntimeExports.jsxs(
149475
- Badge,
149476
- {
149477
- variant: "outline",
149478
- className: "text-xs px-1.5 py-0 border-orange-500 text-orange-700 dark:text-orange-300",
149479
- children: [
149480
- "↻ ",
149481
- totalAttempts,
149482
- "x"
149483
- ]
149484
- }
149485
- ),
149486
- latestExecution.duration && latestExecution.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
149487
- Badge,
149488
- {
149489
- variant: "secondary",
149490
- className: "text-xs px-1.5 py-0 bg-black/10 dark:bg-white/15 border-0",
149491
- children: [
149492
- "⏱ ",
149493
- formatDuration(latestExecution.duration, true)
149494
- ]
149495
- }
149496
- )
149497
- ] })
149498
- ] });
149499
- }
149500
- const EXECUTION_LAYOUT = {
148696
+ ({
149501
148697
  ...LAYOUT$1
149502
- };
149503
- function convertToReactFlowNodes(workflow, execution) {
149504
- var _a3, _b, _c;
149505
- const { nodes, groupNodes } = calculateEnhancedLayout(
149506
- workflow,
149507
- EXECUTION_LAYOUT
149508
- );
149509
- const nodeToParent = /* @__PURE__ */ new Map();
149510
- const groupPositions = /* @__PURE__ */ new Map();
149511
- for (const group of groupNodes) {
149512
- if (group.id.startsWith("group_")) {
149513
- groupPositions.set(group.id, group.position);
149514
- }
149515
- }
149516
- for (const node2 of nodes) {
149517
- const parallelGroupId = ((_a3 = node2.metadata) == null ? void 0 : _a3.parallelGroupId) ? `group_${node2.metadata.parallelGroupId}` : null;
149518
- if (parallelGroupId && groupPositions.has(parallelGroupId)) {
149519
- nodeToParent.set(node2.id, parallelGroupId);
149520
- }
149521
- }
149522
- const reactFlowNodes = [];
149523
- const parallelGroups = groupNodes.filter((g2) => g2.id.startsWith("group_"));
149524
- for (const group of parallelGroups) {
149525
- reactFlowNodes.push({
149526
- id: group.id,
149527
- type: "parallelGroup",
149528
- position: group.position,
149529
- style: {
149530
- ...group.style,
149531
- cursor: "grab",
149532
- zIndex: -1
149533
- },
149534
- data: group.data,
149535
- selectable: true,
149536
- draggable: true
149537
- });
149538
- }
149539
- for (const node2 of nodes) {
149540
- const executions = execution == null ? void 0 : execution.nodeExecutions.get(node2.id);
149541
- const styles2 = getExecutionNodeStyle(node2.data.nodeKind, executions);
149542
- const isCurrentNode = (execution == null ? void 0 : execution.currentNode) === node2.id;
149543
- const isLoopNode = !!((_b = node2.metadata) == null ? void 0 : _b.loopId);
149544
- const isAwaitLoop = !!((_c = node2.metadata) == null ? void 0 : _c.loopIsAwait);
149545
- const isConditionalNode = node2.data.nodeKind === "conditional";
149546
- const nodeType = isConditionalNode ? "diamondNode" : isLoopNode ? "loopNode" : "executionNode";
149547
- const parentId = nodeToParent.get(node2.id);
149548
- let position2 = node2.position;
149549
- if (parentId) {
149550
- const parentPos = groupPositions.get(parentId);
149551
- if (parentPos) {
149552
- position2 = {
149553
- x: node2.position.x - parentPos.x,
149554
- y: node2.position.y - parentPos.y
149555
- };
149556
- }
149557
- }
149558
- const nodeClassName = isCurrentNode ? "animate-pulse-subtle" : "";
149559
- if (isLoopNode) {
149560
- reactFlowNodes.push({
149561
- id: node2.id,
149562
- type: nodeType,
149563
- position: position2,
149564
- parentId,
149565
- extent: parentId ? "parent" : void 0,
149566
- expandParent: true,
149567
- data: {
149568
- ...node2.data,
149569
- label: renderNodeLabel(node2.data, node2.metadata, executions),
149570
- executions,
149571
- isLoopNode: true,
149572
- isAwaitLoop,
149573
- nodeStyle: styles2,
149574
- className: nodeClassName
149575
- }
149576
- });
149577
- } else if (isConditionalNode) {
149578
- reactFlowNodes.push({
149579
- id: node2.id,
149580
- type: nodeType,
149581
- position: position2,
149582
- parentId,
149583
- extent: parentId ? "parent" : void 0,
149584
- expandParent: true,
149585
- data: {
149586
- ...node2.data,
149587
- label: node2.data.label,
149588
- // Show the conditional expression
149589
- executions,
149590
- nodeStyle: styles2,
149591
- className: nodeClassName
149592
- }
149593
- });
149594
- } else {
149595
- reactFlowNodes.push({
149596
- id: node2.id,
149597
- type: nodeType,
149598
- position: position2,
149599
- parentId,
149600
- extent: parentId ? "parent" : void 0,
149601
- expandParent: true,
149602
- data: {
149603
- ...node2.data,
149604
- label: renderNodeLabel(node2.data, node2.metadata, executions),
149605
- executions,
149606
- nodeStyle: styles2,
149607
- className: nodeClassName
149608
- },
149609
- // Styling is handled by ExecutionNodeComponent (keeps running animation behind background)
149610
- style: { width: 220 }
149611
- });
149612
- }
149613
- }
149614
- return reactFlowNodes;
149615
- }
149616
- function convertToReactFlowEdges(workflow, execution) {
149617
- const { additionalEdges } = calculateEnhancedLayout(
149618
- workflow,
149619
- EXECUTION_LAYOUT
149620
- );
149621
- const transformedOriginalEdges = workflow.edges.map((e) => {
149622
- if (e.type === "loop") {
149623
- return {
149624
- ...e,
149625
- id: `loop_back_${e.source}_${e.target}`,
149626
- isOriginal: true
149627
- };
149628
- }
149629
- return { ...e, isOriginal: true };
149630
- });
149631
- const rawEdges = [
149632
- ...transformedOriginalEdges,
149633
- ...additionalEdges.map((e) => ({ ...e, isOriginal: false }))
149634
- ];
149635
- const allEdges = consolidateEdges(rawEdges, workflow.nodes);
149636
- return allEdges.map((edge) => {
149637
- if (edge.type === "selfLoop") {
149638
- return {
149639
- id: edge.id,
149640
- source: edge.source,
149641
- target: edge.target,
149642
- sourceHandle: edge.sourceHandle,
149643
- targetHandle: edge.targetHandle,
149644
- type: "selfLoop",
149645
- label: edge.label,
149646
- markerEnd: {
149647
- type: MarkerType.ArrowClosed,
149648
- width: 12,
149649
- height: 12,
149650
- color: "#a855f7"
149651
- }
149652
- };
149653
- }
149654
- let traversal = execution == null ? void 0 : execution.edgeTraversals.get(edge.id);
149655
- if (!traversal && edge.isConsolidated && edge.originalEdgeIds) {
149656
- for (const originalId of edge.originalEdgeIds) {
149657
- const originalTraversal = execution == null ? void 0 : execution.edgeTraversals.get(originalId);
149658
- if (originalTraversal && originalTraversal.traversalCount > 0) {
149659
- traversal = originalTraversal;
149660
- break;
149661
- }
149662
- }
149663
- }
149664
- const isTraversed = traversal && traversal.traversalCount > 0;
149665
- const hasExecution = !!execution;
149666
- const avgTiming = (traversal == null ? void 0 : traversal.timings.length) ? traversal.timings.reduce((a2, b2) => a2 + b2, 0) / traversal.timings.length : void 0;
149667
- let edgeType = "bezier";
149668
- let strokeDasharray;
149669
- let cfgLabel = edge.label;
149670
- let isConditional = false;
149671
- switch (edge.type) {
149672
- case "parallel":
149673
- edgeType = "smoothstep";
149674
- strokeDasharray = "4,4";
149675
- cfgLabel = void 0;
149676
- break;
149677
- case "loop":
149678
- edgeType = "step";
149679
- strokeDasharray = "8,4";
149680
- break;
149681
- case "conditional":
149682
- edgeType = "smoothstep";
149683
- strokeDasharray = "8,4";
149684
- isConditional = true;
149685
- break;
149686
- default:
149687
- edgeType = "bezier";
149688
- }
149689
- const baseStrokeColor = "#6b7280";
149690
- const finalStrokeColor = isTraversed ? "#22c55e" : baseStrokeColor;
149691
- const finalDasharray = isTraversed ? void 0 : strokeDasharray;
149692
- const opacity = hasExecution && !isTraversed ? 0.35 : 1;
149693
- const strokeWidth = isTraversed ? 2.5 : 1;
149694
- const labelTextColor = isConditional ? "#ffffff" : "#6b7280";
149695
- const labelBgColor = isConditional ? "#374151" : "#f3f4f6";
149696
- const labelBorderColor = isConditional ? "#4b5563" : "#d1d5db";
149697
- return {
149698
- id: edge.id,
149699
- source: edge.source,
149700
- target: edge.target,
149701
- type: edgeType,
149702
- animated: isTraversed && (execution == null ? void 0 : execution.status) === "running",
149703
- label: traversal && traversal.traversalCount > 1 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
149704
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "text-xs px-1.5 py-0", children: [
149705
- traversal.traversalCount,
149706
- "×"
149707
- ] }),
149708
- avgTiming && avgTiming > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
149709
- "~",
149710
- formatDuration(avgTiming, true)
149711
- ] })
149712
- ] }) : cfgLabel,
149713
- labelStyle: {
149714
- fill: labelTextColor,
149715
- fontWeight: 500,
149716
- fontSize: "11px"
149717
- },
149718
- labelBgStyle: {
149719
- fill: labelBgColor,
149720
- fillOpacity: 0.95,
149721
- stroke: labelBorderColor,
149722
- strokeWidth: 1
149723
- },
149724
- labelBgPadding: [4, 6],
149725
- labelBgBorderRadius: 4,
149726
- markerEnd: {
149727
- type: MarkerType.ArrowClosed,
149728
- width: isTraversed ? 14 : 10,
149729
- height: isTraversed ? 14 : 10,
149730
- color: finalStrokeColor
149731
- },
149732
- style: {
149733
- strokeWidth,
149734
- stroke: finalStrokeColor,
149735
- opacity,
149736
- strokeDasharray: finalDasharray
149737
- }
149738
- };
149739
- });
149740
- }
149741
- function GraphNodeDetailPanel({
149742
- selectedNode,
149743
- env: env2,
149744
- onClose
149745
- }) {
149746
- const { node: node2, executions, stepId, runId } = selectedNode;
149747
- const latestExecution = executions[executions.length - 1];
149748
- const hasMultipleAttempts = executions.length > 1;
149749
- const { data: stepData, loading: stepLoading } = useWorkflowResourceData(
149750
- env2 ?? {},
149751
- "step",
149752
- stepId ?? "",
149753
- { runId }
149754
- );
149755
- const resolvedInput = (stepData == null ? void 0 : stepData.input) ?? (latestExecution == null ? void 0 : latestExecution.input);
149756
- const resolvedOutput = (stepData == null ? void 0 : stepData.output) ?? (latestExecution == null ? void 0 : latestExecution.output);
149757
- const resolvedError = (stepData == null ? void 0 : stepData.error) ?? (latestExecution == null ? void 0 : latestExecution.error);
149758
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-background border-l", children: [
149759
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b flex-none", children: [
149760
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149761
- "span",
149762
- {
149763
- className: "text-xs font-medium truncate flex-1",
149764
- title: node2.data.label,
149765
- children: node2.data.label
149766
- }
149767
- ),
149768
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-none", children: [
149769
- (latestExecution == null ? void 0 : latestExecution.duration) !== void 0 && latestExecution.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted px-1.5 py-0.5 rounded", children: formatDuration(latestExecution.duration) }),
149770
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-border" }),
149771
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149772
- "button",
149773
- {
149774
- type: "button",
149775
- onClick: onClose,
149776
- className: "p-1 rounded hover:bg-muted transition-colors",
149777
- "aria-label": "Close panel",
149778
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$3, { className: "h-4 w-4 text-muted-foreground" })
149779
- }
149780
- )
149781
- ] })
149782
- ] }),
149783
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-3 min-h-0", children: [
149784
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col divide-y rounded-lg border overflow-hidden mb-3", children: [
149785
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149786
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "type" }),
149787
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: node2.data.nodeKind })
149788
- ] }),
149789
- latestExecution && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
149790
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149791
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "status" }),
149792
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149793
- StatusBadge,
149794
- {
149795
- status: mapToStatusBadgeStatus(latestExecution.status)
149796
- }
149797
- )
149798
- ] }),
149799
- latestExecution.duration !== void 0 && latestExecution.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149800
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "duration" }),
149801
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: formatDuration(latestExecution.duration) })
149802
- ] }),
149803
- hasMultipleAttempts && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149804
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "attempts" }),
149805
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: executions.length })
149806
- ] }),
149807
- latestExecution.startedAt && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149808
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "startedAt" }),
149809
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: new Date(latestExecution.startedAt).toLocaleString() })
149810
- ] }),
149811
- latestExecution.completedAt && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149812
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "completedAt" }),
149813
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: new Date(latestExecution.completedAt).toLocaleString() })
149814
- ] })
149815
- ] })
149816
- ] }),
149817
- stepLoading && stepId && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground mb-3", children: [
149818
- /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }),
149819
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Loading step data..." })
149820
- ] }),
149821
- resolvedInput !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", children: [
149822
- /* @__PURE__ */ jsxRuntimeExports.jsxs("summary", { className: "cursor-pointer rounded-md border px-2.5 py-1.5 text-xs hover:brightness-95 bg-muted/50", children: [
149823
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Input" }),
149824
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground ml-1", children: [
149825
- "(",
149826
- Array.isArray(resolvedInput) ? resolvedInput.length : 1,
149827
- " args)"
149828
- ] })
149829
- ] }),
149830
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149831
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149832
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149833
- /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-[11px] overflow-x-auto rounded-md border p-2.5 bg-muted/30 max-h-64 overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: JSON.stringify(resolvedInput, null, 2) }) })
149834
- ] })
149835
- ] }),
149836
- resolvedOutput !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", children: [
149837
- /* @__PURE__ */ jsxRuntimeExports.jsx("summary", { className: "cursor-pointer rounded-md border px-2.5 py-1.5 text-xs hover:brightness-95 bg-muted/50", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Output" }) }),
149838
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149839
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149840
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149841
- /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-[11px] overflow-x-auto rounded-md border p-2.5 bg-muted/30 max-h-64 overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: JSON.stringify(resolvedOutput, null, 2) }) })
149842
- ] })
149843
- ] }),
149844
- resolvedError && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", open: true, children: [
149845
- /* @__PURE__ */ jsxRuntimeExports.jsx("summary", { className: "cursor-pointer rounded-md border border-red-300 bg-red-50 dark:bg-red-950/20 px-2.5 py-1.5 text-xs hover:brightness-95", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-red-600 dark:text-red-400", children: "Error" }) }),
149846
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149847
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-red-300" }),
149848
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-red-300" }),
149849
- /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-[11px] overflow-x-auto rounded-md border border-red-200 p-2.5 bg-red-50 dark:bg-red-950/20 text-red-700 dark:text-red-300 whitespace-pre-wrap max-h-64 overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: typeof resolvedError === "object" ? JSON.stringify(resolvedError, null, 2) : String(resolvedError) }) })
149850
- ] })
149851
- ] }),
149852
- hasMultipleAttempts && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group", children: [
149853
- /* @__PURE__ */ jsxRuntimeExports.jsxs("summary", { className: "cursor-pointer rounded-md border px-2.5 py-1.5 text-xs hover:brightness-95 bg-muted/50", children: [
149854
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Attempt History" }),
149855
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground ml-1", children: [
149856
- "(",
149857
- executions.length,
149858
- " attempts)"
149859
- ] })
149860
- ] }),
149861
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149862
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149863
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149864
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col divide-y rounded-md border overflow-hidden", children: executions.map((exec) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
149865
- "div",
149866
- {
149867
- className: "flex items-center justify-between px-2.5 py-1.5 text-[11px]",
149868
- children: [
149869
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
149870
- "Attempt ",
149871
- exec.attemptNumber
149872
- ] }),
149873
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149874
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149875
- StatusBadge,
149876
- {
149877
- status: mapToStatusBadgeStatus(exec.status)
149878
- }
149879
- ),
149880
- exec.duration !== void 0 && exec.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatDuration(exec.duration) })
149881
- ] })
149882
- ]
149883
- },
149884
- exec.attemptNumber
149885
- )) })
149886
- ] })
149887
- ] })
149888
- ] })
149889
- ] });
149890
- }
149891
- function WorkflowGraphExecutionViewer({
149892
- workflow,
149893
- execution,
149894
- env: env2,
149895
- onNodeClick
149896
- }) {
149897
- const [selectedNode, setSelectedNode] = reactExports.useState(
149898
- null
149899
- );
149900
- const panelWidth = 320;
149901
- const initialNodes = reactExports.useMemo(
149902
- () => convertToReactFlowNodes(workflow, execution),
149903
- [workflow, execution]
149904
- );
149905
- const initialEdges = reactExports.useMemo(
149906
- () => convertToReactFlowEdges(workflow, execution),
149907
- [workflow, execution]
149908
- );
149909
- const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
149910
- const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
149911
- reactExports.useEffect(() => {
149912
- setNodes((currentNodes) => {
149913
- const newNodes = convertToReactFlowNodes(workflow, execution);
149914
- const currentPositions = new Map(
149915
- currentNodes.map((n) => [n.id, n.position])
149916
- );
149917
- return newNodes.map((node2) => ({
149918
- ...node2,
149919
- position: currentPositions.get(node2.id) ?? node2.position
149920
- }));
149921
- });
149922
- setEdges(convertToReactFlowEdges(workflow, execution));
149923
- }, [workflow, execution, setNodes, setEdges]);
149924
- const handleNodeClick2 = reactExports.useCallback(
149925
- (_event, node2) => {
149926
- const graphNode = workflow.nodes.find((n) => n.id === node2.id);
149927
- if (graphNode) {
149928
- const executions = node2.data.executions || [];
149929
- const latestExecution = executions[executions.length - 1];
149930
- setSelectedNode({
149931
- nodeId: node2.id,
149932
- node: graphNode,
149933
- executions,
149934
- stepId: latestExecution == null ? void 0 : latestExecution.stepId,
149935
- runId: execution == null ? void 0 : execution.runId
149936
- });
149937
- if (onNodeClick && executions.length > 0) {
149938
- onNodeClick(node2.id, executions);
149939
- }
149940
- }
149941
- },
149942
- [workflow.nodes, execution == null ? void 0 : execution.runId, onNodeClick]
149943
- );
149944
- const handleClosePanel = reactExports.useCallback(() => {
149945
- setSelectedNode(null);
149946
- }, []);
149947
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full w-full border rounded-lg bg-background relative overflow-hidden flex", children: [
149948
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149949
- "div",
149950
- {
149951
- className: "h-full flex-1 min-w-0",
149952
- style: {
149953
- width: selectedNode ? `calc(100% - ${panelWidth}px)` : "100%"
149954
- },
149955
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
149956
- index,
149957
- {
149958
- nodes,
149959
- edges,
149960
- onNodesChange,
149961
- onEdgesChange,
149962
- onNodeClick: handleNodeClick2,
149963
- nodeTypes,
149964
- edgeTypes,
149965
- fitView: true,
149966
- minZoom: 0.1,
149967
- maxZoom: 2,
149968
- defaultViewport: { x: 0, y: 0, zoom: 1 },
149969
- proOptions: { hideAttribution: true },
149970
- children: [
149971
- /* @__PURE__ */ jsxRuntimeExports.jsx(Background, {}),
149972
- /* @__PURE__ */ jsxRuntimeExports.jsx(Controls, {}),
149973
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149974
- Panel,
149975
- {
149976
- position: "top-left",
149977
- className: "bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-lg p-2 text-xs",
149978
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
149979
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-[10px] text-muted-foreground mb-1", children: "Status" }),
149980
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149981
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-green-500 bg-background" }),
149982
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Completed" })
149983
- ] }),
149984
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149985
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-red-500 bg-background" }),
149986
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Failed" })
149987
- ] }),
149988
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149989
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-blue-500 bg-background" }),
149990
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Running" })
149991
- ] }),
149992
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149993
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-yellow-500 bg-background" }),
149994
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Cancelled" })
149995
- ] }),
149996
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 opacity-50", children: [
149997
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-gray-400 bg-background" }),
149998
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Pending" })
149999
- ] })
150000
- ] })
150001
- }
150002
- ),
150003
- execution && /* @__PURE__ */ jsxRuntimeExports.jsxs(
150004
- Panel,
150005
- {
150006
- position: "top-right",
150007
- className: "bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-lg p-3 text-xs space-y-1.5",
150008
- children: [
150009
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-sm", children: "Execution" }),
150010
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
150011
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "Status:" }),
150012
- /* @__PURE__ */ jsxRuntimeExports.jsx(
150013
- Badge,
150014
- {
150015
- variant: execution.status === "completed" ? "default" : execution.status === "failed" ? "destructive" : execution.status === "cancelled" ? "outline" : "secondary",
150016
- className: "text-xs",
150017
- children: execution.status
150018
- }
150019
- )
150020
- ] }),
150021
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
150022
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "Progress:" }),
150023
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", children: [
150024
- execution.executionPath.length,
150025
- " / ",
150026
- workflow.nodes.length
150027
- ] })
150028
- ] })
150029
- ]
150030
- }
150031
- )
150032
- ]
150033
- }
150034
- )
150035
- }
150036
- ),
150037
- selectedNode && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full flex-none", style: { width: panelWidth }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
150038
- GraphNodeDetailPanel,
150039
- {
150040
- selectedNode,
150041
- env: env2,
150042
- onClose: handleClosePanel
150043
- }
150044
- ) })
150045
- ] });
150046
- }
150047
- function GraphTabContent({
150048
- run,
150049
- allEvents,
150050
- env: env2
150051
- }) {
150052
- const {
150053
- manifest: graphManifest,
150054
- loading: graphLoading,
150055
- error: graphError
150056
- } = useWorkflowGraphManifest();
150057
- const workflowGraph = reactExports.useMemo(() => {
150058
- var _a3;
150059
- if (!graphManifest || !run.workflowName) return null;
150060
- const runWorkflowName = String(run.workflowName).trim();
150061
- const direct = graphManifest.workflows[runWorkflowName];
150062
- if (direct) return direct;
150063
- const runShortName = (_a3 = parseWorkflowName(runWorkflowName)) == null ? void 0 : _a3.shortName;
150064
- const workflows = Object.values(graphManifest.workflows);
150065
- return workflows.find((wf) => {
150066
- var _a4;
150067
- if (wf.workflowId === runWorkflowName) return true;
150068
- if (wf.workflowName === runWorkflowName) return true;
150069
- if (!runShortName) return false;
150070
- return ((_a4 = parseWorkflowName(wf.workflowName)) == null ? void 0 : _a4.shortName) === runShortName;
150071
- }) ?? null;
150072
- }, [graphManifest, run.workflowName]);
150073
- const stepsFromEvents = reactExports.useMemo(() => {
150074
- if (!allEvents) return [];
150075
- const stepEventsMap = /* @__PURE__ */ new Map();
150076
- for (const event of allEvents) {
150077
- if (event.eventType.startsWith("step_") && event.correlationId) {
150078
- const existing = stepEventsMap.get(event.correlationId);
150079
- if (existing) {
150080
- existing.push(event);
150081
- } else {
150082
- stepEventsMap.set(event.correlationId, [event]);
150083
- }
150084
- }
150085
- }
150086
- return Array.from(stepEventsMap.values()).map(stepEventsToStepEntity).filter((s2) => s2 !== null);
150087
- }, [allEvents]);
150088
- const execution = reactExports.useMemo(() => {
150089
- if (!workflowGraph || !run.runId) return null;
150090
- return mapRunToExecution(
150091
- run,
150092
- stepsFromEvents,
150093
- allEvents || [],
150094
- workflowGraph
150095
- );
150096
- }, [workflowGraph, run, stepsFromEvents, allEvents]);
150097
- if (graphLoading) {
150098
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center w-full h-full", children: [
150099
- /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-8 w-8 animate-spin text-muted-foreground" }),
150100
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-4 text-muted-foreground", children: "Loading workflow graph..." })
150101
- ] });
150102
- }
150103
- if (graphError) {
150104
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center w-full h-full p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", className: "max-w-lg", children: [
150105
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
150106
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Error Loading Workflow Graph" }),
150107
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: graphError.message })
150108
- ] }) });
150109
- }
150110
- if (!workflowGraph) {
150111
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center w-full h-full", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { className: "max-w-lg", children: [
150112
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
150113
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Workflow Graph Not Found" }),
150114
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: "Could not find the workflow graph for this run. The workflow may have been deleted or the graph manifest may need to be regenerated." })
150115
- ] }) });
150116
- }
150117
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
150118
- WorkflowGraphExecutionViewer,
150119
- {
150120
- workflow: workflowGraph,
150121
- execution: execution || void 0,
150122
- env: env2
150123
- }
150124
- );
150125
- }
148698
+ });
150126
148699
  function RunDetailView({
150127
148700
  runId,
150128
148701
  // TODO: This should open the right sidebar within the trace viewer
@@ -150137,7 +148710,8 @@ function RunDetailView({
150137
148710
  const [showCancelDialog, setShowCancelDialog] = reactExports.useState(false);
150138
148711
  const [showRerunDialog, setShowRerunDialog] = reactExports.useState(false);
150139
148712
  const env2 = reactExports.useMemo(() => ({}), []);
150140
- const activeTab = searchParams.get("tab") || "trace";
148713
+ const rawTab = searchParams.get("tab") || "trace";
148714
+ const activeTab = rawTab === "graph" ? "trace" : rawTab;
150141
148715
  const selectedStreamId = searchParams.get("streamId");
150142
148716
  const updateSearchParams = reactExports.useCallback(
150143
148717
  (updates) => {
@@ -150155,7 +148729,7 @@ function RunDetailView({
150155
148729
  );
150156
148730
  const setActiveTab = reactExports.useCallback(
150157
148731
  (tab2) => {
150158
- if (tab2 === "trace" || tab2 === "graph") {
148732
+ if (tab2 !== "streams") {
150159
148733
  updateSearchParams({ tab: tab2, streamId: null });
150160
148734
  } else {
150161
148735
  updateSearchParams({ tab: tab2 });
@@ -150220,7 +148794,7 @@ function RunDetailView({
150220
148794
  },
150221
148795
  [env2, runId]
150222
148796
  );
150223
- const isLocalBackend = serverConfig.backendId === "local" || serverConfig.backendId === "@workflow/world-local";
148797
+ serverConfig.backendId === "local" || serverConfig.backendId === "@workflow/world-local";
150224
148798
  const {
150225
148799
  run: runData,
150226
148800
  events: allEvents,
@@ -150301,7 +148875,7 @@ function RunDetailView({
150301
148875
  chunks: streamChunks,
150302
148876
  isLive: streamIsLive,
150303
148877
  error: streamError
150304
- } = useStreamReader(env2, selectedStreamId, runId, encryptionKey);
148878
+ } = useStreamReader(env2, selectedStreamId, runId, encryptionKey, run.status);
150305
148879
  const handleCancelClick = () => {
150306
148880
  setShowCancelDialog(true);
150307
148881
  };
@@ -150473,10 +149047,7 @@ function RunDetailView({
150473
149047
  /* @__PURE__ */ jsxRuntimeExports.jsx(List$1, { className: "h-4 w-4" }),
150474
149048
  "Trace"
150475
149049
  ] }),
150476
- isLocalBackend && /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "graph", className: "gap-2", children: [
150477
- /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "h-4 w-4" }),
150478
- "Graph"
150479
- ] }),
149050
+ false,
150480
149051
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "events", className: "gap-2", children: [
150481
149052
  /* @__PURE__ */ jsxRuntimeExports.jsx(List$1, { className: "h-4 w-4" }),
150482
149053
  "Events"
@@ -150636,14 +149207,7 @@ function RunDetailView({
150636
149207
  }
150637
149208
  ) })
150638
149209
  ] }) }) }),
150639
- isLocalBackend && /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "graph", className: "mt-0 flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { title: "Failed to load execution graph", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full min-h-[500px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
150640
- GraphTabContent,
150641
- {
150642
- run,
150643
- allEvents,
150644
- env: env2
150645
- }
150646
- ) }) }) })
149210
+ false
150647
149211
  ]
150648
149212
  }
150649
149213
  ) })
@@ -150783,27 +149347,32 @@ async function loader({
150783
149347
  });
150784
149348
  }
150785
149349
  const url2 = new URL(request2.url);
150786
- const startIndexParam = url2.searchParams.get("startIndex");
150787
- const startIndex = startIndexParam != null ? Number.parseInt(startIndexParam, 10) : void 0;
150788
- if (startIndex !== void 0 && Number.isNaN(startIndex)) {
149350
+ const runId = url2.searchParams.get("runId");
149351
+ if (!runId) {
150789
149352
  return Response.json({
150790
- message: "Invalid startIndex parameter",
149353
+ message: "Missing runId parameter",
150791
149354
  layer: "server"
150792
149355
  }, {
150793
149356
  status: 400
150794
149357
  });
150795
149358
  }
149359
+ const cursor = url2.searchParams.get("cursor") ?? void 0;
150796
149360
  try {
150797
- const stream = await readStreamServerAction({}, streamId, startIndex);
150798
- if (!stream || !(stream instanceof ReadableStream)) {
150799
- return Response.json(stream, {
149361
+ const result = await readStreamChunksServerAction({}, streamId, runId, cursor);
149362
+ if (!("buffer" in result)) {
149363
+ return Response.json(result, {
150800
149364
  status: 500
150801
149365
  });
150802
149366
  }
150803
- return new Response(stream, {
150804
- headers: {
150805
- "Content-Type": "application/octet-stream"
150806
- }
149367
+ const headers2 = {
149368
+ "Content-Type": "application/octet-stream",
149369
+ "X-Stream-Done": String(result.done)
149370
+ };
149371
+ if (result.cursor) {
149372
+ headers2["X-Stream-Cursor"] = result.cursor;
149373
+ }
149374
+ return new Response(result.buffer, {
149375
+ headers: headers2
150807
149376
  });
150808
149377
  } catch (error2) {
150809
149378
  const message2 = error2 instanceof Error ? error2.message : String(error2);
@@ -150819,7 +149388,7 @@ const route4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
150819
149388
  __proto__: null,
150820
149389
  loader
150821
149390
  }, Symbol.toStringTag, { value: "Module" }));
150822
- const serverManifest = { "entry": { "module": "/assets/entry.client-BjpmGyLC.js", "imports": ["/assets/index-DklpUtP3.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/root-DXnpwJxc.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/mermaid-3ZIDBTTL-CrmlsXj3.js"], "css": ["/assets/root-DtrAdcW8.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/home": { "id": "routes/home", "parentId": "root", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/home-CFxVErsy.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/use-workflow-graph-DGcT3V07.js", "/assets/mermaid-3ZIDBTTL-CrmlsXj3.js"], "css": ["/assets/use-workflow-graph-yls6qlc0.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/run-detail": { "id": "routes/run-detail", "parentId": "root", "path": "run/:runId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/run-detail-C6LG6p9l.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/use-workflow-graph-DGcT3V07.js", "/assets/mermaid-3ZIDBTTL-CrmlsXj3.js", "/assets/encryption-8OvC6eoJ.js"], "css": ["/assets/use-workflow-graph-yls6qlc0.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.rpc": { "id": "routes/api.rpc", "parentId": "root", "path": "api/rpc", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.rpc-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.stream.$streamId": { "id": "routes/api.stream.$streamId", "parentId": "root", "path": "api/stream/:streamId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.stream._streamId-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 } }, "url": "/assets/manifest-beaac576.js", "version": "beaac576", "sri": void 0 };
149391
+ const serverManifest = { "entry": { "module": "/assets/entry.client-BjpmGyLC.js", "imports": ["/assets/index-DklpUtP3.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/root-Dae_xV-y.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/mermaid-3ZIDBTTL-D95wSBpg.js"], "css": ["/assets/root-DtrAdcW8.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/home": { "id": "routes/home", "parentId": "root", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/home-ClC-EMyL.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/workflow-graph-viewer-BZlGoIt2.js", "/assets/mermaid-3ZIDBTTL-D95wSBpg.js"], "css": ["/assets/workflow-graph-viewer-yls6qlc0.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/run-detail": { "id": "routes/run-detail", "parentId": "root", "path": "run/:runId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/run-detail-Brs1Rm25.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/workflow-graph-viewer-BZlGoIt2.js", "/assets/mermaid-3ZIDBTTL-D95wSBpg.js", "/assets/encryption-8OvC6eoJ.js"], "css": ["/assets/workflow-graph-viewer-yls6qlc0.css", "/assets/mermaid-3ZIDBTTL-DKxHcEOp.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.rpc": { "id": "routes/api.rpc", "parentId": "root", "path": "api/rpc", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.rpc-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.stream.$streamId": { "id": "routes/api.stream.$streamId", "parentId": "root", "path": "api/stream/:streamId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.stream._streamId-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 } }, "url": "/assets/manifest-7a6ad03e.js", "version": "7a6ad03e", "sri": void 0 };
150823
149392
  const assetsBuildDirectory = "build/client";
150824
149393
  const basename = "/";
150825
149394
  const future = { "unstable_optimizeDeps": false, "unstable_subResourceIntegrity": false, "unstable_trailingSlashAwareDataRequests": false, "unstable_previewServerPrerendering": false, "v8_middleware": false, "v8_splitRouteModules": false, "v8_viteEnvironmentApi": false };