@workflow/web 4.1.0-beta.43 → 4.1.0-beta.45

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 (23) hide show
  1. package/build/client/assets/{highlighted-body-B3W2YXNL-BdpKyd6t.js → highlighted-body-B3W2YXNL-DmGJDYCd.js} +1 -1
  2. package/build/client/assets/home-Bg63MGns.js +40 -0
  3. package/build/client/assets/manifest-f52831b8.js +1 -0
  4. package/build/client/assets/{mermaid-3ZIDBTTL-D6v4WgFl.js → mermaid-3ZIDBTTL-ClWSYlBT.js} +63 -63
  5. package/build/client/assets/{root-CxkGJJO9.js → root-CADywoAy.js} +1 -1
  6. package/build/client/assets/{root-DUJPWGN3.css → root-DtrAdcW8.css} +1 -1
  7. package/build/client/assets/run-detail-CX8hD4AT.js +37 -0
  8. package/build/client/assets/{server-build-BFalDDpv.css → server-build-8B6V768r.css} +1 -1
  9. package/build/client/assets/workflow-graph-viewer-RUyTSlHH.js +161 -0
  10. package/build/server/assets/{app-KW-1KXCl.js → app-DMT28sgS.js} +1 -1
  11. package/build/server/assets/{highlighted-body-B3W2YXNL-DapKdL2n.js → highlighted-body-B3W2YXNL-CKl1xXgz.js} +2 -2
  12. package/build/server/assets/{index-93Io7SSr.js → index-BHIV6JOr.js} +2 -2
  13. package/build/server/assets/{mermaid-3ZIDBTTL-BdsOvyTU.js → mermaid-3ZIDBTTL-uTah_BkY.js} +2 -2
  14. package/build/server/assets/{server-build-D9d_jMLb.js → server-build-DiN0zpXF.js} +930 -1927
  15. package/build/server/assets/{token-Bf2BqxEG.js → token-fvUEOQRa.js} +2 -2
  16. package/build/server/assets/{token-util-C8FlMBAQ.js → token-util-1mDJoKQG.js} +2 -2
  17. package/build/server/index.js +1 -1
  18. package/package.json +6 -6
  19. package/build/client/assets/home-C884R8Ik.js +0 -35
  20. package/build/client/assets/manifest-14123a0c.js +0 -1
  21. package/build/client/assets/run-detail-D_eXHYm3.js +0 -36
  22. package/build/client/assets/use-workflow-graph-WEp5s5k_.js +0 -166
  23. /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-KW-1KXCl.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-DMT28sgS.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";
@@ -24,7 +24,7 @@ import minproc from "node:process";
24
24
  import path$3, { join as join$1, resolve, dirname, isAbsolute, sep as sep$1 } from "node:path";
25
25
  import { fileURLToPath } from "node:url";
26
26
  import { createRequire } from "module";
27
- import require$$0$8, { readdir, readlink, readFile, mkdir, access, constants as constants$5, writeFile, unlink, rm } from "node:fs/promises";
27
+ import fs$1, { readdir, readlink, readFile, mkdir, access, constants as constants$5, writeFile, unlink, rm } from "node:fs/promises";
28
28
  import crypto, { createHash, webcrypto } from "node:crypto";
29
29
  import require$$1$1 from "tty";
30
30
  import require$$0$1 from "os";
@@ -30646,9 +30646,13 @@ function formatDuration(ms2, compact = false) {
30646
30646
  }
30647
30647
  if (compact) {
30648
30648
  if (ms2 < MS_IN_HOUR) {
30649
- return `${durationFormatter.format(ms2 / MS_IN_MINUTE)}m`;
30649
+ const m3 = Math.floor(ms2 / MS_IN_MINUTE);
30650
+ const s2 = Math.floor(ms2 % MS_IN_MINUTE / MS_IN_SECOND);
30651
+ return s2 > 0 ? `${m3}m ${s2}s` : `${m3}m`;
30650
30652
  }
30651
- return `${durationFormatter.format(ms2 / MS_IN_HOUR)}h`;
30653
+ const h2 = Math.floor(ms2 / MS_IN_HOUR);
30654
+ const m2 = Math.floor(ms2 % MS_IN_HOUR / MS_IN_MINUTE);
30655
+ return m2 > 0 ? `${h2}h ${m2}m` : `${h2}h`;
30652
30656
  }
30653
30657
  const days = Math.floor(ms2 / MS_IN_DAY);
30654
30658
  const hours = Math.floor(ms2 % MS_IN_DAY / MS_IN_HOUR);
@@ -34545,6 +34549,21 @@ function decodeFormatPrefix$1(data) {
34545
34549
  const payload = data.subarray(FORMAT_PREFIX_LENGTH$1);
34546
34550
  return { format: format2, payload };
34547
34551
  }
34552
+ function isExpiredObject(data) {
34553
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
34554
+ return false;
34555
+ }
34556
+ const keys2 = Object.keys(data);
34557
+ return keys2.length === 1 && keys2[0] === "expiredAt" && typeof data.expiredAt === "string";
34558
+ }
34559
+ function isExpiredStub(data) {
34560
+ if (isExpiredObject(data))
34561
+ return true;
34562
+ if (Array.isArray(data) && data.length === 1 && isExpiredObject(data[0])) {
34563
+ return true;
34564
+ }
34565
+ return false;
34566
+ }
34548
34567
  function isEncryptedData(data) {
34549
34568
  if (!(data instanceof Uint8Array) || data.length < FORMAT_PREFIX_LENGTH$1) {
34550
34569
  return false;
@@ -34759,6 +34778,7 @@ const serializationFormat = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object
34759
34778
  hydrateDataWithKey,
34760
34779
  hydrateResourceIO: hydrateResourceIO$1,
34761
34780
  isEncryptedData,
34781
+ isExpiredStub,
34762
34782
  observabilityRevivers,
34763
34783
  serializedClassToString,
34764
34784
  serializedInstanceToRef,
@@ -34836,7 +34856,7 @@ function getRevivers() {
34836
34856
  }
34837
34857
  function hydrateResourceIO(resource) {
34838
34858
  const hydrated = hydrateResourceIO$1(resource, getRevivers());
34839
- return replaceEncryptedWithMarkers(hydrated);
34859
+ return replaceEncryptedAndExpiredWithMarkers(hydrated);
34840
34860
  }
34841
34861
  const ENCRYPTED_DISPLAY_NAME = "Encrypted";
34842
34862
  function createEncryptedMarker(data) {
@@ -34854,22 +34874,35 @@ function isEncryptedMarker(value) {
34854
34874
  var _a3;
34855
34875
  return value !== null && typeof value === "object" && ((_a3 = value.constructor) == null ? void 0 : _a3.name) === ENCRYPTED_DISPLAY_NAME;
34856
34876
  }
34857
- function replaceEncryptedWithMarkers(resource) {
34877
+ const EXPIRED_DISPLAY_NAME = "Expired Data";
34878
+ function createExpiredMarker() {
34879
+ const ctor = { [EXPIRED_DISPLAY_NAME]: function() {
34880
+ } }[EXPIRED_DISPLAY_NAME];
34881
+ return Object.create(ctor.prototype);
34882
+ }
34883
+ function isExpiredMarker(value) {
34884
+ var _a3;
34885
+ return value !== null && typeof value === "object" && ((_a3 = value.constructor) == null ? void 0 : _a3.name) === EXPIRED_DISPLAY_NAME;
34886
+ }
34887
+ function toDisplayMarker(value) {
34888
+ if (isEncryptedData(value))
34889
+ return createEncryptedMarker(value);
34890
+ if (isExpiredStub(value))
34891
+ return createExpiredMarker();
34892
+ return value;
34893
+ }
34894
+ function replaceEncryptedAndExpiredWithMarkers(resource) {
34858
34895
  if (!resource || typeof resource !== "object")
34859
34896
  return resource;
34860
34897
  const r2 = resource;
34861
34898
  const result = { ...r2 };
34862
34899
  for (const key of ["input", "output", "metadata", "error"]) {
34863
- if (isEncryptedData(result[key])) {
34864
- result[key] = createEncryptedMarker(result[key]);
34865
- }
34900
+ result[key] = toDisplayMarker(result[key]);
34866
34901
  }
34867
34902
  if (result.eventData && typeof result.eventData === "object") {
34868
34903
  const ed = { ...result.eventData };
34869
34904
  for (const key of EVENT_DATA_SERIALIZED_FIELDS) {
34870
- if (isEncryptedData(ed[key])) {
34871
- ed[key] = createEncryptedMarker(ed[key]);
34872
- }
34905
+ ed[key] = toDisplayMarker(ed[key]);
34873
34906
  }
34874
34907
  result.eventData = ed;
34875
34908
  }
@@ -64866,7 +64899,7 @@ var tn = f("block", "before:content-[counter(line)]", "before:inline-block", "be
64866
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 });
64867
64900
  var Se = reactExports.createContext({ code: "" }), de$1 = () => reactExports.useContext(Se);
64868
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 }) });
64869
- var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-DapKdL2n.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-CKl1xXgz.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
64870
64903
  let i = reactExports.useMemo(() => e.replace(cn$1, ""), [e]), c = reactExports.useMemo(() => ({ bg: "transparent", fg: "inherit", tokens: i.split(`
64871
64904
  `).map((a2) => [{ content: a2, color: "inherit", bgColor: "transparent", htmlStyle: {}, offset: 0 }]) }), [i]);
64872
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 }) })] }) });
@@ -65188,7 +65221,7 @@ var Dt = ({ children: e, className: t, onDownload: o, onError: n }) => {
65188
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] });
65189
65222
  };
65190
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 }) })] });
65191
- var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-BdsOvyTU.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
65224
+ var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-uTah_BkY.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
65192
65225
  function ke(e, t) {
65193
65226
  if (!(e != null && e.position || t != null && t.position)) return true;
65194
65227
  if (!(e != null && e.position && (t != null && t.position))) return false;
@@ -65823,6 +65856,13 @@ function EncryptedFieldBlock() {
65823
65856
  color: "var(--ds-gray-700)"
65824
65857
  }, children: [jsxRuntimeExports.jsx(Lock, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Encrypted" })] });
65825
65858
  }
65859
+ function ExpiredFieldBlock() {
65860
+ return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
65861
+ borderColor: "var(--ds-gray-300)",
65862
+ backgroundColor: "var(--ds-gray-100)",
65863
+ color: "var(--ds-gray-700)"
65864
+ }, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
65865
+ }
65826
65866
  function JsonBlock(value) {
65827
65867
  return jsxRuntimeExports.jsx(CopyableDataBlock, { data: value });
65828
65868
  }
@@ -65990,11 +66030,15 @@ const attributeToDisplayFn = {
65990
66030
  return null;
65991
66031
  if (isEncryptedMarker(value))
65992
66032
  return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
66033
+ if (isExpiredMarker(value))
66034
+ return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
65993
66035
  return JsonBlock(value);
65994
66036
  },
65995
66037
  input: (value, context) => {
65996
66038
  if (isEncryptedMarker(value))
65997
66039
  return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
66040
+ if (isExpiredMarker(value))
66041
+ return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
65998
66042
  if (value && typeof value === "object" && "args" in value) {
65999
66043
  const { args, closureVars, thisVal } = value;
66000
66044
  const argCount2 = Array.isArray(args) ? args.length : 0;
@@ -66025,11 +66069,15 @@ const attributeToDisplayFn = {
66025
66069
  return null;
66026
66070
  if (isEncryptedMarker(value))
66027
66071
  return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
66072
+ if (isExpiredMarker(value))
66073
+ return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
66028
66074
  return jsxRuntimeExports.jsx(DetailCard, { summary: "Output", summaryClassName: "text-base py-2", contentClassName: "mt-0", children: JsonBlock(value) });
66029
66075
  },
66030
66076
  error: (value) => {
66031
66077
  if (isEncryptedMarker(value))
66032
66078
  return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
66079
+ if (isExpiredMarker(value))
66080
+ return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
66033
66081
  if (!hasDisplayContent(value))
66034
66082
  return null;
66035
66083
  if (isStructuredErrorWithStack(value)) {
@@ -66040,6 +66088,8 @@ const attributeToDisplayFn = {
66040
66088
  eventData: (value) => {
66041
66089
  if (isEncryptedMarker(value))
66042
66090
  return jsxRuntimeExports.jsx(EncryptedFieldBlock, {});
66091
+ if (isExpiredMarker(value))
66092
+ return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
66043
66093
  if (!hasDisplayContent(value))
66044
66094
  return null;
66045
66095
  return jsxRuntimeExports.jsx(DetailCard, { summary: "Event Data", children: JsonBlock(value) });
@@ -66059,7 +66109,7 @@ const ExpiredDataMessage = () => jsxRuntimeExports.jsx("div", { className: "text
66059
66109
  }, children: jsxRuntimeExports.jsx("span", { children: "The data for this run has expired and is no longer available." }) });
66060
66110
  const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
66061
66111
  const isExpandableLoadingTarget = attribute === "input" || attribute === "output" || attribute === "eventData";
66062
- if (isLoading && isExpandableLoadingTarget) {
66112
+ if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
66063
66113
  return jsxRuntimeExports.jsxs("div", { className: `my-2 flex flex-col ${attribute === "input" || attribute === "output" ? "gap-2 my-3.5" : "gap-0"}`, children: [jsxRuntimeExports.jsx("span", { className: `${attribute === "input" || attribute === "output" ? "text-base" : "text-xs"} font-medium first-letter:uppercase`, style: { color: "var(--ds-gray-700)" }, children: attribute }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-9 w-full rounded-md" })] });
66064
66114
  }
66065
66115
  const displayFn = attributeToDisplayFn[attribute];
@@ -66220,7 +66270,23 @@ function EventItem({ event, onLoadEventData, encryptionKey }) {
66220
66270
  borderColor: "var(--ds-gray-300)"
66221
66271
  }, children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayData != null && jsxRuntimeExports.jsx("div", { className: "mt-2", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayData }) })] });
66222
66272
  }
66273
+ function hasOnlyExpiredFields(data) {
66274
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
66275
+ return false;
66276
+ }
66277
+ const record2 = data;
66278
+ const serializedKeys = ["result", "input", "output", "metadata", "payload"];
66279
+ const presentKeys = serializedKeys.filter((k2) => k2 in record2);
66280
+ return presentKeys.length > 0 && presentKeys.every((k2) => isExpiredMarker(record2[k2]));
66281
+ }
66223
66282
  function EventDataBlock({ eventType, data }) {
66283
+ if (isExpiredMarker(data) || hasOnlyExpiredFields(data)) {
66284
+ return jsxRuntimeExports.jsx("div", { className: "flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs", style: {
66285
+ borderColor: "var(--ds-gray-300)",
66286
+ backgroundColor: "var(--ds-gray-100)",
66287
+ color: "var(--ds-gray-700)"
66288
+ }, children: jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Data expired" }) });
66289
+ }
66224
66290
  if (ERROR_EVENT_TYPES.has(eventType) && data != null && typeof data === "object") {
66225
66291
  const record2 = data;
66226
66292
  if (isStructuredErrorWithStack(record2.error)) {
@@ -67065,8 +67131,7 @@ function formatWallClockTime(epochMs) {
67065
67131
  const h2 = String(d2.getHours()).padStart(2, "0");
67066
67132
  const m2 = String(d2.getMinutes()).padStart(2, "0");
67067
67133
  const s2 = String(d2.getSeconds()).padStart(2, "0");
67068
- const ms2 = String(d2.getMilliseconds()).padStart(3, "0");
67069
- return `${h2}:${m2}:${s2}.${ms2}`;
67134
+ return `${h2}:${m2}:${s2}`;
67070
67135
  }
67071
67136
  const SEGMENT_CLASS_MAP = {
67072
67137
  queued: "segQueued",
@@ -73762,6 +73827,9 @@ const BASE_URL = "https://useworkflow.dev/err";
73762
73827
  function isError(value) {
73763
73828
  return typeof value === "object" && value !== null && "name" in value && "message" in value;
73764
73829
  }
73830
+ const ERROR_SLUGS = {
73831
+ STEP_NOT_REGISTERED: "step-not-registered"
73832
+ };
73765
73833
  class WorkflowError extends Error {
73766
73834
  constructor(message2, options) {
73767
73835
  const msgDocs = (options == null ? void 0 : options.slug) ? `${message2}
@@ -73779,7 +73847,7 @@ Caused by: ${options.cause.stack}`;
73779
73847
  return isError(value) && value.name === "WorkflowError";
73780
73848
  }
73781
73849
  }
73782
- class WorkflowAPIError extends WorkflowError {
73850
+ class WorkflowWorldError extends WorkflowError {
73783
73851
  constructor(message2, options) {
73784
73852
  super(message2, {
73785
73853
  cause: options == null ? void 0 : options.cause
@@ -73787,16 +73855,16 @@ class WorkflowAPIError extends WorkflowError {
73787
73855
  __publicField(this, "status");
73788
73856
  __publicField(this, "code");
73789
73857
  __publicField(this, "url");
73790
- /** Retry-After value in seconds, present on 429 responses */
73858
+ /** Retry-After value in seconds, present on 429 and 425 responses */
73791
73859
  __publicField(this, "retryAfter");
73792
- this.name = "WorkflowAPIError";
73860
+ this.name = "WorkflowWorldError";
73793
73861
  this.status = options == null ? void 0 : options.status;
73794
73862
  this.code = options == null ? void 0 : options.code;
73795
73863
  this.url = options == null ? void 0 : options.url;
73796
73864
  this.retryAfter = options == null ? void 0 : options.retryAfter;
73797
73865
  }
73798
73866
  static is(value) {
73799
- return isError(value) && value.name === "WorkflowAPIError";
73867
+ return isError(value) && value.name === "WorkflowWorldError";
73800
73868
  }
73801
73869
  }
73802
73870
  class WorkflowRunFailedError extends WorkflowError {
@@ -73843,6 +73911,17 @@ class WorkflowRuntimeError extends WorkflowError {
73843
73911
  return isError(value) && value.name === "WorkflowRuntimeError";
73844
73912
  }
73845
73913
  }
73914
+ class StepNotRegisteredError extends WorkflowRuntimeError {
73915
+ constructor(stepName) {
73916
+ super(`Step "${stepName}" is not registered in the current deployment. This usually indicates a build or bundling issue that caused the step to not be included in the deployment.`, { slug: ERROR_SLUGS.STEP_NOT_REGISTERED });
73917
+ __publicField(this, "stepName");
73918
+ this.name = "StepNotRegisteredError";
73919
+ this.stepName = stepName;
73920
+ }
73921
+ static is(value) {
73922
+ return isError(value) && value.name === "StepNotRegisteredError";
73923
+ }
73924
+ }
73846
73925
  class WorkflowRunNotFoundError extends WorkflowError {
73847
73926
  constructor(runId) {
73848
73927
  super(`Workflow run "${runId}" not found`, {});
@@ -73865,6 +73944,44 @@ class HookNotFoundError extends WorkflowError {
73865
73944
  return isError(value) && value.name === "HookNotFoundError";
73866
73945
  }
73867
73946
  }
73947
+ class EntityConflictError extends WorkflowWorldError {
73948
+ constructor(message2) {
73949
+ super(message2);
73950
+ this.name = "EntityConflictError";
73951
+ }
73952
+ static is(value) {
73953
+ return isError(value) && value.name === "EntityConflictError";
73954
+ }
73955
+ }
73956
+ class RunExpiredError extends WorkflowWorldError {
73957
+ constructor(message2) {
73958
+ super(message2);
73959
+ this.name = "RunExpiredError";
73960
+ }
73961
+ static is(value) {
73962
+ return isError(value) && value.name === "RunExpiredError";
73963
+ }
73964
+ }
73965
+ class TooEarlyError extends WorkflowWorldError {
73966
+ constructor(message2, options) {
73967
+ super(message2, { retryAfter: options == null ? void 0 : options.retryAfter });
73968
+ this.name = "TooEarlyError";
73969
+ }
73970
+ static is(value) {
73971
+ return isError(value) && value.name === "TooEarlyError";
73972
+ }
73973
+ }
73974
+ class ThrottleError extends WorkflowWorldError {
73975
+ constructor(message2, options) {
73976
+ super(message2);
73977
+ __publicField(this, "retryAfter");
73978
+ this.name = "ThrottleError";
73979
+ this.retryAfter = options == null ? void 0 : options.retryAfter;
73980
+ }
73981
+ static is(value) {
73982
+ return isError(value) && value.name === "ThrottleError";
73983
+ }
73984
+ }
73868
73985
  class WorkflowRunCancelledError extends WorkflowError {
73869
73986
  constructor(runId) {
73870
73987
  super(`Workflow run "${runId}" cancelled`, {});
@@ -73918,6 +74035,7 @@ class RetryableError extends Error {
73918
74035
  }
73919
74036
  }
73920
74037
  const VERCEL_403_ERROR_MESSAGE = "Your current vercel account does not have access to this resource. Use `vercel login` or `vercel switch` to ensure you are linked to the right account.";
74038
+ const MAX_QUEUE_DELIVERIES = 48;
73921
74039
  const NEVER = Object.freeze({
73922
74040
  status: "aborted"
73923
74041
  });
@@ -87856,7 +87974,7 @@ const StructuredErrorSchema = object$1({
87856
87974
  message: string$1(),
87857
87975
  stack: string$1().optional(),
87858
87976
  code: string$1().optional()
87859
- // TODO: currently unused. make this an enum maybe
87977
+ // Populated with RunErrorCode values (USER_ERROR, RUNTIME_ERROR) for run_failed events
87860
87978
  });
87861
87979
  const WorkflowRunStatusSchema = _enum([
87862
87980
  "pending",
@@ -87869,6 +87987,26 @@ const WorkflowRunBaseSchema = object$1({
87869
87987
  runId: string$1(),
87870
87988
  status: WorkflowRunStatusSchema,
87871
87989
  deploymentId: string$1(),
87990
+ /**
87991
+ * The machine-readable name of the workflow function.
87992
+ *
87993
+ * This field contains a structured identifier like `workflow//./src/workflows/order//processOrder`
87994
+ * that encodes the workflow's module specifier and function name.
87995
+ *
87996
+ * Use `parseWorkflowName()` from `@workflow/utils/parse-name` to extract:
87997
+ * - `shortName`: User-friendly display name (e.g., `"processOrder"`)
87998
+ * - `moduleSpecifier`: The module path or package (e.g., `"./src/workflows/order"`)
87999
+ * - `functionName`: The full function path (e.g., `"processOrder"`)
88000
+ *
88001
+ * @example
88002
+ * ```ts
88003
+ * import { parseWorkflowName } from "@workflow/utils/parse-name";
88004
+ *
88005
+ * const parsed = parseWorkflowName(run.workflowName);
88006
+ * // parsed.shortName → "processOrder"
88007
+ * // parsed.moduleSpecifier → "./src/workflows/order"
88008
+ * ```
88009
+ */
87872
88010
  workflowName: string$1(),
87873
88011
  // Optional in database for backwards compatibility, defaults to 1 (legacy) when reading
87874
88012
  specVersion: number$1().optional(),
@@ -87934,6 +88072,26 @@ const StepStatusSchema = _enum([
87934
88072
  const StepSchema = object$1({
87935
88073
  runId: string$1(),
87936
88074
  stepId: string$1(),
88075
+ /**
88076
+ * The machine-readable name of the step function.
88077
+ *
88078
+ * This field contains a structured identifier like `step//./src/workflows/order//processPayment`
88079
+ * that encodes the step's module specifier and function name.
88080
+ *
88081
+ * Use `parseStepName()` from `@workflow/utils/parse-name` to extract:
88082
+ * - `shortName`: User-friendly display name (e.g., `"processPayment"`)
88083
+ * - `moduleSpecifier`: The module path or package (e.g., `"./src/workflows/order"`)
88084
+ * - `functionName`: The full function path (e.g., `"processPayment"` or `"outer/nested"`)
88085
+ *
88086
+ * @example
88087
+ * ```ts
88088
+ * import { parseStepName } from "@workflow/utils/parse-name";
88089
+ *
88090
+ * const parsed = parseStepName(step.stepName);
88091
+ * // parsed.shortName → "processPayment"
88092
+ * // parsed.moduleSpecifier → "./src/workflows/order"
88093
+ * ```
88094
+ */
87937
88095
  stepName: string$1(),
87938
88096
  status: StepStatusSchema,
87939
88097
  input: SerializedDataSchema,
@@ -87957,17 +88115,6 @@ const StepSchema = object$1({
87957
88115
  // Optional in database for backwards compatibility, defaults to 1 (legacy) when reading
87958
88116
  specVersion: number$1().optional()
87959
88117
  });
87960
- const WaitStatusSchema = _enum(["waiting", "completed"]);
87961
- const WaitSchema = object$1({
87962
- waitId: string$1(),
87963
- runId: string$1(),
87964
- status: WaitStatusSchema,
87965
- resumeAt: date$2().optional(),
87966
- completedAt: date$2().optional(),
87967
- createdAt: date$2(),
87968
- updatedAt: date$2(),
87969
- specVersion: number$1().optional()
87970
- });
87971
88118
  const ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
87972
88119
  const ENCODING_LEN = 32;
87973
88120
  const RANDOM_LEN = 16;
@@ -88136,6 +88283,17 @@ function validateUlidTimestamp(prefixedUlid, prefix, thresholdMs = DEFAULT_TIMES
88136
88283
  const thresholdSeconds = Math.round(thresholdMs / 1e3);
88137
88284
  return `Invalid runId timestamp: embedded timestamp differs from server time by ${driftSeconds}s (threshold: ${thresholdSeconds}s)`;
88138
88285
  }
88286
+ const WaitStatusSchema = _enum(["waiting", "completed"]);
88287
+ const WaitSchema = object$1({
88288
+ waitId: string$1(),
88289
+ runId: string$1(),
88290
+ status: WaitStatusSchema,
88291
+ resumeAt: date$2().optional(),
88292
+ completedAt: date$2().optional(),
88293
+ createdAt: date$2(),
88294
+ updatedAt: date$2(),
88295
+ specVersion: number$1().optional()
88296
+ });
88139
88297
  const NONCE_LENGTH = 12;
88140
88298
  const TAG_LENGTH = 128;
88141
88299
  const KEY_LENGTH = 32;
@@ -89426,12 +89584,12 @@ async function writeJSON(filePath, data, opts) {
89426
89584
  async function write(filePath, data, opts) {
89427
89585
  if (!(opts == null ? void 0 : opts.overwrite)) {
89428
89586
  if (createdFilesCache.has(filePath)) {
89429
- throw new WorkflowAPIError(`File ${filePath} already exists and 'overwrite' is false`, { status: 409 });
89587
+ throw new EntityConflictError(`File ${filePath} already exists and 'overwrite' is false`);
89430
89588
  }
89431
89589
  try {
89432
89590
  await promises.access(filePath);
89433
89591
  createdFilesCache.add(filePath);
89434
- throw new WorkflowAPIError(`File ${filePath} already exists and 'overwrite' is false`, { status: 409 });
89592
+ throw new EntityConflictError(`File ${filePath} already exists and 'overwrite' is false`);
89435
89593
  } catch (error2) {
89436
89594
  if (error2.code !== "ENOENT") {
89437
89595
  throw error2;
@@ -92211,8 +92369,8 @@ function requireGetVercelOidcToken() {
92211
92369
  }
92212
92370
  try {
92213
92371
  const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
92214
- await import("./token-util-C8FlMBAQ.js").then((n) => n.t),
92215
- await import("./token-Bf2BqxEG.js").then((n) => n.t)
92372
+ await import("./token-util-1mDJoKQG.js").then((n) => n.t),
92373
+ await import("./token-fvUEOQRa.js").then((n) => n.t)
92216
92374
  ]);
92217
92375
  if (!token || isExpired(getTokenPayload(token), options == null ? void 0 : options.expirationBufferMs)) {
92218
92376
  await refreshToken(options);
@@ -107826,7 +107984,7 @@ function requireSnapshotRecorder() {
107826
107984
  var _flushTimeout, _isUrlExcluded, _snapshots, _snapshotPath, _maxSnapshots, _autoFlush, _headerFilters, _SnapshotRecorder_instances, startAutoFlush_fn, stopAutoFlush_fn, scheduleFlush_fn;
107827
107985
  if (hasRequiredSnapshotRecorder) return snapshotRecorder;
107828
107986
  hasRequiredSnapshotRecorder = 1;
107829
- const { writeFile: writeFile2, readFile: readFile2, mkdir: mkdir2 } = require$$0$8;
107987
+ const { writeFile: writeFile2, readFile: readFile2, mkdir: mkdir2 } = fs$1;
107830
107988
  const { dirname: dirname2, resolve: resolve2 } = path$3;
107831
107989
  const { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = require$$2$3;
107832
107990
  const { InvalidArgumentError, UndiciError } = requireErrors();
@@ -119058,6 +119216,9 @@ function createQueue$2(config2) {
119058
119216
  const body2 = transport.serialize(message2);
119059
119217
  const { pathname, prefix } = getQueueRoute(queueName);
119060
119218
  const messageId = MessageId.parse(`msg_${generateId2()}`);
119219
+ const msg = message2;
119220
+ const runId = msg.runId ?? msg.workflowRunId ?? void 0;
119221
+ const stepId = msg.stepId ?? void 0;
119061
119222
  if (opts == null ? void 0 : opts.idempotencyKey) {
119062
119223
  const key = opts.idempotencyKey;
119063
119224
  inflightMessages.set(key, messageId);
@@ -119071,10 +119232,9 @@ function createQueue$2(config2) {
119071
119232
  console.warn(`[world-local]: concurrency limit (${WORKFLOW_LOCAL_QUEUE_CONCURRENCY}) reached, waiting for queue to free up`);
119072
119233
  await semaphore.acquire();
119073
119234
  }
119235
+ const MAX_LOCAL_SAFETY_LIMIT = 256;
119074
119236
  try {
119075
- let defaultRetriesLeft = 3;
119076
- for (let attempt = 0; defaultRetriesLeft > 0; attempt++) {
119077
- defaultRetriesLeft--;
119237
+ for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {
119078
119238
  const headers2 = {
119079
119239
  ...opts == null ? void 0 : opts.headers,
119080
119240
  "content-type": "application/json",
@@ -119110,22 +119270,27 @@ function createQueue$2(config2) {
119110
119270
  const timeoutMs = Math.min(timeoutSeconds * 1e3, MAX_SAFE_TIMEOUT_MS);
119111
119271
  await setTimeout$1(timeoutMs);
119112
119272
  }
119113
- defaultRetriesLeft++;
119114
119273
  continue;
119115
119274
  }
119116
119275
  } catch {
119117
119276
  }
119118
119277
  return;
119119
119278
  }
119120
- console.error(`[local world] Failed to queue message`, {
119279
+ console.error(`[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response2.status})`, {
119121
119280
  queueName,
119122
- text: text2,
119123
- status: response2.status,
119124
- headers: Object.fromEntries(response2.headers.entries()),
119125
- body: body2.toString()
119281
+ messageId,
119282
+ ...runId && { runId },
119283
+ ...stepId && { stepId },
119284
+ handlerError: text2
119126
119285
  });
119286
+ await setTimeout$1(5e3);
119127
119287
  }
119128
- console.error(`[local world] Reached max retries of local world queue implementation`);
119288
+ console.error(`[world-local] Queue message exhausted safety limit (${MAX_LOCAL_SAFETY_LIMIT} attempts)`, {
119289
+ queueName,
119290
+ messageId,
119291
+ ...runId && { runId },
119292
+ ...stepId && { stepId }
119293
+ });
119129
119294
  } finally {
119130
119295
  semaphore.release();
119131
119296
  }
@@ -119480,12 +119645,12 @@ function createEventsStorage(basedir, tag) {
119480
119645
  if (data.eventType === "run_created" && runId && runId !== "") {
119481
119646
  const validationError = validateUlidTimestamp(effectiveRunId, "wrun_");
119482
119647
  if (validationError) {
119483
- throw new WorkflowAPIError(validationError, { status: 400 });
119648
+ throw new WorkflowWorldError(validationError);
119484
119649
  }
119485
119650
  }
119486
119651
  const effectiveSpecVersion = data.specVersion ?? SPEC_VERSION_CURRENT;
119487
119652
  const isRunTerminal = (status) => ["completed", "failed", "cancelled"].includes(status);
119488
- const isStepTerminal = (status) => ["completed", "failed"].includes(status);
119653
+ const isStepTerminal = (status) => ["completed", "failed", "cancelled"].includes(status);
119489
119654
  let currentRun = null;
119490
119655
  const skipRunValidationEvents = ["step_completed", "step_retrying"];
119491
119656
  if (data.eventType !== "run_created" && !skipRunValidationEvents.includes(data.eventType)) {
@@ -119522,10 +119687,10 @@ function createEventsStorage(basedir, tag) {
119522
119687
  };
119523
119688
  }
119524
119689
  if (runTerminalEvents.includes(data.eventType) || data.eventType === "run_cancelled") {
119525
- throw new WorkflowAPIError(`Cannot transition run from terminal state "${currentRun.status}"`, { status: 409 });
119690
+ throw new EntityConflictError(`Cannot transition run from terminal state "${currentRun.status}"`);
119526
119691
  }
119527
119692
  if (data.eventType === "step_created" || data.eventType === "hook_created" || data.eventType === "wait_created") {
119528
- throw new WorkflowAPIError(`Cannot create new entities on run in terminal state "${currentRun.status}"`, { status: 409 });
119693
+ throw new EntityConflictError(`Cannot create new entities on run in terminal state "${currentRun.status}"`);
119529
119694
  }
119530
119695
  }
119531
119696
  let validatedStep = null;
@@ -119539,26 +119704,22 @@ function createEventsStorage(basedir, tag) {
119539
119704
  const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
119540
119705
  validatedStep = await readJSONWithFallback(basedir, "steps", stepCompositeKey, StepSchema, tag);
119541
119706
  if (!validatedStep) {
119542
- throw new WorkflowAPIError(`Step "${data.correlationId}" not found`, {
119543
- status: 404
119544
- });
119707
+ throw new WorkflowWorldError(`Step "${data.correlationId}" not found`);
119545
119708
  }
119546
119709
  if (isStepTerminal(validatedStep.status)) {
119547
- throw new WorkflowAPIError(`Cannot modify step in terminal state "${validatedStep.status}"`, { status: 409 });
119710
+ throw new EntityConflictError(`Cannot modify step in terminal state "${validatedStep.status}"`);
119548
119711
  }
119549
119712
  if (currentRun && isRunTerminal(currentRun.status)) {
119550
119713
  if (validatedStep.status !== "running") {
119551
- throw new WorkflowAPIError(`Cannot modify non-running step on run in terminal state "${currentRun.status}"`, { status: 410 });
119714
+ throw new RunExpiredError(`Cannot modify non-running step on run in terminal state "${currentRun.status}"`);
119552
119715
  }
119553
119716
  }
119554
119717
  }
119555
- const hookEventsRequiringExistence = ["hook_disposed", "hook_received"];
119556
- if (hookEventsRequiringExistence.includes(data.eventType) && data.correlationId) {
119718
+ const hookEventsRequiringExistence2 = ["hook_disposed", "hook_received"];
119719
+ if (hookEventsRequiringExistence2.includes(data.eventType) && data.correlationId) {
119557
119720
  const existingHook = await readJSONWithFallback(basedir, "hooks", data.correlationId, HookSchema, tag);
119558
119721
  if (!existingHook) {
119559
- throw new WorkflowAPIError(`Hook "${data.correlationId}" not found`, {
119560
- status: 404
119561
- });
119722
+ throw new HookNotFoundError(data.correlationId);
119562
119723
  }
119563
119724
  }
119564
119725
  const event = {
@@ -119715,14 +119876,15 @@ function createEventsStorage(basedir, tag) {
119715
119876
  } else if (data.eventType === "step_started") {
119716
119877
  if (validatedStep) {
119717
119878
  if (validatedStep.retryAfter && validatedStep.retryAfter.getTime() > Date.now()) {
119718
- const err = new WorkflowAPIError(`Cannot start step "${data.correlationId}": retryAfter timestamp has not been reached yet`, { status: 425 });
119719
- err.meta = {
119720
- stepId: data.correlationId,
119721
- retryAfter: validatedStep.retryAfter.toISOString()
119722
- };
119723
- throw err;
119879
+ throw new TooEarlyError(`Cannot start step "${data.correlationId}": retryAfter timestamp has not been reached yet`, {
119880
+ retryAfter: Math.ceil((validatedStep.retryAfter.getTime() - Date.now()) / 1e3)
119881
+ });
119724
119882
  }
119725
119883
  const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
119884
+ const freshStep = await readJSONWithFallback(basedir, "steps", stepCompositeKey, StepSchema, tag);
119885
+ if (freshStep && isStepTerminal(freshStep.status)) {
119886
+ throw new EntityConflictError(`Cannot modify step in terminal state "${freshStep.status}"`);
119887
+ }
119726
119888
  step = {
119727
119889
  ...validatedStep,
119728
119890
  status: "running",
@@ -119740,6 +119902,12 @@ function createEventsStorage(basedir, tag) {
119740
119902
  const completedData = data.eventData;
119741
119903
  if (validatedStep) {
119742
119904
  const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
119905
+ const lockName = tag ? `${stepCompositeKey}.terminal.${tag}` : `${stepCompositeKey}.terminal`;
119906
+ const terminalLockPath = path$3.join(basedir, ".locks", "steps", lockName);
119907
+ const claimed = await writeExclusive(terminalLockPath, "");
119908
+ if (!claimed) {
119909
+ throw new EntityConflictError("Cannot modify step in terminal state");
119910
+ }
119743
119911
  step = {
119744
119912
  ...validatedStep,
119745
119913
  status: "completed",
@@ -119753,6 +119921,12 @@ function createEventsStorage(basedir, tag) {
119753
119921
  const failedData = data.eventData;
119754
119922
  if (validatedStep) {
119755
119923
  const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;
119924
+ const lockName = tag ? `${stepCompositeKey}.terminal.${tag}` : `${stepCompositeKey}.terminal`;
119925
+ const terminalLockPath = path$3.join(basedir, ".locks", "steps", lockName);
119926
+ const claimed = await writeExclusive(terminalLockPath, "");
119927
+ if (!claimed) {
119928
+ throw new EntityConflictError("Cannot modify step in terminal state");
119929
+ }
119756
119930
  const error2 = {
119757
119931
  message: typeof failedData.error === "string" ? failedData.error : ((_c = failedData.error) == null ? void 0 : _c.message) ?? "Unknown error",
119758
119932
  stack: failedData.stack
@@ -119831,6 +120005,12 @@ function createEventsStorage(basedir, tag) {
119831
120005
  };
119832
120006
  await writeJSON(taggedPath(basedir, "hooks", data.correlationId, tag), hook);
119833
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
+ }
119834
120014
  const hookPath = taggedPath(basedir, "hooks", data.correlationId, tag);
119835
120015
  const existingHook = await readJSONWithFallback(basedir, "hooks", data.correlationId, HookSchema, tag);
119836
120016
  if (existingHook) {
@@ -119843,7 +120023,7 @@ function createEventsStorage(basedir, tag) {
119843
120023
  const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;
119844
120024
  const existingWait = await readJSONWithFallback(basedir, "waits", waitCompositeKey, WaitSchema, tag);
119845
120025
  if (existingWait) {
119846
- throw new WorkflowAPIError(`Wait "${data.correlationId}" already exists`, { status: 409 });
120026
+ throw new EntityConflictError(`Wait "${data.correlationId}" already exists`);
119847
120027
  }
119848
120028
  wait = {
119849
120029
  waitId: waitCompositeKey,
@@ -119858,14 +120038,17 @@ function createEventsStorage(basedir, tag) {
119858
120038
  await writeJSON(taggedPath(basedir, "waits", waitCompositeKey, tag), wait);
119859
120039
  } else if (data.eventType === "wait_completed") {
119860
120040
  const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;
120041
+ const waitLockName = tag ? `${waitCompositeKey}.completed.${tag}` : `${waitCompositeKey}.completed`;
120042
+ const lockPath = path$3.join(basedir, ".locks", "waits", waitLockName);
120043
+ const claimed = await writeExclusive(lockPath, "");
120044
+ if (!claimed) {
120045
+ throw new EntityConflictError(`Wait "${data.correlationId}" already completed`);
120046
+ }
119861
120047
  const existingWait = await readJSONWithFallback(basedir, "waits", waitCompositeKey, WaitSchema, tag);
119862
120048
  if (!existingWait) {
119863
- throw new WorkflowAPIError(`Wait "${data.correlationId}" not found`, {
119864
- status: 404
120049
+ await fs$1.unlink(lockPath).catch(() => {
119865
120050
  });
119866
- }
119867
- if (existingWait.status === "completed") {
119868
- throw new WorkflowAPIError(`Wait "${data.correlationId}" already completed`, { status: 409 });
120051
+ throw new WorkflowWorldError(`Wait "${data.correlationId}" not found`);
119869
120052
  }
119870
120053
  wait = {
119871
120054
  ...existingWait,
@@ -120060,6 +120243,9 @@ function serializeChunk(chunk) {
120060
120243
  const eofByte = Buffer.from([chunk.eof ? 1 : 0]);
120061
120244
  return Buffer.concat([eofByte, chunk.chunk]);
120062
120245
  }
120246
+ function isEofChunk(serialized) {
120247
+ return serialized[0] === 1;
120248
+ }
120063
120249
  function deserializeChunk(serialized) {
120064
120250
  const eof = serialized[0] === 1;
120065
120251
  const chunk = Buffer.from(serialized.subarray(1));
@@ -120152,6 +120338,117 @@ function createStreamer$1(basedir, tag) {
120152
120338
  const data = await readJSONWithFallback(basedir, "streams/runs", runId, RunStreamsSchema, tag);
120153
120339
  return (data == null ? void 0 : data.streams) ?? [];
120154
120340
  },
120341
+ async getStreamChunks(name2, _runId, options) {
120342
+ const limit = (options == null ? void 0 : options.limit) ?? 100;
120343
+ const chunksDir = path$3.join(basedir, "streams", "chunks");
120344
+ const listPromises = [
120345
+ listFilesByExtension(chunksDir, ".bin"),
120346
+ listFilesByExtension(chunksDir, ".json")
120347
+ ];
120348
+ if (tag) {
120349
+ listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120350
+ }
120351
+ const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120352
+ const taggedBinFiles = taggedResults[0] ?? [];
120353
+ const fileExtMap = /* @__PURE__ */ new Map();
120354
+ for (const f2 of jsonFiles)
120355
+ fileExtMap.set(f2, ".json");
120356
+ const tagSfx = tag ? `.${tag}` : "";
120357
+ for (const f2 of binFiles) {
120358
+ if (tag && f2.endsWith(tagSfx))
120359
+ continue;
120360
+ fileExtMap.set(f2, ".bin");
120361
+ }
120362
+ for (const f2 of taggedBinFiles)
120363
+ fileExtMap.set(f2, `.${tag}.bin`);
120364
+ const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120365
+ let startIndex = 0;
120366
+ if (options == null ? void 0 : options.cursor) {
120367
+ try {
120368
+ const decoded = JSON.parse(Buffer.from(options.cursor, "base64").toString("utf-8"));
120369
+ startIndex = decoded.i;
120370
+ } catch {
120371
+ startIndex = 0;
120372
+ }
120373
+ }
120374
+ let streamDone = false;
120375
+ const resultChunks = [];
120376
+ let dataIndex = 0;
120377
+ for (const file2 of chunkFiles) {
120378
+ const ext2 = fileExtMap.get(file2) ?? ".bin";
120379
+ const filePath = path$3.join(chunksDir, `${file2}${ext2}`);
120380
+ if (dataIndex < startIndex) {
120381
+ if (isEofChunk(await readBuffer(filePath))) {
120382
+ streamDone = true;
120383
+ break;
120384
+ }
120385
+ dataIndex++;
120386
+ continue;
120387
+ }
120388
+ if (resultChunks.length >= limit) {
120389
+ if (isEofChunk(await readBuffer(filePath))) {
120390
+ streamDone = true;
120391
+ } else {
120392
+ dataIndex++;
120393
+ }
120394
+ break;
120395
+ }
120396
+ const chunk = deserializeChunk(await readBuffer(filePath));
120397
+ if (chunk.eof) {
120398
+ streamDone = true;
120399
+ break;
120400
+ }
120401
+ resultChunks.push({
120402
+ index: dataIndex,
120403
+ data: Uint8Array.from(chunk.chunk)
120404
+ });
120405
+ dataIndex++;
120406
+ }
120407
+ const hasMore = !streamDone && dataIndex > startIndex + resultChunks.length;
120408
+ const nextIndex = startIndex + resultChunks.length;
120409
+ const nextCursor = hasMore ? Buffer.from(JSON.stringify({ i: nextIndex })).toString("base64") : null;
120410
+ return {
120411
+ data: resultChunks,
120412
+ cursor: nextCursor,
120413
+ hasMore,
120414
+ done: streamDone
120415
+ };
120416
+ },
120417
+ async getStreamInfo(name2, _runId) {
120418
+ const chunksDir = path$3.join(basedir, "streams", "chunks");
120419
+ const listPromises = [
120420
+ listFilesByExtension(chunksDir, ".bin"),
120421
+ listFilesByExtension(chunksDir, ".json")
120422
+ ];
120423
+ if (tag) {
120424
+ listPromises.push(listFilesByExtension(chunksDir, `.${tag}.bin`));
120425
+ }
120426
+ const [binFiles, jsonFiles, ...taggedResults] = await Promise.all(listPromises);
120427
+ const taggedBinFiles = taggedResults[0] ?? [];
120428
+ const fileExtMap = /* @__PURE__ */ new Map();
120429
+ for (const f2 of jsonFiles)
120430
+ fileExtMap.set(f2, ".json");
120431
+ const tagSfx = tag ? `.${tag}` : "";
120432
+ for (const f2 of binFiles) {
120433
+ if (tag && f2.endsWith(tagSfx))
120434
+ continue;
120435
+ fileExtMap.set(f2, ".bin");
120436
+ }
120437
+ for (const f2 of taggedBinFiles)
120438
+ fileExtMap.set(f2, `.${tag}.bin`);
120439
+ const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120440
+ let streamDone = false;
120441
+ let dataCount = 0;
120442
+ for (const file2 of chunkFiles) {
120443
+ const ext2 = fileExtMap.get(file2) ?? ".bin";
120444
+ if (isEofChunk(await readBuffer(path$3.join(chunksDir, `${file2}${ext2}`)))) {
120445
+ streamDone = true;
120446
+ break;
120447
+ }
120448
+ dataCount++;
120449
+ }
120450
+ return { tailIndex: dataCount - 1, done: streamDone };
120451
+ },
120155
120452
  async readFromStream(name2, startIndex = 0) {
120156
120453
  const chunksDir = path$3.join(basedir, "streams", "chunks");
120157
120454
  let removeListeners = () => {
@@ -120212,8 +120509,18 @@ function createStreamer$1(basedir, tag) {
120212
120509
  for (const f2 of taggedBinFiles)
120213
120510
  fileExtMap.set(f2, `.${tag}.bin`);
120214
120511
  const chunkFiles = [...fileExtMap.keys()].filter((file2) => file2.startsWith(`${name2}-`)).sort();
120512
+ let dataChunkCount = chunkFiles.length;
120513
+ if (typeof startIndex === "number" && startIndex < 0 && chunkFiles.length > 0) {
120514
+ const lastFile = chunkFiles[chunkFiles.length - 1];
120515
+ const lastExt = fileExtMap.get(lastFile) ?? ".bin";
120516
+ const lastChunk = deserializeChunk(await readBuffer(path$3.join(chunksDir, `${lastFile}${lastExt}`)));
120517
+ if ((lastChunk == null ? void 0 : lastChunk.eof) === true) {
120518
+ dataChunkCount--;
120519
+ }
120520
+ }
120521
+ const resolvedStartIndex = typeof startIndex === "number" && startIndex < 0 ? Math.max(0, dataChunkCount + startIndex) : startIndex;
120215
120522
  let isComplete = false;
120216
- for (let i = startIndex; i < chunkFiles.length; i++) {
120523
+ for (let i = resolvedStartIndex; i < chunkFiles.length; i++) {
120217
120524
  const file2 = chunkFiles[i];
120218
120525
  const rawChunkId = file2.substring(name2.length + 1);
120219
120526
  const chunkId = tag ? rawChunkId.replace(`.${tag}`, "") : rawChunkId;
@@ -120267,7 +120574,7 @@ function createLocalWorld(args) {
120267
120574
  return {
120268
120575
  ...queue,
120269
120576
  ...createStorage$1(mergedConfig.dataDir, tag),
120270
- ...createStreamer$1(mergedConfig.dataDir, tag),
120577
+ ...instrumentObject$1("world.streams", createStreamer$1(mergedConfig.dataDir, tag)),
120271
120578
  async start() {
120272
120579
  await initDataDir(mergedConfig.dataDir);
120273
120580
  },
@@ -120279,7 +120586,7 @@ function createLocalWorld(args) {
120279
120586
  const basedir = mergedConfig.dataDir;
120280
120587
  const hooksDir = path$3.join(basedir, "hooks");
120281
120588
  const taggedHookFiles = await listTaggedFiles(hooksDir, tag);
120282
- const { HookSchema: HookSchema2 } = await import("./index-93Io7SSr.js");
120589
+ const { HookSchema: HookSchema2 } = await import("./index-BHIV6JOr.js");
120283
120590
  await Promise.all(taggedHookFiles.map(async (hookFile) => {
120284
120591
  const hook = await readJSON(path$3.join(hooksDir, hookFile), HookSchema2);
120285
120592
  if (hook == null ? void 0 : hook.token) {
@@ -120299,6 +120606,8 @@ function createLocalWorld(args) {
120299
120606
  const files = await listTaggedFiles(fullDir, tag);
120300
120607
  await Promise.all(files.map((f2) => deleteJSON(path$3.join(fullDir, f2))));
120301
120608
  }));
120609
+ await promises.rm(path$3.join(basedir, ".locks"), { recursive: true, force: true }).catch(() => {
120610
+ });
120302
120611
  const chunksDir = path$3.join(basedir, "streams", "chunks");
120303
120612
  const taggedBinFiles = await listTaggedFilesByExtension(chunksDir, tag, ".bin");
120304
120613
  await Promise.all(taggedBinFiles.map((f2) => promises.unlink(path$3.join(chunksDir, f2)).catch(() => {
@@ -120482,10 +120791,60 @@ const PeerService = SemanticConvention("peer.service");
120482
120791
  const RpcSystem = SemanticConvention("rpc.system");
120483
120792
  const RpcService = SemanticConvention("rpc.service");
120484
120793
  const RpcMethod = SemanticConvention("rpc.method");
120485
- const version$1 = "4.1.0-beta.44";
120794
+ const WORKFLOW_SERVER_SERVICE = {
120795
+ peerService: "workflow-server",
120796
+ rpcSystem: "http",
120797
+ rpcService: "workflow-server"
120798
+ };
120799
+ function extractEventType(args) {
120800
+ if (args.length >= 2 && typeof args[1] === "object" && args[1] !== null) {
120801
+ const data = args[1];
120802
+ if (typeof data.eventType === "string") {
120803
+ return data.eventType;
120804
+ }
120805
+ }
120806
+ return void 0;
120807
+ }
120808
+ function instrumentObject(prefix, o) {
120809
+ const handlers2 = {};
120810
+ for (const key of Object.keys(o)) {
120811
+ if (typeof o[key] !== "function") {
120812
+ handlers2[key] = o[key];
120813
+ } else {
120814
+ const f2 = o[key];
120815
+ const methodName = String(key);
120816
+ handlers2[key] = async (...args) => {
120817
+ let spanName2 = `${prefix}.${methodName}`;
120818
+ if (prefix === "world.events" && methodName === "create") {
120819
+ const eventType = extractEventType(args);
120820
+ if (eventType) {
120821
+ spanName2 = `${prefix}.${methodName} ${eventType}`;
120822
+ }
120823
+ }
120824
+ return trace(spanName2, { kind: await getSpanKind("CLIENT") }, async (span) => {
120825
+ span == null ? void 0 : span.setAttributes({
120826
+ ...PeerService(WORKFLOW_SERVER_SERVICE.peerService),
120827
+ ...RpcSystem(WORKFLOW_SERVER_SERVICE.rpcSystem),
120828
+ ...RpcService(WORKFLOW_SERVER_SERVICE.rpcService),
120829
+ ...RpcMethod(spanName2)
120830
+ });
120831
+ return f2(...args);
120832
+ });
120833
+ };
120834
+ }
120835
+ }
120836
+ return handlers2;
120837
+ }
120838
+ const version$1 = "4.1.0-beta.45";
120839
+ const HTTP_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
120840
+ function httpLog(method, endpoint, status, ms2) {
120841
+ if (HTTP_DEBUG_ENABLED) {
120842
+ console.debug(`[workflow:world-vercel:http] ${method} ${endpoint} -> ${status} (${ms2}ms)`);
120843
+ }
120844
+ }
120486
120845
  const DEFAULT_RESOLVE_DATA_OPTION = "all";
120487
120846
  function deserializeError(obj) {
120488
- const { error: error2, ...rest } = obj;
120847
+ const { error: error2, errorCode, ...rest } = obj;
120489
120848
  if (!error2) {
120490
120849
  return obj;
120491
120850
  }
@@ -120497,7 +120856,7 @@ function deserializeError(obj) {
120497
120856
  error: {
120498
120857
  message: result.data.message,
120499
120858
  stack: result.data.stack,
120500
- code: result.data.code
120859
+ code: errorCode ?? result.data.code
120501
120860
  }
120502
120861
  };
120503
120862
  }
@@ -120510,14 +120869,15 @@ function deserializeError(obj) {
120510
120869
  error: {
120511
120870
  message: parsed.message,
120512
120871
  stack: parsed.stack,
120513
- code: parsed.code
120872
+ code: errorCode ?? parsed.code
120514
120873
  }
120515
120874
  };
120516
120875
  } catch {
120517
120876
  return {
120518
120877
  ...rest,
120519
120878
  error: {
120520
- message: error2
120879
+ message: error2,
120880
+ code: errorCode
120521
120881
  }
120522
120882
  };
120523
120883
  }
@@ -120577,7 +120937,6 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
120577
120937
  } catch {
120578
120938
  }
120579
120939
  return trace(`http ${method}`, { kind: await getSpanKind("CLIENT") }, async (span) => {
120580
- var _a3;
120581
120940
  span == null ? void 0 : span.setAttributes({
120582
120941
  ...HttpRequestMethod(method),
120583
120942
  ...UrlFull(url2),
@@ -120600,35 +120959,57 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
120600
120959
  body: body2,
120601
120960
  headers: headers2
120602
120961
  });
120962
+ const fetchStart = Date.now();
120603
120963
  const response2 = await fetch(request2, {
120604
120964
  dispatcher: getDispatcher()
120605
120965
  });
120966
+ const fetchMs = Date.now() - fetchStart;
120967
+ httpLog(method, endpoint, response2.status, fetchMs);
120606
120968
  span == null ? void 0 : span.setAttributes({
120607
120969
  ...HttpResponseStatusCode(response2.status)
120608
120970
  });
120609
120971
  if (!response2.ok) {
120610
120972
  const errorData = await parseResponseBody(response2).then((r2) => r2.data).catch(() => ({}));
120611
- if (process.env.DEBUG === "1") {
120612
- const stringifiedHeaders = Array.from(headers2.entries()).map(([key, value]) => `-H "${key}: ${value}"`).join(" ");
120973
+ if (process.env.DEBUG) {
120974
+ const stringifiedHeaders = Array.from(headers2.entries()).filter(([key]) => key.toLowerCase() !== "authorization").map(([key, value]) => `-H "${key}: ${value}"`).join(" ");
120613
120975
  console.error(`Failed to fetch, reproduce with:
120614
120976
  curl -X ${request2.method} ${stringifiedHeaders} "${url2}"`);
120615
120977
  }
120616
120978
  let retryAfter;
120617
- if (response2.status === 429) {
120618
- const retryAfterHeader = response2.headers.get("Retry-After");
120619
- if (retryAfterHeader) {
120620
- const parsed = parseInt(retryAfterHeader, 10);
120621
- if (!Number.isNaN(parsed)) {
120622
- retryAfter = parsed;
120623
- }
120979
+ const retryAfterHeader = response2.headers.get("Retry-After");
120980
+ if (retryAfterHeader) {
120981
+ const parsed = parseInt(retryAfterHeader, 10);
120982
+ if (!Number.isNaN(parsed)) {
120983
+ retryAfter = parsed;
120624
120984
  }
120625
120985
  }
120626
- const error2 = new WorkflowAPIError(errorData.message || `${request2.method} ${endpoint} -> HTTP ${response2.status}: ${response2.statusText}`, { url: url2, status: response2.status, code: errorData.code, retryAfter });
120627
- span == null ? void 0 : span.setAttributes({
120628
- ...ErrorType(errorData.code || `HTTP ${response2.status}`)
120629
- });
120630
- (_a3 = span == null ? void 0 : span.recordException) == null ? void 0 : _a3.call(span, error2);
120631
- throw error2;
120986
+ const defaultMessage = errorData.message || `${request2.method} ${endpoint} -> HTTP ${response2.status}: ${response2.statusText}`;
120987
+ const throwWithTrace = (error2) => {
120988
+ var _a3;
120989
+ span == null ? void 0 : span.setAttributes({
120990
+ ...ErrorType(errorData.code || `HTTP ${response2.status}`)
120991
+ });
120992
+ (_a3 = span == null ? void 0 : span.recordException) == null ? void 0 : _a3.call(span, error2);
120993
+ throw error2;
120994
+ };
120995
+ if (response2.status === 409) {
120996
+ throwWithTrace(new EntityConflictError(defaultMessage));
120997
+ }
120998
+ if (response2.status === 410) {
120999
+ throwWithTrace(new RunExpiredError(defaultMessage));
121000
+ }
121001
+ if (response2.status === 425) {
121002
+ throwWithTrace(new TooEarlyError(defaultMessage, { retryAfter }));
121003
+ }
121004
+ if (response2.status === 429) {
121005
+ throwWithTrace(new ThrottleError(defaultMessage, { retryAfter }));
121006
+ }
121007
+ throwWithTrace(new WorkflowWorldError(defaultMessage, {
121008
+ url: url2,
121009
+ status: response2.status,
121010
+ code: errorData.code,
121011
+ retryAfter
121012
+ }));
120632
121013
  }
120633
121014
  onResponse == null ? void 0 : onResponse(response2);
120634
121015
  let parseResult;
@@ -120644,18 +121025,19 @@ curl -X ${request2.method} ${stringifiedHeaders} "${url2}"`);
120644
121025
  });
120645
121026
  } catch (error2) {
120646
121027
  const contentType = response2.headers.get("Content-Type") || "unknown";
120647
- throw new WorkflowAPIError(`Failed to parse response body for ${request2.method} ${endpoint} (Content-Type: ${contentType}):
121028
+ throw new WorkflowWorldError(`Failed to parse response body for ${request2.method} ${endpoint} (Content-Type: ${contentType}):
120648
121029
 
120649
121030
  ${error2}`, { url: url2, cause: error2 });
120650
121031
  }
120651
121032
  const result = await trace("world.validate", async () => {
120652
121033
  const validationResult = schema.safeParse(parseResult.data);
120653
121034
  if (!validationResult.success) {
120654
- throw new WorkflowAPIError(`Schema validation failed for ${method} ${endpoint}:
120655
-
120656
- ${validationResult.error}
121035
+ const issues = validationResult.error.issues.map((i) => ` ${i.path.length > 0 ? i.path.join(".") : "<root>"}: ${i.message}`).join("\n");
121036
+ const debugContext = process.env.DEBUG ? `
120657
121037
 
120658
- Response context: ${parseResult.getDebugContext()}`, { url: url2, cause: validationResult.error });
121038
+ Response context: ${parseResult.getDebugContext()}` : "";
121039
+ throw new WorkflowWorldError(`Schema validation failed for ${method} ${endpoint}:
121040
+ ${issues}${debugContext}`, { url: url2, cause: validationResult.error });
120659
121041
  }
120660
121042
  return validationResult.data;
120661
121043
  });
@@ -120881,7 +121263,7 @@ async function resolveRefDescriptor(descriptor, runId, config2) {
120881
121263
  ...HttpResponseStatusCode(response2.status)
120882
121264
  });
120883
121265
  if (!response2.ok) {
120884
- const error2 = new WorkflowAPIError(`Failed to resolve ref: HTTP ${response2.status}`, { url: url2, status: response2.status });
121266
+ const error2 = new WorkflowWorldError(`Failed to resolve ref: HTTP ${response2.status}`, { url: url2, status: response2.status });
120885
121267
  span == null ? void 0 : span.setAttributes({
120886
121268
  ...ErrorType(`HTTP ${response2.status}`)
120887
121269
  });
@@ -120928,6 +121310,9 @@ const WorkflowRunWireBaseSchema = WorkflowRunBaseSchema.omit({
120928
121310
  }).extend({
120929
121311
  // Backend returns error as either a JSON string or structured object
120930
121312
  error: union([string$1(), StructuredErrorSchema]).optional(),
121313
+ // errorCode is stored inline on the run entity (not inside errorRef).
121314
+ // It's merged into StructuredError.code by deserializeError().
121315
+ errorCode: string$1().optional(),
120931
121316
  // Not part of the World interface, but passed through for direct consumers and debugging
120932
121317
  blobStorageBytes: number$1().optional(),
120933
121318
  streamStorageBytes: number$1().optional()
@@ -121010,7 +121395,7 @@ async function getWorkflowRun(id2, params, config2) {
121010
121395
  });
121011
121396
  return filterRunData(run, resolveData);
121012
121397
  } catch (error2) {
121013
- if (error2 instanceof WorkflowAPIError && error2.status === 404) {
121398
+ if (error2 instanceof WorkflowWorldError && error2.status === 404) {
121014
121399
  throw new WorkflowRunNotFoundError(id2);
121015
121400
  }
121016
121401
  throw error2;
@@ -121032,7 +121417,7 @@ async function cancelWorkflowRunV1(id2, params, config2) {
121032
121417
  });
121033
121418
  return filterRunData(run, resolveData);
121034
121419
  } catch (error2) {
121035
- if (error2 instanceof WorkflowAPIError && error2.status === 404) {
121420
+ if (error2 instanceof WorkflowWorldError && error2.status === 404) {
121036
121421
  throw new WorkflowRunNotFoundError(id2);
121037
121422
  }
121038
121423
  throw error2;
@@ -121184,7 +121569,8 @@ const eventDataRefFieldMap = {
121184
121569
  step_completed: "result",
121185
121570
  step_failed: "error",
121186
121571
  step_retrying: "error",
121187
- hook_created: "metadata"
121572
+ hook_created: "metadata",
121573
+ hook_received: "payload"
121188
121574
  };
121189
121575
  const eventsNeedingResolve = /* @__PURE__ */ new Set([
121190
121576
  "run_created",
@@ -121275,7 +121661,7 @@ async function getEvent(runId, eventId, params, config2) {
121275
121661
  const searchParams = new URLSearchParams();
121276
121662
  searchParams.set("remoteRefBehavior", remoteRefBehavior);
121277
121663
  const queryString = searchParams.toString();
121278
- const endpoint = `/v2/runs/${encodeURIComponent(runId)}/events/${encodeURIComponent(eventId)}${queryString ? `?${queryString}` : ""}`;
121664
+ const endpoint = `/v3/runs/${encodeURIComponent(runId)}/events/${encodeURIComponent(eventId)}${queryString ? `?${queryString}` : ""}`;
121279
121665
  const event = await makeRequest({
121280
121666
  endpoint,
121281
121667
  options: { method: "GET" },
@@ -121308,7 +121694,7 @@ async function getWorkflowRunEvents(params, config2) {
121308
121694
  searchParams.set("remoteRefBehavior", "lazy");
121309
121695
  const queryString = searchParams.toString();
121310
121696
  const query = queryString ? `?${queryString}` : "";
121311
- const endpoint = correlationId ? `/v2/events${query}` : `/v2/runs/${encodeURIComponent(runId)}/events${query}`;
121697
+ const endpoint = correlationId ? `/v2/events${query}` : `/v3/runs/${encodeURIComponent(runId)}/events${query}`;
121312
121698
  let refResolveConcurrency;
121313
121699
  const response2 = await makeRequest({
121314
121700
  endpoint,
@@ -121347,7 +121733,21 @@ async function getWorkflowRunEvents(params, config2) {
121347
121733
  data: response2.data.map((event) => stripEventAndLegacyRefs(event, resolveData))
121348
121734
  };
121349
121735
  }
121736
+ const hookEventsRequiringExistence = /* @__PURE__ */ new Set([
121737
+ "hook_disposed",
121738
+ "hook_received"
121739
+ ]);
121350
121740
  async function createWorkflowRunEvent(id2, data, params, config2) {
121741
+ try {
121742
+ return await createWorkflowRunEventInner(id2, data, params, config2);
121743
+ } catch (err) {
121744
+ if (hookEventsRequiringExistence.has(data.eventType) && WorkflowWorldError.is(err) && err.status === 404 && data.correlationId) {
121745
+ throw new HookNotFoundError(data.correlationId);
121746
+ }
121747
+ throw err;
121748
+ }
121749
+ }
121750
+ async function createWorkflowRunEventInner(id2, data, params, config2) {
121351
121751
  const resolveData = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION;
121352
121752
  const v1Compat = (params == null ? void 0 : params.v1Compat) ?? false;
121353
121753
  if (v1Compat) {
@@ -121370,14 +121770,14 @@ async function createWorkflowRunEvent(id2, data, params, config2) {
121370
121770
  if (data.eventType === "run_created" && id2) {
121371
121771
  const validationError = validateUlidTimestamp(id2, "wrun_");
121372
121772
  if (validationError) {
121373
- throw new WorkflowAPIError(validationError, { status: 400 });
121773
+ throw new WorkflowWorldError(validationError, { status: 400 });
121374
121774
  }
121375
121775
  }
121376
121776
  const runIdPath = id2 === null ? "null" : encodeURIComponent(id2);
121377
121777
  const remoteRefBehavior = eventsNeedingResolve.has(data.eventType) ? "resolve" : "lazy";
121378
121778
  if (remoteRefBehavior === "resolve") {
121379
121779
  const wireResult2 = await makeRequest({
121380
- endpoint: `/v2/runs/${runIdPath}/events`,
121780
+ endpoint: `/v3/runs/${runIdPath}/events`,
121381
121781
  options: { method: "POST" },
121382
121782
  data: {
121383
121783
  ...data,
@@ -121395,7 +121795,7 @@ async function createWorkflowRunEvent(id2, data, params, config2) {
121395
121795
  };
121396
121796
  }
121397
121797
  const wireResult = await makeRequest({
121398
- endpoint: `/v2/runs/${runIdPath}/events`,
121798
+ endpoint: `/v3/runs/${runIdPath}/events`,
121399
121799
  options: { method: "POST" },
121400
121800
  data: {
121401
121801
  ...data,
@@ -121472,56 +121872,12 @@ async function getHookByToken(token, config2) {
121472
121872
  schema: HookSchema
121473
121873
  });
121474
121874
  } catch (error2) {
121475
- if (WorkflowAPIError.is(error2) && error2.status === 404) {
121875
+ if (WorkflowWorldError.is(error2) && error2.status === 404) {
121476
121876
  throw new HookNotFoundError(token);
121477
121877
  }
121478
121878
  throw error2;
121479
121879
  }
121480
121880
  }
121481
- const WORKFLOW_SERVER_SERVICE = {
121482
- peerService: "workflow-server",
121483
- rpcSystem: "http",
121484
- rpcService: "workflow-server"
121485
- };
121486
- function extractEventType(args) {
121487
- if (args.length >= 2 && typeof args[1] === "object" && args[1] !== null) {
121488
- const data = args[1];
121489
- if (typeof data.eventType === "string") {
121490
- return data.eventType;
121491
- }
121492
- }
121493
- return void 0;
121494
- }
121495
- function instrumentObject(prefix, o) {
121496
- const handlers2 = {};
121497
- for (const key of Object.keys(o)) {
121498
- if (typeof o[key] !== "function") {
121499
- handlers2[key] = o[key];
121500
- } else {
121501
- const f2 = o[key];
121502
- const methodName = String(key);
121503
- handlers2[key] = async (...args) => {
121504
- let spanName2 = `${prefix}.${methodName}`;
121505
- if (prefix === "world.events" && methodName === "create") {
121506
- const eventType = extractEventType(args);
121507
- if (eventType) {
121508
- spanName2 = `${prefix}.${methodName} ${eventType}`;
121509
- }
121510
- }
121511
- return trace(spanName2, { kind: await getSpanKind("CLIENT") }, async (span) => {
121512
- span == null ? void 0 : span.setAttributes({
121513
- ...PeerService(WORKFLOW_SERVER_SERVICE.peerService),
121514
- ...RpcSystem(WORKFLOW_SERVER_SERVICE.rpcSystem),
121515
- ...RpcService(WORKFLOW_SERVER_SERVICE.rpcService),
121516
- ...RpcMethod(spanName2)
121517
- });
121518
- return f2(...args);
121519
- });
121520
- };
121521
- }
121522
- }
121523
- return handlers2;
121524
- }
121525
121881
  function createStorage(config2) {
121526
121882
  const storage = {
121527
121883
  // Storage interface with namespaced methods
@@ -121578,6 +121934,19 @@ function encodeMultiChunks(chunks) {
121578
121934
  }
121579
121935
  return result;
121580
121936
  }
121937
+ const StreamInfoResponseSchema = object$1({
121938
+ tailIndex: number$1(),
121939
+ done: boolean$1()
121940
+ });
121941
+ const StreamChunksResponseSchema = object$1({
121942
+ data: array$1(object$1({
121943
+ index: number$1(),
121944
+ data: _instanceof(Uint8Array)
121945
+ })),
121946
+ cursor: string$1().nullable(),
121947
+ hasMore: boolean$1(),
121948
+ done: boolean$1()
121949
+ });
121581
121950
  function createStreamer(config2) {
121582
121951
  return {
121583
121952
  async writeToStream(name2, runId, chunk) {
@@ -121631,6 +122000,30 @@ function createStreamer(config2) {
121631
122000
  }
121632
122001
  return response2.body;
121633
122002
  },
122003
+ async getStreamChunks(name2, runId, options) {
122004
+ const params = new URLSearchParams();
122005
+ if ((options == null ? void 0 : options.limit) != null) {
122006
+ params.set("limit", String(options.limit));
122007
+ }
122008
+ if (options == null ? void 0 : options.cursor) {
122009
+ params.set("cursor", options.cursor);
122010
+ }
122011
+ const qs = params.toString();
122012
+ const endpoint = `/v2/runs/${encodeURIComponent(runId)}/streams/${encodeURIComponent(name2)}/chunks${qs ? `?${qs}` : ""}`;
122013
+ return makeRequest({
122014
+ endpoint,
122015
+ config: config2,
122016
+ schema: StreamChunksResponseSchema
122017
+ });
122018
+ },
122019
+ async getStreamInfo(name2, runId) {
122020
+ const endpoint = `/v2/runs/${encodeURIComponent(runId)}/streams/${encodeURIComponent(name2)}/info`;
122021
+ return makeRequest({
122022
+ endpoint,
122023
+ config: config2,
122024
+ schema: StreamInfoResponseSchema
122025
+ });
122026
+ },
121634
122027
  async listStreamsByRunId(runId) {
121635
122028
  const httpConfig = await getHttpConfig(config2);
121636
122029
  const url2 = new URL(`${httpConfig.baseUrl}/v2/runs/${encodeURIComponent(runId)}/streams`);
@@ -121650,7 +122043,7 @@ function createVercelWorld(config2) {
121650
122043
  return {
121651
122044
  ...createQueue$1(config2),
121652
122045
  ...createStorage(config2),
121653
- ...createStreamer(config2),
122046
+ ...instrumentObject("world.streams", createStreamer(config2)),
121654
122047
  getEncryptionKeyForRun: createGetEncryptionKeyForRun(projectId, (_b = config2 == null ? void 0 : config2.projectConfig) == null ? void 0 : _b.teamId, config2 == null ? void 0 : config2.token),
121655
122048
  resolveLatestDeploymentId: createResolveLatestDeploymentId(config2)
121656
122049
  };
@@ -123092,6 +123485,11 @@ async function flushablePipe(source, sink, state) {
123092
123485
  }
123093
123486
  const contextStorage = /* @__PURE__ */ new AsyncLocalStorage();
123094
123487
  const registeredSteps = /* @__PURE__ */ new Map();
123488
+ const BUILTIN_RESPONSE_STEP_NAMES = /* @__PURE__ */ new Set([
123489
+ "__builtin_response_array_buffer",
123490
+ "__builtin_response_json",
123491
+ "__builtin_response_text"
123492
+ ]);
123095
123493
  function getStepIdAliasCandidates(stepId) {
123096
123494
  const parts = stepId.split("//");
123097
123495
  if (parts.length !== 3 || parts[0] !== "step") {
@@ -123120,6 +123518,17 @@ function getStepIdAliasCandidates(stepId) {
123120
123518
  }
123121
123519
  return Array.from(modulePathAliases, (aliasModulePath) => `step//${aliasModulePath}//${fnName}`);
123122
123520
  }
123521
+ function getBuiltinResponseStepAlias(stepId) {
123522
+ if (!BUILTIN_RESPONSE_STEP_NAMES.has(stepId)) {
123523
+ return void 0;
123524
+ }
123525
+ for (const [registeredStepId, stepFn] of registeredSteps.entries()) {
123526
+ if (registeredStepId.endsWith(`//${stepId}`)) {
123527
+ return stepFn;
123528
+ }
123529
+ }
123530
+ return void 0;
123531
+ }
123123
123532
  function getStepFunction(stepId) {
123124
123533
  const directMatch = registeredSteps.get(stepId);
123125
123534
  if (directMatch) {
@@ -123131,6 +123540,10 @@ function getStepFunction(stepId) {
123131
123540
  return aliasMatch;
123132
123541
  }
123133
123542
  }
123543
+ const builtinAliasMatch = getBuiltinResponseStepAlias(stepId);
123544
+ if (builtinAliasMatch) {
123545
+ return builtinAliasMatch;
123546
+ }
123134
123547
  return void 0;
123135
123548
  }
123136
123549
  const SerializationFormat = {
@@ -123371,12 +123784,21 @@ class WorkflowServerWritableStream extends WritableStream {
123371
123784
  }
123372
123785
  buffer = [];
123373
123786
  };
123787
+ let flushWaiters = [];
123374
123788
  const scheduleFlush = () => {
123375
123789
  if (flushTimer)
123376
123790
  return;
123377
123791
  flushTimer = setTimeout(() => {
123378
123792
  flushTimer = null;
123379
- flushPromise = flush();
123793
+ const currentWaiters = flushWaiters;
123794
+ flushWaiters = [];
123795
+ flushPromise = flush().then(() => {
123796
+ for (const w2 of currentWaiters)
123797
+ w2.resolve();
123798
+ }, (err) => {
123799
+ for (const w2 of currentWaiters)
123800
+ w2.reject(err);
123801
+ });
123380
123802
  }, STREAM_FLUSH_INTERVAL_MS);
123381
123803
  };
123382
123804
  super({
@@ -123387,6 +123809,9 @@ class WorkflowServerWritableStream extends WritableStream {
123387
123809
  }
123388
123810
  buffer.push(chunk);
123389
123811
  scheduleFlush();
123812
+ await new Promise((resolve2, reject) => {
123813
+ flushWaiters.push({ resolve: resolve2, reject });
123814
+ });
123390
123815
  },
123391
123816
  async close() {
123392
123817
  if (flushPromise) {
@@ -123396,12 +123821,17 @@ class WorkflowServerWritableStream extends WritableStream {
123396
123821
  await flush();
123397
123822
  await world.closeStream(name2, runId);
123398
123823
  },
123399
- abort() {
123824
+ abort(reason) {
123400
123825
  if (flushTimer) {
123401
123826
  clearTimeout(flushTimer);
123402
123827
  flushTimer = null;
123403
123828
  }
123404
123829
  buffer = [];
123830
+ const waiters = flushWaiters;
123831
+ flushWaiters = [];
123832
+ const abortError = reason ?? new Error("Stream aborted");
123833
+ for (const w2 of waiters)
123834
+ w2.reject(abortError);
123405
123835
  }
123406
123836
  });
123407
123837
  }
@@ -124871,7 +125301,7 @@ async function resumeHook$2(tokenOrHook, payload, encryptionKeyOverride) {
124871
125301
  });
124872
125302
  });
124873
125303
  }
124874
- const version = "4.2.0-beta.71";
125304
+ const version = "4.2.0-beta.73";
124875
125305
  const ulid = monotonicFactory();
124876
125306
  async function start$1(workflow, argsOrOptions, options) {
124877
125307
  return await waitedUntil(() => {
@@ -125037,7 +125467,7 @@ async function wakeUpRun$2(world, runId, options) {
125037
125467
  await world.events.create(runId, eventData, { v1Compat: compatMode });
125038
125468
  stoppedCount++;
125039
125469
  } catch (err) {
125040
- if (WorkflowAPIError.is(err) && err.status === 409) {
125470
+ if (EntityConflictError.is(err)) {
125041
125471
  stoppedCount++;
125042
125472
  } else {
125043
125473
  errors2.push(err instanceof Error ? err : new Error(String(err)));
@@ -125178,17 +125608,30 @@ class Run {
125178
125608
  * Retrieves the workflow run's default readable stream, which reads chunks
125179
125609
  * written to the corresponding writable stream {@link getWritable}.
125180
125610
  *
125611
+ * The returned stream has an additional {@link WorkflowReadableStream.getTailIndex | getTailIndex()}
125612
+ * helper that returns the index of the last known chunk. This is useful when
125613
+ * building reconnection endpoints that need to inform clients where the
125614
+ * stream starts.
125615
+ *
125181
125616
  * @param options - The options for the readable stream.
125182
- * @returns The `ReadableStream` for the workflow run.
125617
+ * @returns A `WorkflowReadableStream` for the workflow run.
125183
125618
  */
125184
125619
  getReadable(options = {}) {
125185
125620
  const { ops = [], global: global2 = globalThis, startIndex, namespace: namespace2 } = options;
125186
125621
  const name2 = getWorkflowRunStreamId(this.runId, namespace2);
125187
125622
  const encryptionKey = this.getEncryptionKey();
125188
- return getExternalRevivers(global2, ops, this.runId, encryptionKey).ReadableStream({
125623
+ const stream = getExternalRevivers(global2, ops, this.runId, encryptionKey).ReadableStream({
125189
125624
  name: name2,
125190
125625
  startIndex
125191
125626
  });
125627
+ const world = this.world;
125628
+ const runId = this.runId;
125629
+ return Object.assign(stream, {
125630
+ getTailIndex: async () => {
125631
+ const info = await world.getStreamInfo(name2, runId);
125632
+ return info.tailIndex;
125633
+ }
125634
+ });
125192
125635
  }
125193
125636
  /**
125194
125637
  * Polls the workflow return value every 1 second until it is completed.
@@ -125229,6 +125672,41 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125229
125672
  }
125230
125673
  const { workflowName, workflowRunId, workflowStartedAt, stepId, traceCarrier: traceContext, requestedAt } = StepInvokePayloadSchema.parse(message_);
125231
125674
  const { requestId } = metadata;
125675
+ if (metadata.attempt > MAX_QUEUE_DELIVERIES) {
125676
+ runtimeLogger.error(`Step handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, {
125677
+ workflowRunId,
125678
+ stepId,
125679
+ stepName: metadata.queueName.slice("__wkf_step_".length),
125680
+ attempt: metadata.attempt
125681
+ });
125682
+ try {
125683
+ const world = getWorld();
125684
+ await world.events.create(workflowRunId, {
125685
+ eventType: "step_failed",
125686
+ specVersion: SPEC_VERSION_CURRENT,
125687
+ correlationId: stepId,
125688
+ eventData: {
125689
+ error: `Step exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`
125690
+ }
125691
+ }, { requestId });
125692
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
125693
+ runId: workflowRunId,
125694
+ traceCarrier: await serializeTraceCarrier(),
125695
+ requestedAt: /* @__PURE__ */ new Date()
125696
+ });
125697
+ } catch (err) {
125698
+ if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
125699
+ return;
125700
+ }
125701
+ runtimeLogger.error(`Failed to mark step as failed after ${metadata.attempt} delivery attempts. A persistent error is preventing the step from being terminated. The run will remain in its current state until manually resolved. This is most likely due to a persistent outage of the workflow backend or a bug in the workflow runtime and should be reported to the Workflow team.`, {
125702
+ workflowRunId,
125703
+ stepId,
125704
+ attempt: metadata.attempt,
125705
+ error: err instanceof Error ? err.message : String(err)
125706
+ });
125707
+ }
125708
+ return;
125709
+ }
125232
125710
  const spanLinks = await linkToCurrentContext();
125233
125711
  return await withTraceContext(traceContext, async () => {
125234
125712
  const stepName = metadata.queueName.slice("__wkf_step_".length);
@@ -125239,7 +125717,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125239
125717
  getSpanKind$2("CONSUMER")
125240
125718
  ]);
125241
125719
  return trace$2(`STEP ${stepName}`, { kind: spanKind, links: spanLinks }, async (span) => {
125242
- var _a3, _b, _c, _d, _e2, _f, _g;
125720
+ var _a3, _b, _c, _d, _e2, _f;
125243
125721
  span == null ? void 0 : span.setAttributes({
125244
125722
  ...StepName(stepName),
125245
125723
  ...StepAttempt(metadata.attempt),
@@ -125251,18 +125729,10 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125251
125729
  ...getQueueOverhead({ requestedAt })
125252
125730
  });
125253
125731
  const stepFn = getStepFunction(stepName);
125254
- if (!stepFn) {
125255
- throw new Error(`Step "${stepName}" not found`);
125256
- }
125257
- if (typeof stepFn !== "function") {
125258
- throw new Error(`Step "${stepName}" is not a function (got ${typeof stepFn})`);
125259
- }
125260
- const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
125261
125732
  span == null ? void 0 : span.setAttributes({
125262
125733
  ...WorkflowName(workflowName),
125263
125734
  ...WorkflowRunId(workflowRunId),
125264
125735
  ...StepId(stepId),
125265
- ...StepMaxRetries(maxRetries),
125266
125736
  ...StepTracePropagated(!!traceContext)
125267
125737
  });
125268
125738
  let step;
@@ -125277,62 +125747,56 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125277
125747
  }
125278
125748
  step = startResult.step;
125279
125749
  } catch (err) {
125280
- if (WorkflowAPIError.is(err)) {
125281
- if (err.status === 429) {
125282
- const retryRetryAfter = Math.max(1, typeof err.retryAfter === "number" ? err.retryAfter : 1);
125283
- runtimeLogger.info("Throttled again on retry, deferring to queue", {
125284
- retryAfterSeconds: retryRetryAfter
125285
- });
125286
- return { timeoutSeconds: retryRetryAfter };
125287
- }
125288
- if (err.status === 410) {
125289
- runtimeLogger.info(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
125290
- return;
125291
- }
125292
- if (err.status === 409) {
125293
- runtimeLogger.debug("Step in terminal state, re-enqueuing workflow", {
125294
- stepName,
125295
- stepId,
125296
- workflowRunId,
125297
- error: err.message
125298
- });
125299
- span == null ? void 0 : span.setAttributes({
125300
- ...StepSkipped(true),
125301
- // Use 'completed' as a representative terminal state for the skip reason
125302
- ...StepSkipReason("completed")
125303
- });
125304
- (_a3 = span == null ? void 0 : span.addEvent) == null ? void 0 : _a3.call(span, "step.skipped", {
125305
- "skip.reason": "terminal_state",
125306
- "step.name": stepName,
125307
- "step.id": stepId
125308
- });
125309
- await queueMessage(world, getWorkflowQueueName(workflowName), {
125310
- runId: workflowRunId,
125311
- traceCarrier: await serializeTraceCarrier(),
125312
- requestedAt: /* @__PURE__ */ new Date()
125313
- });
125314
- return;
125315
- }
125316
- if (err.status === 425) {
125317
- const retryAfterStr = (_b = err.meta) == null ? void 0 : _b.retryAfter;
125318
- const retryAfter = retryAfterStr ? new Date(retryAfterStr) : new Date(Date.now() + 1e3);
125319
- const timeoutSeconds = Math.max(1, Math.ceil((retryAfter.getTime() - Date.now()) / 1e3));
125320
- span == null ? void 0 : span.setAttributes({
125321
- ...StepRetryTimeoutSeconds(timeoutSeconds)
125322
- });
125323
- (_c = span == null ? void 0 : span.addEvent) == null ? void 0 : _c.call(span, "step.delayed", {
125324
- "delay.reason": "retry_after_not_reached",
125325
- "delay.timeout_seconds": timeoutSeconds,
125326
- "delay.retry_after": retryAfter.toISOString()
125327
- });
125328
- runtimeLogger.debug("Step retryAfter timestamp not yet reached", {
125329
- stepName,
125330
- stepId,
125331
- retryAfter,
125332
- timeoutSeconds
125333
- });
125334
- return { timeoutSeconds };
125335
- }
125750
+ if (ThrottleError.is(err)) {
125751
+ const retryRetryAfter = Math.max(1, typeof err.retryAfter === "number" ? err.retryAfter : 1);
125752
+ runtimeLogger.info("Throttled again on retry, deferring to queue", {
125753
+ retryAfterSeconds: retryRetryAfter
125754
+ });
125755
+ return { timeoutSeconds: retryRetryAfter };
125756
+ }
125757
+ if (RunExpiredError.is(err)) {
125758
+ runtimeLogger.info(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
125759
+ return;
125760
+ }
125761
+ if (EntityConflictError.is(err)) {
125762
+ runtimeLogger.debug("Step in terminal state, re-enqueuing workflow", {
125763
+ stepName,
125764
+ stepId,
125765
+ workflowRunId,
125766
+ error: err.message
125767
+ });
125768
+ span == null ? void 0 : span.setAttributes({
125769
+ ...StepSkipped(true),
125770
+ ...StepSkipReason("completed")
125771
+ });
125772
+ (_a3 = span == null ? void 0 : span.addEvent) == null ? void 0 : _a3.call(span, "step.skipped", {
125773
+ "skip.reason": "terminal_state",
125774
+ "step.name": stepName,
125775
+ "step.id": stepId
125776
+ });
125777
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
125778
+ runId: workflowRunId,
125779
+ traceCarrier: await serializeTraceCarrier(),
125780
+ requestedAt: /* @__PURE__ */ new Date()
125781
+ });
125782
+ return;
125783
+ }
125784
+ if (TooEarlyError.is(err)) {
125785
+ const timeoutSeconds = Math.max(1, err.retryAfter ?? 1);
125786
+ span == null ? void 0 : span.setAttributes({
125787
+ ...StepRetryTimeoutSeconds(timeoutSeconds)
125788
+ });
125789
+ (_b = span == null ? void 0 : span.addEvent) == null ? void 0 : _b.call(span, "step.delayed", {
125790
+ "delay.reason": "retry_after_not_reached",
125791
+ "delay.timeout_seconds": timeoutSeconds
125792
+ });
125793
+ runtimeLogger.debug("Step retryAfter timestamp not yet reached", {
125794
+ stepName,
125795
+ stepId,
125796
+ retryAfterSeconds: err.retryAfter,
125797
+ timeoutSeconds
125798
+ });
125799
+ return { timeoutSeconds };
125336
125800
  }
125337
125801
  throw err;
125338
125802
  }
@@ -125345,6 +125809,51 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125345
125809
  span == null ? void 0 : span.setAttributes({
125346
125810
  ...StepStatus(step.status)
125347
125811
  });
125812
+ if (!stepFn || typeof stepFn !== "function") {
125813
+ const err = new StepNotRegisteredError(stepName);
125814
+ runtimeLogger.error("Step function not registered, failing step (not run)", {
125815
+ workflowRunId,
125816
+ stepName,
125817
+ stepId,
125818
+ error: err.message
125819
+ });
125820
+ try {
125821
+ await world.events.create(workflowRunId, {
125822
+ eventType: "step_failed",
125823
+ specVersion: SPEC_VERSION_CURRENT,
125824
+ correlationId: stepId,
125825
+ eventData: {
125826
+ error: err.message,
125827
+ stack: err.stack
125828
+ }
125829
+ }, { requestId });
125830
+ } catch (stepFailErr) {
125831
+ if (EntityConflictError.is(stepFailErr)) {
125832
+ runtimeLogger.info("Tried failing step for missing function, but step has already finished.", {
125833
+ workflowRunId,
125834
+ stepId,
125835
+ stepName,
125836
+ message: stepFailErr.message
125837
+ });
125838
+ return;
125839
+ }
125840
+ throw stepFailErr;
125841
+ }
125842
+ span == null ? void 0 : span.setAttributes({
125843
+ ...StepStatus("failed"),
125844
+ ...StepFatalError(true)
125845
+ });
125846
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
125847
+ runId: workflowRunId,
125848
+ traceCarrier: await serializeTraceCarrier(),
125849
+ requestedAt: /* @__PURE__ */ new Date()
125850
+ });
125851
+ return;
125852
+ }
125853
+ const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
125854
+ span == null ? void 0 : span.setAttributes({
125855
+ ...StepMaxRetries(maxRetries)
125856
+ });
125348
125857
  let result;
125349
125858
  if (step.attempt > maxRetries + 1) {
125350
125859
  const retryCount = step.attempt - 1;
@@ -125361,11 +125870,11 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125361
125870
  correlationId: stepId,
125362
125871
  eventData: {
125363
125872
  error: errorMessage,
125364
- stack: (_d = step.error) == null ? void 0 : _d.stack
125873
+ stack: (_c = step.error) == null ? void 0 : _c.stack
125365
125874
  }
125366
125875
  }, { requestId });
125367
125876
  } catch (err) {
125368
- if (WorkflowAPIError.is(err) && err.status === 409) {
125877
+ if (EntityConflictError.is(err)) {
125369
125878
  runtimeLogger.info("Tried failing step, but step has already finished.", {
125370
125879
  workflowRunId,
125371
125880
  stepId,
@@ -125406,7 +125915,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125406
125915
  }
125407
125916
  }, { requestId });
125408
125917
  } catch (failErr) {
125409
- if (WorkflowAPIError.is(failErr) && failErr.status === 409) {
125918
+ if (EntityConflictError.is(failErr)) {
125410
125919
  return;
125411
125920
  }
125412
125921
  throw failErr;
@@ -125420,7 +125929,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125420
125929
  }
125421
125930
  const stepStartedAt = step.startedAt;
125422
125931
  const ops = [];
125423
- const rawKey = await ((_e2 = world.getEncryptionKeyForRun) == null ? void 0 : _e2.call(world, workflowRunId));
125932
+ const rawKey = await ((_d = world.getEncryptionKeyForRun) == null ? void 0 : _d.call(world, workflowRunId));
125424
125933
  const encryptionKey = rawKey ? await importKey(rawKey) : void 0;
125425
125934
  const hydratedInput = await trace$2("step.hydrate", {}, async (hydrateSpan) => {
125426
125935
  const startTime = Date.now();
@@ -125469,15 +125978,15 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125469
125978
  });
125470
125979
  if (userCodeFailed) {
125471
125980
  const err = userCodeError;
125472
- if (WorkflowAPIError.is(err)) {
125473
- if (err.status === 410) {
125474
- stepLogger.info("Workflow run already completed, skipping step", {
125475
- workflowRunId,
125476
- stepId,
125477
- message: err.message
125478
- });
125479
- return;
125480
- }
125981
+ if (RunExpiredError.is(err)) {
125982
+ stepLogger.info("Workflow run already completed, skipping step", {
125983
+ workflowRunId,
125984
+ stepId,
125985
+ message: err.message
125986
+ });
125987
+ return;
125988
+ }
125989
+ if (WorkflowWorldError.is(err)) {
125481
125990
  if (err.status !== void 0 && err.status >= 500) {
125482
125991
  throw err;
125483
125992
  }
@@ -125485,7 +125994,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125485
125994
  const normalizedError = await normalizeUnknownError(err);
125486
125995
  const normalizedStack = normalizedError.stack || getErrorStack(err) || "";
125487
125996
  if (err instanceof Error) {
125488
- (_f = span == null ? void 0 : span.recordException) == null ? void 0 : _f.call(span, err);
125997
+ (_e2 = span == null ? void 0 : span.recordException) == null ? void 0 : _e2.call(span, err);
125489
125998
  }
125490
125999
  const isFatal = FatalError.is(err);
125491
126000
  const isRetryable = RetryableError.is(err);
@@ -125514,7 +126023,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125514
126023
  }
125515
126024
  }, { requestId });
125516
126025
  } catch (stepFailErr) {
125517
- if (WorkflowAPIError.is(stepFailErr) && stepFailErr.status === 409) {
126026
+ if (EntityConflictError.is(stepFailErr)) {
125518
126027
  runtimeLogger.info("Tried failing step, but step has already finished.", {
125519
126028
  workflowRunId,
125520
126029
  stepId,
@@ -125557,7 +126066,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125557
126066
  }
125558
126067
  }, { requestId });
125559
126068
  } catch (stepFailErr) {
125560
- if (WorkflowAPIError.is(stepFailErr) && stepFailErr.status === 409) {
126069
+ if (EntityConflictError.is(stepFailErr)) {
125561
126070
  runtimeLogger.info("Tried failing step, but step has already finished.", {
125562
126071
  workflowRunId,
125563
126072
  stepId,
@@ -125602,7 +126111,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125602
126111
  }
125603
126112
  }, { requestId });
125604
126113
  } catch (stepRetryErr) {
125605
- if (WorkflowAPIError.is(stepRetryErr) && stepRetryErr.status === 409) {
126114
+ if (EntityConflictError.is(stepRetryErr)) {
125606
126115
  runtimeLogger.info("Tried retrying step, but step has already finished.", {
125607
126116
  workflowRunId,
125608
126117
  stepId,
@@ -125618,7 +126127,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125618
126127
  ...StepRetryTimeoutSeconds(timeoutSeconds),
125619
126128
  ...StepRetryWillRetry(true)
125620
126129
  });
125621
- (_g = span == null ? void 0 : span.addEvent) == null ? void 0 : _g.call(span, "retry.scheduled", {
126130
+ (_f = span == null ? void 0 : span.addEvent) == null ? void 0 : _f.call(span, "retry.scheduled", {
125622
126131
  "retry.timeout_seconds": timeoutSeconds,
125623
126132
  "retry.attempt": currentAttempt,
125624
126133
  "retry.max_retries": maxRetries2
@@ -125658,7 +126167,7 @@ getWorldHandlers().createQueueHandler("__wkf_step_", async (message_, metadata)
125658
126167
  result
125659
126168
  }
125660
126169
  }, { requestId }).catch((err) => {
125661
- if (WorkflowAPIError.is(err) && err.status === 409) {
126170
+ if (EntityConflictError.is(err)) {
125662
126171
  runtimeLogger.info("Tried completing step, but step has already finished.", {
125663
126172
  workflowRunId,
125664
126173
  stepId,
@@ -126033,7 +126542,7 @@ async function getWorldFromEnv(userEnvMap) {
126033
126542
  function createServerActionError(error2, operation, requestParams) {
126034
126543
  const err = error2 instanceof Error ? error2 : new Error(String(error2));
126035
126544
  let errorResponse;
126036
- if (WorkflowAPIError.is(error2)) {
126545
+ if (WorkflowWorldError.is(error2)) {
126037
126546
  const status = error2.status ?? 500;
126038
126547
  const isClientError = status >= 400 && status < 500;
126039
126548
  if (!isClientError) {
@@ -126376,7 +126885,7 @@ async function fetchWorkflowsManifest(_worldEnv) {
126376
126885
  }
126377
126886
  for (const manifestPath of manifestPaths) {
126378
126887
  try {
126379
- const content2 = await require$$0$8.readFile(manifestPath, "utf-8");
126888
+ const content2 = await fs$1.readFile(manifestPath, "utf-8");
126380
126889
  const manifest = JSON.parse(content2);
126381
126890
  return createResponse(manifest);
126382
126891
  } catch (_err) {
@@ -132197,12 +132706,17 @@ function useWorkflowResourceData(env2, resource, resourceId, options = {}) {
132197
132706
  async (resource2) => encryptionKey ? hydrateResourceIOWithKey(resource2, encryptionKey) : hydrateResourceIO(resource2),
132198
132707
  [encryptionKey]
132199
132708
  );
132709
+ const prevSelectionRef = reactExports.useRef("");
132200
132710
  const fetchData = reactExports.useCallback(async () => {
132201
132711
  if (!enabled) {
132202
132712
  setLoading(false);
132203
132713
  return;
132204
132714
  }
132205
- setData(null);
132715
+ const selectionKey = `${resource}:${resourceId}`;
132716
+ if (selectionKey !== prevSelectionRef.current) {
132717
+ setData(null);
132718
+ prevSelectionRef.current = selectionKey;
132719
+ }
132206
132720
  setError(null);
132207
132721
  setLoading(true);
132208
132722
  if (resource === "hook") {
@@ -134533,6 +135047,12 @@ function SelectionBar({
134533
135047
  }
134534
135048
  );
134535
135049
  }
135050
+ function getErrorCode(error2) {
135051
+ if (error2 !== null && typeof error2 === "object" && "code" in error2 && typeof error2.code === "string") {
135052
+ return error2.code;
135053
+ }
135054
+ return void 0;
135055
+ }
134536
135056
  function StatusBadge({
134537
135057
  status,
134538
135058
  context,
@@ -134571,41 +135091,41 @@ function StatusBadge({
134571
135091
  ")"
134572
135092
  ] })
134573
135093
  ] });
134574
- if (status === "failed" && (context == null ? void 0 : context.error)) {
134575
- return /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorStatusBadge, { content: content2, error: context.error });
135094
+ const errorCode = status === "failed" ? getErrorCode(context == null ? void 0 : context.error) : void 0;
135095
+ if (errorCode) {
135096
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorCodeBadge, { content: content2, errorCode });
134576
135097
  }
134577
135098
  return content2;
134578
135099
  }
134579
- function ErrorStatusBadge({
135100
+ function ErrorCodeBadge({
134580
135101
  content: content2,
134581
- error: error2
135102
+ errorCode
134582
135103
  }) {
134583
135104
  const [copied, setCopied] = reactExports.useState(false);
134584
- const errorMessage = typeof error2 === "string" ? error2 : error2 instanceof Error ? error2.message : JSON.stringify(error2);
134585
135105
  const handleCopy = async (e) => {
134586
135106
  e.stopPropagation();
134587
- await navigator.clipboard.writeText(errorMessage);
134588
- setCopied(true);
134589
- setTimeout(() => setCopied(false), 2e3);
135107
+ try {
135108
+ await navigator.clipboard.writeText(errorCode);
135109
+ setCopied(true);
135110
+ setTimeout(() => setCopied(false), 2e3);
135111
+ } catch {
135112
+ }
134590
135113
  };
134591
135114
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
134592
135115
  /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "cursor-help", children: content2 }) }),
134593
- /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContent, { className: "max-w-md p-0", children: [
134594
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2 p-1 border-b", children: [
134595
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium pl-1 pt-1", children: "Error Details" }),
134596
- /* @__PURE__ */ jsxRuntimeExports.jsx(
134597
- Button,
134598
- {
134599
- variant: "ghost",
134600
- size: "icon",
134601
- className: "h-6 w-6 shrink-0",
134602
- onClick: handleCopy,
134603
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-2.5 w-2.5 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-2.5 w-2.5 text-muted-foreground" })
134604
- }
134605
- )
134606
- ] }),
134607
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-48 overflow-auto p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs whitespace-pre-wrap break-words font-mono", children: errorMessage }) })
134608
- ] })
135116
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { className: "p-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 p-1.5", children: [
135117
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-mono", children: errorCode }),
135118
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
135119
+ Button,
135120
+ {
135121
+ variant: "ghost",
135122
+ size: "icon",
135123
+ className: "h-5 w-5 shrink-0",
135124
+ onClick: handleCopy,
135125
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-2.5 w-2.5 text-muted-foreground" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-2.5 w-2.5 text-muted-foreground" })
135126
+ }
135127
+ )
135128
+ ] }) })
134609
135129
  ] });
134610
135130
  }
134611
135131
  function useRunActions({
@@ -145200,17 +145720,12 @@ const baseNodeTypes = {
145200
145720
  parallelGroup: ParallelGroupComponent,
145201
145721
  diamondNode: DiamondNodeComponent
145202
145722
  };
145203
- const nodeTypes$1 = baseNodeTypes;
145723
+ const nodeTypes = baseNodeTypes;
145204
145724
  const defaultSelfLoopStyle = {
145205
145725
  strokeColor: "#6b7280",
145206
145726
  // gray-500
145207
145727
  labelBgClass: "bg-gray-200 dark:bg-gray-700 text-black dark:text-gray-200 border-gray-400 dark:border-gray-500"
145208
145728
  };
145209
- const executionSelfLoopStyle = {
145210
- strokeColor: "#a855f7",
145211
- // purple-500
145212
- labelBgClass: "bg-purple-200 dark:bg-purple-900/50 text-black dark:text-purple-200 border-purple-400 dark:border-purple-600"
145213
- };
145214
145729
  function createSelfLoopEdge(style2 = defaultSelfLoopStyle) {
145215
145730
  return function SelfLoopEdge2({
145216
145731
  id: id2,
@@ -145266,14 +145781,9 @@ function createSelfLoopEdge(style2 = defaultSelfLoopStyle) {
145266
145781
  };
145267
145782
  }
145268
145783
  const SelfLoopEdge = createSelfLoopEdge(defaultSelfLoopStyle);
145269
- const edgeTypes$1 = {
145784
+ const edgeTypes = {
145270
145785
  selfLoop: SelfLoopEdge
145271
145786
  };
145272
- function createEdgeTypes(selfLoopStyle = defaultSelfLoopStyle) {
145273
- return {
145274
- selfLoop: createSelfLoopEdge(selfLoopStyle)
145275
- };
145276
- }
145277
145787
  function getNodeBackgroundColor(nodeKind) {
145278
145788
  if (nodeKind === "workflow_start" || nodeKind === "workflow_end") {
145279
145789
  return "var(--node-bg-start)";
@@ -145506,7 +146016,7 @@ function consolidateEdges(edges, nodes) {
145506
146016
  }
145507
146017
  return consolidatedEdges;
145508
146018
  }
145509
- function convertToReactFlowNodes$1(workflow) {
146019
+ function convertToReactFlowNodes(workflow) {
145510
146020
  var _a3;
145511
146021
  const { nodes, groupNodes } = calculateEnhancedLayout(workflow);
145512
146022
  const nodeToParent = /* @__PURE__ */ new Map();
@@ -145632,7 +146142,7 @@ function convertToReactFlowNodes$1(workflow) {
145632
146142
  });
145633
146143
  return reactFlowNodes;
145634
146144
  }
145635
- function convertToReactFlowEdges$1(workflow) {
146145
+ function convertToReactFlowEdges(workflow) {
145636
146146
  const { additionalEdges } = calculateEnhancedLayout(workflow);
145637
146147
  const transformedOriginalEdges = workflow.edges.map((e) => {
145638
146148
  if (e.type === "loop") {
@@ -145735,18 +146245,18 @@ function convertToReactFlowEdges$1(workflow) {
145735
146245
  }
145736
146246
  function WorkflowGraphViewer({ workflow }) {
145737
146247
  const initialNodes = reactExports.useMemo(
145738
- () => convertToReactFlowNodes$1(workflow),
146248
+ () => convertToReactFlowNodes(workflow),
145739
146249
  [workflow]
145740
146250
  );
145741
146251
  const initialEdges = reactExports.useMemo(
145742
- () => convertToReactFlowEdges$1(workflow),
146252
+ () => convertToReactFlowEdges(workflow),
145743
146253
  [workflow]
145744
146254
  );
145745
146255
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
145746
146256
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
145747
146257
  reactExports.useEffect(() => {
145748
- setNodes(convertToReactFlowNodes$1(workflow));
145749
- setEdges(convertToReactFlowEdges$1(workflow));
146258
+ setNodes(convertToReactFlowNodes(workflow));
146259
+ setEdges(convertToReactFlowEdges(workflow));
145750
146260
  }, [workflow, setNodes, setEdges]);
145751
146261
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full w-full border rounded-lg bg-background relative overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
145752
146262
  index,
@@ -145755,8 +146265,8 @@ function WorkflowGraphViewer({ workflow }) {
145755
146265
  edges,
145756
146266
  onNodesChange,
145757
146267
  onEdgesChange,
145758
- nodeTypes: nodeTypes$1,
145759
- edgeTypes: edgeTypes$1,
146268
+ nodeTypes,
146269
+ edgeTypes,
145760
146270
  fitView: true,
145761
146271
  minZoom: 0.1,
145762
146272
  maxZoom: 2,
@@ -147697,732 +148207,63 @@ function BreadcrumbSeparator({
147697
148207
  }
147698
148208
  );
147699
148209
  }
147700
- const PRIMITIVE_LABELS = {
147701
- sleep: "sleep",
147702
- createHook: "createHook",
147703
- createWebhook: "createWebhook",
147704
- awaitWebhook: "awaitWebhook"
147705
- };
147706
- function normalizeStepName(name2) {
147707
- return name2.replace(/\/\/\.\.\//g, "//");
147708
- }
147709
- function createStepExecution(attemptStep, graphNodeId, idx, totalAttempts) {
147710
- let status;
147711
- switch (attemptStep.status) {
147712
- case "completed":
147713
- status = "completed";
147714
- break;
147715
- case "failed":
147716
- status = idx < totalAttempts - 1 ? "retrying" : "failed";
147717
- break;
147718
- case "running":
147719
- status = "running";
147720
- break;
147721
- case "cancelled":
147722
- status = "cancelled";
147723
- break;
147724
- case "pending":
147725
- default:
147726
- status = "pending";
147727
- break;
147728
- }
147729
- const duration2 = attemptStep.completedAt && attemptStep.startedAt ? new Date(attemptStep.completedAt).getTime() - new Date(attemptStep.startedAt).getTime() : void 0;
147730
- return {
147731
- nodeId: graphNodeId,
147732
- stepId: attemptStep.stepId,
147733
- attemptNumber: attemptStep.attempt,
147734
- status,
147735
- startedAt: attemptStep.startedAt ? new Date(attemptStep.startedAt).toISOString() : void 0,
147736
- completedAt: attemptStep.completedAt ? new Date(attemptStep.completedAt).toISOString() : void 0,
147737
- duration: duration2,
147738
- input: attemptStep.input,
147739
- output: attemptStep.output,
147740
- error: attemptStep.error ? {
147741
- message: attemptStep.error.message,
147742
- stack: attemptStep.error.stack || ""
147743
- } : void 0
147744
- };
147745
- }
147746
- function extractFunctionName(stepId) {
147747
- const parts = stepId.split("//");
147748
- return parts.length >= 3 ? parts[parts.length - 1] : null;
147749
- }
147750
- function buildNodeIndex(nodes) {
147751
- const byStepId = /* @__PURE__ */ new Map();
147752
- const byFunctionName = /* @__PURE__ */ new Map();
147753
- const primitivesByLabel = /* @__PURE__ */ new Map();
147754
- const agentNodes = [];
147755
- const toolNodes = /* @__PURE__ */ new Map();
147756
- for (const node2 of nodes) {
147757
- if (node2.data.stepId) {
147758
- const normalizedStepId = normalizeStepName(node2.data.stepId);
147759
- const existing = byStepId.get(normalizedStepId) || [];
147760
- existing.push(node2);
147761
- byStepId.set(normalizedStepId, existing);
147762
- const functionName = extractFunctionName(normalizedStepId);
147763
- if (functionName) {
147764
- const existingByName = byFunctionName.get(functionName) || [];
147765
- existingByName.push(node2);
147766
- byFunctionName.set(functionName, existingByName);
147767
- }
147768
- }
147769
- if (node2.data.nodeKind === "primitive") {
147770
- const label = node2.data.label;
147771
- const existing = primitivesByLabel.get(label) || [];
147772
- existing.push(node2);
147773
- primitivesByLabel.set(label, existing);
147774
- }
147775
- if (node2.data.nodeKind === "agent") {
147776
- agentNodes.push(node2);
147777
- }
147778
- if (node2.data.nodeKind === "tool") {
147779
- const label = node2.data.label;
147780
- const toolName = label.replace(/ \(tool\)$/, "");
147781
- const existing = toolNodes.get(toolName) || [];
147782
- existing.push(node2);
147783
- toolNodes.set(toolName, existing);
147784
- if (node2.data.stepId) {
147785
- const functionName = extractFunctionName(
147786
- normalizeStepName(node2.data.stepId)
147787
- );
147788
- if (functionName) {
147789
- const existingByName = toolNodes.get(functionName) || [];
147790
- if (!existingByName.includes(node2)) {
147791
- existingByName.push(node2);
147792
- toolNodes.set(functionName, existingByName);
147793
- }
147794
- }
147795
- }
147796
- }
147797
- }
147798
- return { byStepId, byFunctionName, primitivesByLabel, agentNodes, toolNodes };
147799
- }
147800
- function calculateEdgeTraversals(executionPath, graph, nodeExecutions) {
147801
- var _a3, _b, _c, _d;
147802
- const edgeTraversals = /* @__PURE__ */ new Map();
147803
- const executedNodes = new Set(executionPath);
147804
- const parallelGroups = /* @__PURE__ */ new Map();
147805
- for (const node2 of graph.nodes) {
147806
- const groupId = (_a3 = node2.metadata) == null ? void 0 : _a3.parallelGroupId;
147807
- if (groupId) {
147808
- const existing = parallelGroups.get(groupId) || { nodes: [] };
147809
- existing.nodes.push(node2);
147810
- existing.method = (_b = node2.metadata) == null ? void 0 : _b.parallelMethod;
147811
- parallelGroups.set(groupId, existing);
147812
- }
147813
- }
147814
- const raceWinners = /* @__PURE__ */ new Map();
147815
- for (const [groupId, group] of parallelGroups) {
147816
- if (group.method === "race") {
147817
- let winnerNodeId;
147818
- let earliestCompletion;
147819
- for (const node2 of group.nodes) {
147820
- const executions = nodeExecutions.get(node2.id);
147821
- if (executions) {
147822
- for (const exec of executions) {
147823
- if (exec.status === "completed" && exec.completedAt) {
147824
- const completedAt = new Date(exec.completedAt);
147825
- if (!earliestCompletion || completedAt < earliestCompletion) {
147826
- earliestCompletion = completedAt;
147827
- winnerNodeId = node2.id;
147828
- }
147829
- }
147830
- }
147831
- }
147832
- }
147833
- if (winnerNodeId) {
147834
- raceWinners.set(groupId, winnerNodeId);
147835
- }
147836
- }
147837
- }
147838
- const markEdgeTraversed = (edge) => {
147839
- const existing = edgeTraversals.get(edge.id);
147840
- if (existing) {
147841
- existing.traversalCount++;
147842
- } else {
147843
- edgeTraversals.set(edge.id, {
147844
- edgeId: edge.id,
147845
- traversalCount: 1,
147846
- timings: []
147847
- });
147848
- }
147849
- };
147850
- for (const edge of graph.edges) {
147851
- const sourceNode = graph.nodes.find((n) => n.id === edge.source);
147852
- const targetNode = graph.nodes.find((n) => n.id === edge.target);
147853
- if (!sourceNode || !targetNode) continue;
147854
- const sourceExecuted = executedNodes.has(edge.source);
147855
- const targetExecuted = executedNodes.has(edge.target);
147856
- if (!sourceExecuted && !targetExecuted) continue;
147857
- if (edge.type === "conditional") {
147858
- if (sourceExecuted && targetExecuted) {
147859
- markEdgeTraversed(edge);
147860
- }
147861
- continue;
147862
- }
147863
- const sourceGroupId = (_c = sourceNode.metadata) == null ? void 0 : _c.parallelGroupId;
147864
- const sourceMethod = (_d = sourceNode.metadata) == null ? void 0 : _d.parallelMethod;
147865
- if (sourceGroupId && sourceMethod === "race") {
147866
- const winner = raceWinners.get(sourceGroupId);
147867
- if (winner === edge.source && targetExecuted) {
147868
- markEdgeTraversed(edge);
147869
- }
147870
- } else if (sourceExecuted && targetExecuted) {
147871
- markEdgeTraversed(edge);
147872
- } else if (sourceExecuted && edge.type === "parallel") {
147873
- if (targetExecuted) {
147874
- markEdgeTraversed(edge);
147875
- }
147876
- }
147877
- }
147878
- return edgeTraversals;
147879
- }
147880
- function initializeStartNode(run, graph, executionPath, nodeExecutions) {
147881
- const startNode = graph.nodes.find(
147882
- (n) => n.data.nodeKind === "workflow_start"
147883
- );
147884
- if (startNode) {
147885
- executionPath.push(startNode.id);
147886
- nodeExecutions.set(startNode.id, [
147887
- {
147888
- nodeId: startNode.id,
147889
- attemptNumber: 1,
147890
- status: "completed",
147891
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
147892
- completedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0
147893
- // No duration for control flow nodes (start/end/conditional)
147894
- }
147895
- ]);
147896
- }
147897
- }
147898
- function addEndNodeExecution(run, graph, executionPath, nodeExecutions) {
147899
- const endNode = graph.nodes.find((n) => n.data.nodeKind === "workflow_end");
147900
- if (!endNode || executionPath.includes(endNode.id)) {
147901
- return;
147902
- }
147903
- let endNodeStatus;
147904
- switch (run.status) {
147905
- case "completed":
147906
- endNodeStatus = "completed";
147907
- break;
147908
- case "failed":
147909
- endNodeStatus = "failed";
147910
- break;
147911
- case "cancelled":
147912
- endNodeStatus = "cancelled";
147913
- break;
147914
- case "running":
147915
- endNodeStatus = "running";
147916
- break;
147917
- case "pending":
147918
- default:
147919
- return;
147920
- }
147921
- executionPath.push(endNode.id);
147922
- nodeExecutions.set(endNode.id, [
147923
- {
147924
- nodeId: endNode.id,
147925
- attemptNumber: 1,
147926
- status: endNodeStatus,
147927
- startedAt: run.completedAt ? new Date(run.completedAt).toISOString() : void 0,
147928
- completedAt: run.completedAt ? new Date(run.completedAt).toISOString() : void 0
147929
- // No duration for control flow nodes (start/end/conditional)
147930
- }
147931
- ]);
147932
- }
147933
- function processStepGroup(stepGroup, stepName, nodesByStepId, nodesByFunctionName, occurrenceCount, nodeExecutions, executionPath) {
147934
- const normalizedStepName = normalizeStepName(stepName);
147935
- const occurrenceIndex = occurrenceCount.get(normalizedStepName) || 0;
147936
- occurrenceCount.set(normalizedStepName, occurrenceIndex + 1);
147937
- let nodesWithStepId = nodesByStepId.get(normalizedStepName) || [];
147938
- let matchStrategy = "step-id";
147939
- if (nodesWithStepId.length === 0) {
147940
- const functionName = extractFunctionName(normalizedStepName);
147941
- if (functionName) {
147942
- nodesWithStepId = nodesByFunctionName.get(functionName) || [];
147943
- matchStrategy = "function-name";
147944
- }
147945
- }
147946
- const graphNode = nodesWithStepId.length === 1 ? nodesWithStepId[0] : nodesWithStepId[occurrenceIndex];
147947
- console.log("[Graph Mapper] Processing step group:", {
147948
- stepName,
147949
- normalizedStepName,
147950
- attempts: stepGroup.length,
147951
- occurrenceIndex,
147952
- totalNodesWithStepId: nodesWithStepId.length,
147953
- selectedNode: graphNode == null ? void 0 : graphNode.id,
147954
- allNodesWithStepId: nodesWithStepId.map((n) => n.id),
147955
- matchStrategy,
147956
- strategy: nodesWithStepId.length === 1 ? "single-node-multiple-invocations" : "occurrence-based"
147957
- });
147958
- if (!graphNode) {
147959
- return void 0;
147960
- }
147961
- const executions = stepGroup.map(
147962
- (attemptStep, idx) => createStepExecution(attemptStep, graphNode.id, idx, stepGroup.length)
147963
- );
147964
- if (nodesWithStepId.length === 1) {
147965
- const existing = nodeExecutions.get(graphNode.id) || [];
147966
- nodeExecutions.set(graphNode.id, [...existing, ...executions]);
147967
- } else {
147968
- nodeExecutions.set(graphNode.id, executions);
147969
- }
147970
- if (!executionPath.includes(graphNode.id)) {
147971
- executionPath.push(graphNode.id);
147972
- }
147973
- const latestExecution = executions[executions.length - 1];
147974
- return latestExecution.status === "running" ? graphNode.id : void 0;
147975
- }
147976
- function processPrimitiveEvents(events2, primitivesByLabel, nodeExecutions, executionPath) {
147977
- const occurrenceCount = /* @__PURE__ */ new Map();
147978
- const eventsByCorrelation = /* @__PURE__ */ new Map();
147979
- for (const event of events2) {
147980
- if (!event.correlationId) continue;
147981
- const existing = eventsByCorrelation.get(event.correlationId) || [];
147982
- existing.push(event);
147983
- eventsByCorrelation.set(event.correlationId, existing);
147984
- }
147985
- let currentNode;
147986
- const sleepNodes = primitivesByLabel.get(PRIMITIVE_LABELS.sleep) || [];
147987
- const sleepCorrelations = /* @__PURE__ */ new Set();
147988
- for (const event of events2) {
147989
- if (event.eventType === "wait_created" && event.correlationId) {
147990
- sleepCorrelations.add(event.correlationId);
147991
- }
147992
- }
147993
- const sortedSleepCorrelations = Array.from(sleepCorrelations).sort((a2, b2) => {
147994
- var _a3, _b;
147995
- const eventsA = eventsByCorrelation.get(a2) || [];
147996
- const eventsB = eventsByCorrelation.get(b2) || [];
147997
- const timeA = (_a3 = eventsA.find(
147998
- (e) => e.eventType === "wait_created"
147999
- )) == null ? void 0 : _a3.createdAt;
148000
- const timeB = (_b = eventsB.find(
148001
- (e) => e.eventType === "wait_created"
148002
- )) == null ? void 0 : _b.createdAt;
148003
- if (!timeA || !timeB) return 0;
148004
- return new Date(timeA).getTime() - new Date(timeB).getTime();
148005
- });
148006
- for (const correlationId of sortedSleepCorrelations) {
148007
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148008
- const createdEvent = correlationEvents.find(
148009
- (e) => e.eventType === "wait_created"
148010
- );
148011
- const completedEvent = correlationEvents.find(
148012
- (e) => e.eventType === "wait_completed"
148210
+ const FRAME_HEADER_SIZE = 4;
148211
+ const MAX_DISPLAY_ENTRIES = 200;
148212
+ const MAX_DISPLAY_DEPTH = 6;
148213
+ function sanitizeForDisplay(value, depth = 0) {
148214
+ if (value === null || value === void 0) return value;
148215
+ if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
148216
+ const ta2 = value;
148217
+ const name2 = ta2.constructor.name;
148218
+ const preview = Array.from(
148219
+ { length: Math.min(ta2.length, 8) },
148220
+ (_2, i) => ta2[i]
148013
148221
  );
148014
- if (!createdEvent) continue;
148015
- const occurrenceIndex = occurrenceCount.get(PRIMITIVE_LABELS.sleep) || 0;
148016
- occurrenceCount.set(PRIMITIVE_LABELS.sleep, occurrenceIndex + 1);
148017
- const graphNode = sleepNodes.length === 1 ? sleepNodes[0] : sleepNodes[occurrenceIndex];
148018
- if (!graphNode) continue;
148019
- let status = "running";
148020
- if (completedEvent) {
148021
- status = "completed";
148022
- }
148023
- const startedAt = new Date(createdEvent.createdAt).toISOString();
148024
- const completedAt = completedEvent ? new Date(completedEvent.createdAt).toISOString() : void 0;
148025
- const duration2 = completedEvent ? new Date(completedEvent.createdAt).getTime() - new Date(createdEvent.createdAt).getTime() : void 0;
148026
- const execution = {
148027
- nodeId: graphNode.id,
148028
- attemptNumber: 1,
148029
- status,
148030
- startedAt,
148031
- completedAt,
148032
- duration: duration2
148033
- };
148034
- const existing = nodeExecutions.get(graphNode.id) || [];
148035
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148036
- if (!executionPath.includes(graphNode.id)) {
148037
- executionPath.push(graphNode.id);
148038
- }
148039
- if (status === "running") {
148040
- currentNode = graphNode.id;
148041
- }
148222
+ const suffix = ta2.length > 8 ? ", …" : "";
148223
+ return `${name2}(${ta2.length}) [${preview.join(", ")}${suffix}]`;
148042
148224
  }
148043
- const hookNodes = [
148044
- ...primitivesByLabel.get(PRIMITIVE_LABELS.createHook) || [],
148045
- ...primitivesByLabel.get(PRIMITIVE_LABELS.createWebhook) || []
148046
- ];
148047
- const hookCorrelations = /* @__PURE__ */ new Set();
148048
- for (const event of events2) {
148049
- if (event.eventType === "hook_created" && event.correlationId) {
148050
- hookCorrelations.add(event.correlationId);
148051
- }
148225
+ if (value instanceof ArrayBuffer) {
148226
+ return `ArrayBuffer(${value.byteLength})`;
148052
148227
  }
148053
- const sortedHookCorrelations = Array.from(hookCorrelations).sort((a2, b2) => {
148054
- var _a3, _b;
148055
- const eventsA = eventsByCorrelation.get(a2) || [];
148056
- const eventsB = eventsByCorrelation.get(b2) || [];
148057
- const timeA = (_a3 = eventsA.find(
148058
- (e) => e.eventType === "hook_created"
148059
- )) == null ? void 0 : _a3.createdAt;
148060
- const timeB = (_b = eventsB.find(
148061
- (e) => e.eventType === "hook_created"
148062
- )) == null ? void 0 : _b.createdAt;
148063
- if (!timeA || !timeB) return 0;
148064
- return new Date(timeA).getTime() - new Date(timeB).getTime();
148065
- });
148066
- let hookOccurrenceIndex = 0;
148067
- for (const correlationId of sortedHookCorrelations) {
148068
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148069
- const createdEvent = correlationEvents.find(
148070
- (e) => e.eventType === "hook_created"
148071
- );
148072
- if (!createdEvent) continue;
148073
- const graphNode = hookNodes.length === 1 ? hookNodes[0] : hookNodes[hookOccurrenceIndex];
148074
- hookOccurrenceIndex++;
148075
- if (!graphNode) continue;
148076
- const status = "completed";
148077
- const startedAt = new Date(createdEvent.createdAt).toISOString();
148078
- const completedAt = new Date(createdEvent.createdAt).toISOString();
148079
- const execution = {
148080
- nodeId: graphNode.id,
148081
- attemptNumber: 1,
148082
- status,
148083
- startedAt,
148084
- completedAt,
148085
- duration: 0
148086
- };
148087
- const existing = nodeExecutions.get(graphNode.id) || [];
148088
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148089
- if (!executionPath.includes(graphNode.id)) {
148090
- executionPath.push(graphNode.id);
148091
- }
148092
- }
148093
- const awaitWebhookNodes = primitivesByLabel.get(PRIMITIVE_LABELS.awaitWebhook) || [];
148094
- const receivedHookCorrelations = /* @__PURE__ */ new Set();
148095
- for (const event of events2) {
148096
- if (event.eventType === "hook_received" && event.correlationId) {
148097
- receivedHookCorrelations.add(event.correlationId);
148098
- }
148099
- }
148100
- let awaitWebhookIndex = 0;
148101
- for (const correlationId of sortedHookCorrelations) {
148102
- const graphNode = awaitWebhookNodes.length === 1 ? awaitWebhookNodes[0] : awaitWebhookNodes[awaitWebhookIndex];
148103
- awaitWebhookIndex++;
148104
- if (!graphNode) continue;
148105
- const correlationEvents = eventsByCorrelation.get(correlationId) || [];
148106
- const createdEvent = correlationEvents.find(
148107
- (e) => e.eventType === "hook_created"
148108
- );
148109
- const receivedEvent = correlationEvents.find(
148110
- (e) => e.eventType === "hook_received"
148111
- );
148112
- let status;
148113
- let startedAt;
148114
- let completedAt;
148115
- let duration2 = 0;
148116
- if (receivedEvent) {
148117
- status = "completed";
148118
- startedAt = createdEvent ? new Date(createdEvent.createdAt).toISOString() : new Date(receivedEvent.createdAt).toISOString();
148119
- completedAt = new Date(receivedEvent.createdAt).toISOString();
148120
- duration2 = new Date(completedAt).getTime() - new Date(startedAt).getTime();
148121
- } else if (createdEvent) {
148122
- status = "running";
148123
- startedAt = new Date(createdEvent.createdAt).toISOString();
148124
- } else {
148125
- status = "pending";
148126
- }
148127
- const execution = {
148128
- nodeId: graphNode.id,
148129
- attemptNumber: 1,
148130
- status,
148131
- startedAt,
148132
- completedAt,
148133
- duration: duration2
148134
- };
148135
- const existing = nodeExecutions.get(graphNode.id) || [];
148136
- nodeExecutions.set(graphNode.id, [...existing, execution]);
148137
- if (!executionPath.includes(graphNode.id)) {
148138
- executionPath.push(graphNode.id);
148139
- }
148228
+ if (depth >= MAX_DISPLAY_DEPTH) {
148229
+ if (Array.isArray(value)) return `Array(${value.length})`;
148230
+ if (typeof value === "object") return "{…}";
148231
+ return value;
148140
148232
  }
148141
- return currentNode;
148142
- }
148143
- function processAgentAndToolNodes(run, steps, agentNodes, toolNodes, nodeExecutions, executionPath, allNodes) {
148144
- var _a3;
148145
- let agentStatus = "pending";
148146
- if (run.status === "completed") {
148147
- agentStatus = "completed";
148148
- } else if (run.status === "failed") {
148149
- agentStatus = "failed";
148150
- } else if (run.status === "running") {
148151
- agentStatus = "running";
148152
- }
148153
- for (const agentNode of agentNodes) {
148154
- const execution = {
148155
- nodeId: agentNode.id,
148156
- attemptNumber: 1,
148157
- status: agentStatus,
148158
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
148159
- completedAt: run.completedAt && (agentStatus === "completed" || agentStatus === "failed") ? new Date(run.completedAt).toISOString() : void 0
148160
- };
148161
- nodeExecutions.set(agentNode.id, [execution]);
148162
- if (!executionPath.includes(agentNode.id)) {
148163
- executionPath.push(agentNode.id);
148164
- }
148165
- }
148166
- for (const step of steps) {
148167
- const functionName = extractFunctionName(step.stepName);
148168
- if (!functionName) continue;
148169
- const matchingToolNodes = toolNodes.get(functionName);
148170
- if (!matchingToolNodes || matchingToolNodes.length === 0) continue;
148171
- const toolNode = matchingToolNodes[0];
148172
- let status;
148173
- switch (step.status) {
148174
- case "completed":
148175
- status = "completed";
148176
- break;
148177
- case "failed":
148178
- status = "failed";
148179
- break;
148180
- case "running":
148181
- status = "running";
148182
- break;
148183
- case "cancelled":
148184
- status = "cancelled";
148185
- break;
148186
- case "pending":
148187
- default:
148188
- status = "pending";
148189
- break;
148190
- }
148191
- const duration2 = step.completedAt && step.startedAt ? new Date(step.completedAt).getTime() - new Date(step.startedAt).getTime() : void 0;
148192
- const execution = {
148193
- nodeId: toolNode.id,
148194
- stepId: step.stepId,
148195
- attemptNumber: step.attempt,
148196
- status,
148197
- startedAt: step.startedAt ? new Date(step.startedAt).toISOString() : void 0,
148198
- completedAt: step.completedAt ? new Date(step.completedAt).toISOString() : void 0,
148199
- duration: duration2,
148200
- input: step.input,
148201
- output: step.output,
148202
- error: step.error
148203
- };
148204
- const existing = nodeExecutions.get(toolNode.id) || [];
148205
- nodeExecutions.set(toolNode.id, [...existing, execution]);
148206
- if (!executionPath.includes(toolNode.id)) {
148207
- executionPath.push(toolNode.id);
148233
+ if (Array.isArray(value)) {
148234
+ if (value.length <= MAX_DISPLAY_ENTRIES) {
148235
+ return value.map((v2) => sanitizeForDisplay(v2, depth + 1));
148208
148236
  }
148237
+ const trimmed = value.slice(0, MAX_DISPLAY_ENTRIES).map((v2) => sanitizeForDisplay(v2, depth + 1));
148238
+ trimmed.push(`… ${value.length - MAX_DISPLAY_ENTRIES} more items`);
148239
+ return trimmed;
148209
148240
  }
148210
- for (const node2 of allNodes) {
148211
- const isToolsCollection = ((_a3 = node2.metadata) == null ? void 0 : _a3.isToolsCollection) === true;
148212
- if (node2.data.nodeKind === "tool" && isToolsCollection && !nodeExecutions.has(node2.id)) {
148213
- const execution = {
148214
- nodeId: node2.id,
148215
- attemptNumber: 1,
148216
- status: agentStatus,
148217
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
148218
- completedAt: run.completedAt && (agentStatus === "completed" || agentStatus === "failed") ? new Date(run.completedAt).toISOString() : void 0
148219
- };
148220
- nodeExecutions.set(node2.id, [execution]);
148221
- if (!executionPath.includes(node2.id)) {
148222
- executionPath.push(node2.id);
148223
- }
148241
+ if (typeof value === "object") {
148242
+ const keys2 = Object.keys(value);
148243
+ const out = {};
148244
+ const limit = Math.min(keys2.length, MAX_DISPLAY_ENTRIES);
148245
+ for (let i = 0; i < limit; i++) {
148246
+ out[keys2[i]] = sanitizeForDisplay(
148247
+ value[keys2[i]],
148248
+ depth + 1
148249
+ );
148224
148250
  }
148225
- }
148226
- }
148227
- function processConditionalNodes(graph, nodeExecutions, executionPath, run) {
148228
- var _a3, _b, _c;
148229
- const conditionalNodes = graph.nodes.filter(
148230
- (n) => n.data.nodeKind === "conditional"
148231
- );
148232
- const nodesByConditionalId = /* @__PURE__ */ new Map();
148233
- for (const node2 of graph.nodes) {
148234
- const condId = (_a3 = node2.metadata) == null ? void 0 : _a3.conditionalId;
148235
- if (condId) {
148236
- const group = nodesByConditionalId.get(condId) || {
148237
- thenNodes: [],
148238
- elseNodes: []
148239
- };
148240
- if (((_b = node2.metadata) == null ? void 0 : _b.conditionalBranch) === "Then") {
148241
- group.thenNodes.push(node2);
148242
- } else if (((_c = node2.metadata) == null ? void 0 : _c.conditionalBranch) === "Else") {
148243
- group.elseNodes.push(node2);
148244
- }
148245
- nodesByConditionalId.set(condId, group);
148246
- }
148247
- }
148248
- for (const condNode of conditionalNodes) {
148249
- const condIdMatch = condNode.id.match(/^(cond_\d+)_node$/);
148250
- if (!condIdMatch) continue;
148251
- const condId = condIdMatch[1];
148252
- const branches = nodesByConditionalId.get(condId);
148253
- if (!branches) continue;
148254
- const thenExecuted = branches.thenNodes.some(
148255
- (n) => nodeExecutions.has(n.id)
148256
- );
148257
- const elseExecuted = branches.elseNodes.some(
148258
- (n) => nodeExecutions.has(n.id)
148259
- );
148260
- if (thenExecuted || elseExecuted) {
148261
- const allBranchNodes = [...branches.thenNodes, ...branches.elseNodes];
148262
- if (!nodeExecutions.has(condNode.id)) {
148263
- let earliestTime;
148264
- for (const branchNode of allBranchNodes) {
148265
- const execs = nodeExecutions.get(branchNode.id);
148266
- if (execs && execs.length > 0) {
148267
- const firstExec = execs[0];
148268
- if (firstExec.startedAt && (!earliestTime || firstExec.startedAt < earliestTime)) {
148269
- earliestTime = firstExec.startedAt;
148270
- }
148271
- }
148272
- }
148273
- const fallbackTime = run.startedAt ? new Date(run.startedAt).toISOString() : void 0;
148274
- const execution = {
148275
- nodeId: condNode.id,
148276
- attemptNumber: 1,
148277
- status: "completed",
148278
- startedAt: earliestTime || fallbackTime,
148279
- completedAt: earliestTime || fallbackTime
148280
- // No duration for control flow nodes (start/end/conditional)
148281
- };
148282
- nodeExecutions.set(condNode.id, [execution]);
148283
- }
148284
- if (!executionPath.includes(condNode.id)) {
148285
- const branchIndices = allBranchNodes.map((n) => executionPath.indexOf(n.id)).filter((i) => i >= 0);
148286
- if (branchIndices.length > 0) {
148287
- const firstBranchIndex = Math.min(...branchIndices);
148288
- if (firstBranchIndex >= 0 && firstBranchIndex < executionPath.length) {
148289
- executionPath.splice(firstBranchIndex, 0, condNode.id);
148290
- } else {
148291
- executionPath.push(condNode.id);
148292
- }
148293
- } else {
148294
- executionPath.push(condNode.id);
148295
- }
148296
- }
148251
+ if (keys2.length > MAX_DISPLAY_ENTRIES) {
148252
+ out[`… ${keys2.length - MAX_DISPLAY_ENTRIES} more keys`] = "…";
148297
148253
  }
148254
+ return out;
148298
148255
  }
148256
+ return value;
148299
148257
  }
148300
- function mapRunToExecution(run, steps, events2, graph) {
148301
- const nodeExecutions = /* @__PURE__ */ new Map();
148302
- const executionPath = [];
148303
- let currentNode;
148304
- console.log("[Graph Mapper] Mapping run to execution:", {
148305
- runId: run.runId,
148306
- workflowName: run.workflowName,
148307
- graphNodes: graph.nodes.length,
148308
- stepsCount: steps.length
148309
- });
148310
- initializeStartNode(run, graph, executionPath, nodeExecutions);
148311
- const sortedSteps = [...steps].sort(
148312
- (a2, b2) => new Date(a2.createdAt).getTime() - new Date(b2.createdAt).getTime()
148313
- );
148314
- console.log(
148315
- "[Graph Mapper] Sorted steps:",
148316
- sortedSteps.map((s2) => ({
148317
- stepId: s2.stepId,
148318
- stepName: s2.stepName,
148319
- attempt: s2.attempt,
148320
- status: s2.status,
148321
- createdAt: s2.createdAt
148322
- }))
148323
- );
148324
- const {
148325
- byStepId: nodesByStepId,
148326
- byFunctionName: nodesByFunctionName,
148327
- primitivesByLabel,
148328
- agentNodes,
148329
- toolNodes
148330
- } = buildNodeIndex(graph.nodes);
148331
- console.log("[Graph Mapper] Graph nodes by stepId:", {
148332
- allGraphNodes: graph.nodes.map((n) => ({
148333
- id: n.id,
148334
- stepId: n.data.stepId,
148335
- normalizedStepId: n.data.stepId ? normalizeStepName(n.data.stepId) : void 0,
148336
- nodeKind: n.data.nodeKind
148337
- })),
148338
- nodesByStepId: Array.from(nodesByStepId.entries()).map(
148339
- ([stepId, nodes]) => ({
148340
- stepId,
148341
- nodeIds: nodes.map((n) => n.id)
148342
- })
148343
- )
148344
- });
148345
- const stepNameOccurrenceCount = /* @__PURE__ */ new Map();
148346
- let currentStepGroup = [];
148347
- let currentStepId = null;
148348
- let currentStepName = null;
148349
- for (let i = 0; i <= sortedSteps.length; i++) {
148350
- const step = sortedSteps[i];
148351
- const isNewInvocation = !step || step.stepId !== currentStepId;
148352
- if (isNewInvocation) {
148353
- if (currentStepGroup.length > 0 && currentStepName) {
148354
- const runningNode = processStepGroup(
148355
- currentStepGroup,
148356
- currentStepName,
148357
- nodesByStepId,
148358
- nodesByFunctionName,
148359
- stepNameOccurrenceCount,
148360
- nodeExecutions,
148361
- executionPath
148362
- );
148363
- if (runningNode) {
148364
- currentNode = runningNode;
148365
- }
148366
- }
148367
- if (step) {
148368
- currentStepGroup = [step];
148369
- currentStepId = step.stepId;
148370
- currentStepName = step.stepName;
148371
- }
148372
- } else {
148373
- currentStepGroup.push(step);
148374
- }
148375
- }
148376
- const primitiveCurrentNode = processPrimitiveEvents(
148377
- events2,
148378
- primitivesByLabel,
148379
- nodeExecutions,
148380
- executionPath
148381
- );
148382
- if (primitiveCurrentNode) {
148383
- currentNode = primitiveCurrentNode;
148384
- }
148385
- processAgentAndToolNodes(
148386
- run,
148387
- sortedSteps,
148388
- agentNodes,
148389
- toolNodes,
148390
- nodeExecutions,
148391
- executionPath,
148392
- graph.nodes
148393
- );
148394
- processConditionalNodes(graph, nodeExecutions, executionPath, run);
148395
- addEndNodeExecution(run, graph, executionPath, nodeExecutions);
148396
- const edgeTraversals = calculateEdgeTraversals(
148397
- executionPath,
148398
- graph,
148399
- nodeExecutions
148400
- );
148401
- const result = {
148402
- runId: run.runId,
148403
- status: run.status,
148404
- nodeExecutions,
148405
- edgeTraversals,
148406
- currentNode,
148407
- executionPath
148408
- };
148409
- console.log("[Graph Mapper] Mapping complete:", {
148410
- executionPath,
148411
- nodeExecutionsCount: nodeExecutions.size,
148412
- nodeExecutions: Array.from(nodeExecutions.entries()).map(
148413
- ([nodeId, execs]) => {
148414
- var _a3;
148415
- return {
148416
- nodeId,
148417
- executionCount: execs.length,
148418
- latestStatus: (_a3 = execs[execs.length - 1]) == null ? void 0 : _a3.status
148419
- };
148420
- }
148421
- )
148422
- });
148423
- return result;
148258
+ const yieldToMain = () => new Promise((resolve2) => setTimeout(resolve2, 0));
148259
+ const YIELD_EVERY_N_FRAMES = 64;
148260
+ function detectEncoding(data) {
148261
+ if (data.length < FRAME_HEADER_SIZE) return "framed";
148262
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
148263
+ const len = view.getUint32(0, false);
148264
+ if (len > 0 && len <= 10 * 1024 * 1024) return "framed";
148265
+ return "legacy";
148424
148266
  }
148425
- const FRAME_HEADER_SIZE = 4;
148426
148267
  function useStreamReader(env2, streamId, runId, encryptionKey) {
148427
148268
  const [chunks, setChunks] = reactExports.useState([]);
148428
148269
  const [isLive, setIsLive] = reactExports.useState(false);
@@ -148452,36 +148293,82 @@ function useStreamReader(env2, streamId, runId, encryptionKey) {
148452
148293
  );
148453
148294
  const cryptoKey = encryptionKey ? await importKey(encryptionKey) : void 0;
148454
148295
  const reader = rawStream.getReader();
148296
+ const decoder2 = new TextDecoder();
148455
148297
  let buffer = new Uint8Array(0);
148298
+ let encoding2 = null;
148299
+ let textRemainder = "";
148456
148300
  const appendToBuffer = (data) => {
148457
148301
  const newBuffer = new Uint8Array(buffer.length + data.length);
148458
148302
  newBuffer.set(buffer, 0);
148459
148303
  newBuffer.set(data, buffer.length);
148460
148304
  buffer = newBuffer;
148461
148305
  };
148306
+ const addLegacyLine = (line) => {
148307
+ if (!mounted || !line) return;
148308
+ const chunkId = chunkIdRef.current++;
148309
+ let text2;
148310
+ try {
148311
+ const parsed = JSON.parse(line);
148312
+ text2 = JSON.stringify(parsed, null, 2);
148313
+ } catch {
148314
+ text2 = line;
148315
+ }
148316
+ setChunks((prev) => [...prev, { id: chunkId, text: text2 }]);
148317
+ };
148462
148318
  for (; ; ) {
148463
148319
  if (abortController.signal.aborted) break;
148464
148320
  const { value, done } = await reader.read();
148465
148321
  if (done) {
148322
+ if (encoding2 === "legacy" && textRemainder.trim()) {
148323
+ addLegacyLine(textRemainder.trim());
148324
+ textRemainder = "";
148325
+ }
148466
148326
  if (mounted) setIsLive(false);
148467
148327
  break;
148468
148328
  }
148469
- appendToBuffer(value);
148470
- while (buffer.length >= FRAME_HEADER_SIZE) {
148329
+ if (encoding2 === null) {
148330
+ appendToBuffer(value);
148331
+ if (buffer.length >= FRAME_HEADER_SIZE) {
148332
+ encoding2 = detectEncoding(buffer);
148333
+ }
148334
+ if (encoding2 === "legacy") {
148335
+ textRemainder = decoder2.decode(buffer, { stream: true });
148336
+ buffer = new Uint8Array(0);
148337
+ }
148338
+ } else if (encoding2 === "legacy") {
148339
+ textRemainder += decoder2.decode(value, { stream: true });
148340
+ } else {
148341
+ appendToBuffer(value);
148342
+ }
148343
+ if (encoding2 === "legacy") {
148344
+ const lines = textRemainder.split("\n");
148345
+ textRemainder = lines.pop() ?? "";
148346
+ for (const line of lines) {
148347
+ const trimmed = line.trim();
148348
+ if (trimmed) addLegacyLine(trimmed);
148349
+ }
148350
+ continue;
148351
+ }
148352
+ let offset2 = 0;
148353
+ let framesInBatch = 0;
148354
+ while (offset2 + FRAME_HEADER_SIZE <= buffer.length) {
148471
148355
  const view = new DataView(
148472
148356
  buffer.buffer,
148473
- buffer.byteOffset,
148474
- buffer.byteLength
148357
+ buffer.byteOffset + offset2,
148358
+ buffer.byteLength - offset2
148475
148359
  );
148476
148360
  const frameLength = view.getUint32(0, false);
148477
- if (buffer.length < FRAME_HEADER_SIZE + frameLength) {
148361
+ if (frameLength === 0 || frameLength > 10 * 1024 * 1024) {
148362
+ break;
148363
+ }
148364
+ if (offset2 + FRAME_HEADER_SIZE + frameLength > buffer.length) {
148478
148365
  break;
148479
148366
  }
148480
148367
  const frameData = buffer.slice(
148481
- FRAME_HEADER_SIZE,
148482
- FRAME_HEADER_SIZE + frameLength
148368
+ offset2 + FRAME_HEADER_SIZE,
148369
+ offset2 + FRAME_HEADER_SIZE + frameLength
148483
148370
  );
148484
- buffer = buffer.slice(FRAME_HEADER_SIZE + frameLength);
148371
+ offset2 += FRAME_HEADER_SIZE + frameLength;
148485
148372
  try {
148486
148373
  const { format: format2, payload } = decodeFormatPrefix$1(frameData);
148487
148374
  let dataToHydrate;
@@ -148504,13 +148391,29 @@ function useStreamReader(env2, streamId, runId, encryptionKey) {
148504
148391
  const hydrated = hydrateData(dataToHydrate, revivers);
148505
148392
  if (mounted && hydrated !== void 0 && hydrated !== null) {
148506
148393
  const chunkId = chunkIdRef.current++;
148507
- const text2 = typeof hydrated === "string" ? hydrated : JSON.stringify(hydrated, null, 2);
148394
+ let text2;
148395
+ try {
148396
+ if (typeof hydrated === "string") {
148397
+ text2 = hydrated;
148398
+ } else {
148399
+ const safe = sanitizeForDisplay(hydrated);
148400
+ text2 = JSON.stringify(safe, null, 2);
148401
+ }
148402
+ } catch {
148403
+ text2 = "[Serialization Error]";
148404
+ }
148508
148405
  setChunks((prev) => [...prev, { id: chunkId, text: text2 }]);
148509
148406
  }
148510
148407
  } catch (err) {
148511
148408
  console.error("Failed to process stream frame:", err);
148512
148409
  }
148410
+ framesInBatch++;
148411
+ if (framesInBatch % YIELD_EVERY_N_FRAMES === 0) {
148412
+ await yieldToMain();
148413
+ if (abortController.signal.aborted || !mounted) break;
148414
+ }
148513
148415
  }
148416
+ buffer = buffer.slice(offset2);
148514
148417
  }
148515
148418
  } catch (err) {
148516
148419
  if (abortController.signal.aborted) return;
@@ -148664,900 +148567,9 @@ function LiveStatus({ hasError, errorMessage }) {
148664
148567
  /* @__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` }) })
148665
148568
  ] }) });
148666
148569
  }
148667
- function mapToStatusBadgeStatus(status) {
148668
- if (status === "retrying") return "running";
148669
- return status;
148670
- }
148671
- function ExecutionLoopNodeComponent({ data, selected: selected2 }) {
148672
- var _a3, _b, _c, _d;
148673
- const nodeData = data;
148674
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
148675
- "div",
148676
- {
148677
- className: `relative ${nodeData.className || ""}`,
148678
- style: {
148679
- borderWidth: ((_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.borderWidth) ?? 2,
148680
- borderRadius: 8,
148681
- padding: 12,
148682
- width: 220,
148683
- borderStyle: "solid",
148684
- backgroundColor: (_b = nodeData.nodeStyle) == null ? void 0 : _b.backgroundColor,
148685
- borderColor: ((_c = nodeData.nodeStyle) == null ? void 0 : _c.borderColor) ?? "#9ca3af",
148686
- opacity: (_d = nodeData.nodeStyle) == null ? void 0 : _d.opacity,
148687
- boxShadow: selected2 ? "0 0 0 2px rgba(168, 85, 247, 0.5)" : void 0
148688
- },
148689
- children: [
148690
- nodeData.label,
148691
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148692
- Handle,
148693
- {
148694
- type: "target",
148695
- position: Position.Top,
148696
- className: "!bg-purple-500"
148697
- }
148698
- ),
148699
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148700
- Handle,
148701
- {
148702
- type: "source",
148703
- position: Position.Bottom,
148704
- className: "!bg-purple-500"
148705
- }
148706
- ),
148707
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148708
- Handle,
148709
- {
148710
- type: "source",
148711
- position: Position.Left,
148712
- id: "loop-out",
148713
- className: "!bg-purple-500 !-left-1 !w-[6px] !h-[6px] !min-w-0 !min-h-0",
148714
- style: { top: "30%" }
148715
- }
148716
- ),
148717
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148718
- Handle,
148719
- {
148720
- type: "target",
148721
- position: Position.Left,
148722
- id: "loop-in",
148723
- className: "!bg-purple-500 !-left-1 !w-[6px] !h-[6px] !min-w-0 !min-h-0",
148724
- style: { top: "70%" }
148725
- }
148726
- )
148727
- ]
148728
- }
148729
- );
148730
- }
148731
- function ExecutionNodeComponent({ data, selected: selected2 }) {
148732
- var _a3, _b, _c, _d;
148733
- const nodeData = data;
148734
- const isStart = nodeData.nodeKind === "workflow_start";
148735
- const isEnd = nodeData.nodeKind === "workflow_end";
148736
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
148737
- "div",
148738
- {
148739
- className: `relative ${nodeData.className || ""}`,
148740
- style: {
148741
- borderWidth: ((_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.borderWidth) ?? 2,
148742
- borderRadius: 8,
148743
- padding: 12,
148744
- width: 220,
148745
- borderStyle: "solid",
148746
- backgroundColor: (_b = nodeData.nodeStyle) == null ? void 0 : _b.backgroundColor,
148747
- borderColor: ((_c = nodeData.nodeStyle) == null ? void 0 : _c.borderColor) ?? "#9ca3af",
148748
- opacity: (_d = nodeData.nodeStyle) == null ? void 0 : _d.opacity,
148749
- boxShadow: selected2 ? "0 0 0 2px rgba(59, 130, 246, 0.35)" : void 0
148750
- },
148751
- children: [
148752
- nodeData.label,
148753
- !isStart && /* @__PURE__ */ jsxRuntimeExports.jsx(Handle, { type: "target", position: Position.Top, className: "!bg-muted" }),
148754
- !isEnd && /* @__PURE__ */ jsxRuntimeExports.jsx(
148755
- Handle,
148756
- {
148757
- type: "source",
148758
- position: Position.Bottom,
148759
- className: "!bg-muted"
148760
- }
148761
- )
148762
- ]
148763
- }
148764
- );
148765
- }
148766
- function ExecutionDiamondNodeComponent({ data, selected: selected2 }) {
148767
- var _a3, _b, _c;
148768
- const nodeData = data;
148769
- const size2 = 160;
148770
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
148771
- "div",
148772
- {
148773
- className: `relative flex items-center justify-center ${nodeData.className || ""}`,
148774
- style: {
148775
- width: size2,
148776
- height: size2
148777
- },
148778
- children: [
148779
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148780
- "div",
148781
- {
148782
- style: {
148783
- width: size2 * 0.7,
148784
- height: size2 * 0.7,
148785
- transform: "rotate(45deg)",
148786
- borderWidth: 2,
148787
- borderStyle: "solid",
148788
- borderRadius: 4,
148789
- backgroundColor: (_a3 = nodeData.nodeStyle) == null ? void 0 : _a3.backgroundColor,
148790
- borderColor: ((_b = nodeData.nodeStyle) == null ? void 0 : _b.borderColor) ?? "#ef4444",
148791
- opacity: (_c = nodeData.nodeStyle) == null ? void 0 : _c.opacity,
148792
- boxShadow: selected2 ? "0 0 0 2px rgba(239, 68, 68, 0.5)" : void 0
148793
- }
148794
- }
148795
- ),
148796
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148797
- "div",
148798
- {
148799
- className: "absolute inset-0 flex items-center justify-center pointer-events-auto",
148800
- style: {
148801
- fontSize: 11,
148802
- fontWeight: 600,
148803
- padding: size2 * 0.25
148804
- // Keep text within the diamond's inscribed area
148805
- },
148806
- title: typeof nodeData.label === "string" ? nodeData.label : void 0,
148807
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-center line-clamp-3 overflow-hidden", children: nodeData.label })
148808
- }
148809
- ),
148810
- /* @__PURE__ */ jsxRuntimeExports.jsx(Handle, { type: "target", position: Position.Top, className: "!bg-red-500" }),
148811
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148812
- Handle,
148813
- {
148814
- type: "source",
148815
- position: Position.Bottom,
148816
- id: "bottom",
148817
- className: "!bg-red-500"
148818
- }
148819
- ),
148820
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148821
- Handle,
148822
- {
148823
- type: "source",
148824
- position: Position.Left,
148825
- id: "left",
148826
- className: "!bg-red-500"
148827
- }
148828
- ),
148829
- /* @__PURE__ */ jsxRuntimeExports.jsx(
148830
- Handle,
148831
- {
148832
- type: "source",
148833
- position: Position.Right,
148834
- id: "right",
148835
- className: "!bg-red-500"
148836
- }
148837
- )
148838
- ]
148839
- }
148840
- );
148841
- }
148842
- const nodeTypes = {
148843
- loopNode: ExecutionLoopNodeComponent,
148844
- parallelGroup: ParallelGroupComponent,
148845
- // Imported from shared
148846
- executionNode: ExecutionNodeComponent,
148847
- diamondNode: ExecutionDiamondNodeComponent
148848
- };
148849
- const edgeTypes = createEdgeTypes(executionSelfLoopStyle);
148850
- function getExecutionNodeStyle(nodeKind, executions) {
148851
- const backgroundColor = getNodeBackgroundColor(nodeKind);
148852
- if (!executions || executions.length === 0) {
148853
- return {
148854
- color: "hsl(var(--card-foreground))",
148855
- backgroundColor,
148856
- borderColor: "#9ca3af",
148857
- // gray-400
148858
- opacity: 0.4
148859
- };
148860
- }
148861
- const latestExecution = executions[executions.length - 1];
148862
- let borderColor = "#9ca3af";
148863
- let borderWidth = 2;
148864
- switch (latestExecution.status) {
148865
- case "completed":
148866
- borderColor = "#22c55e";
148867
- break;
148868
- case "failed":
148869
- borderColor = "#ef4444";
148870
- borderWidth = 3;
148871
- break;
148872
- case "running":
148873
- borderColor = "#3b82f6";
148874
- borderWidth = 2;
148875
- break;
148876
- case "retrying":
148877
- borderColor = "#f97316";
148878
- break;
148879
- case "cancelled":
148880
- borderColor = "#eab308";
148881
- break;
148882
- case "pending":
148883
- borderColor = "#9ca3af";
148884
- break;
148885
- }
148886
- return {
148887
- color: "hsl(var(--card-foreground))",
148888
- backgroundColor,
148889
- borderColor,
148890
- borderWidth
148891
- };
148892
- }
148893
- function renderNodeLabel(nodeData, _metadata, executions) {
148894
- const baseLabel = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 w-full overflow-hidden", children: [
148895
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", children: getNodeIcon(nodeData.nodeKind, nodeData.label) }),
148896
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium break-words whitespace-normal leading-tight flex-1 min-w-0", children: nodeData.label })
148897
- ] });
148898
- if (!executions || executions.length === 0) {
148899
- return baseLabel;
148900
- }
148901
- const latestExecution = executions[executions.length - 1];
148902
- const totalAttempts = executions.length;
148903
- const hasRetries = totalAttempts > 1;
148904
- const hasMetadata = hasRetries || latestExecution.duration && latestExecution.duration > 0;
148905
- if (!hasMetadata) return baseLabel;
148906
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
148907
- baseLabel,
148908
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-1 text-xs", children: [
148909
- hasRetries && /* @__PURE__ */ jsxRuntimeExports.jsxs(
148910
- Badge,
148911
- {
148912
- variant: "outline",
148913
- className: "text-xs px-1.5 py-0 border-orange-500 text-orange-700 dark:text-orange-300",
148914
- children: [
148915
- "↻ ",
148916
- totalAttempts,
148917
- "x"
148918
- ]
148919
- }
148920
- ),
148921
- latestExecution.duration && latestExecution.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
148922
- Badge,
148923
- {
148924
- variant: "secondary",
148925
- className: "text-xs px-1.5 py-0 bg-black/10 dark:bg-white/15 border-0",
148926
- children: [
148927
- "⏱ ",
148928
- formatDuration(latestExecution.duration, true)
148929
- ]
148930
- }
148931
- )
148932
- ] })
148933
- ] });
148934
- }
148935
- const EXECUTION_LAYOUT = {
148570
+ ({
148936
148571
  ...LAYOUT$1
148937
- };
148938
- function convertToReactFlowNodes(workflow, execution) {
148939
- var _a3, _b, _c;
148940
- const { nodes, groupNodes } = calculateEnhancedLayout(
148941
- workflow,
148942
- EXECUTION_LAYOUT
148943
- );
148944
- const nodeToParent = /* @__PURE__ */ new Map();
148945
- const groupPositions = /* @__PURE__ */ new Map();
148946
- for (const group of groupNodes) {
148947
- if (group.id.startsWith("group_")) {
148948
- groupPositions.set(group.id, group.position);
148949
- }
148950
- }
148951
- for (const node2 of nodes) {
148952
- const parallelGroupId = ((_a3 = node2.metadata) == null ? void 0 : _a3.parallelGroupId) ? `group_${node2.metadata.parallelGroupId}` : null;
148953
- if (parallelGroupId && groupPositions.has(parallelGroupId)) {
148954
- nodeToParent.set(node2.id, parallelGroupId);
148955
- }
148956
- }
148957
- const reactFlowNodes = [];
148958
- const parallelGroups = groupNodes.filter((g2) => g2.id.startsWith("group_"));
148959
- for (const group of parallelGroups) {
148960
- reactFlowNodes.push({
148961
- id: group.id,
148962
- type: "parallelGroup",
148963
- position: group.position,
148964
- style: {
148965
- ...group.style,
148966
- cursor: "grab",
148967
- zIndex: -1
148968
- },
148969
- data: group.data,
148970
- selectable: true,
148971
- draggable: true
148972
- });
148973
- }
148974
- for (const node2 of nodes) {
148975
- const executions = execution == null ? void 0 : execution.nodeExecutions.get(node2.id);
148976
- const styles2 = getExecutionNodeStyle(node2.data.nodeKind, executions);
148977
- const isCurrentNode = (execution == null ? void 0 : execution.currentNode) === node2.id;
148978
- const isLoopNode = !!((_b = node2.metadata) == null ? void 0 : _b.loopId);
148979
- const isAwaitLoop = !!((_c = node2.metadata) == null ? void 0 : _c.loopIsAwait);
148980
- const isConditionalNode = node2.data.nodeKind === "conditional";
148981
- const nodeType = isConditionalNode ? "diamondNode" : isLoopNode ? "loopNode" : "executionNode";
148982
- const parentId = nodeToParent.get(node2.id);
148983
- let position2 = node2.position;
148984
- if (parentId) {
148985
- const parentPos = groupPositions.get(parentId);
148986
- if (parentPos) {
148987
- position2 = {
148988
- x: node2.position.x - parentPos.x,
148989
- y: node2.position.y - parentPos.y
148990
- };
148991
- }
148992
- }
148993
- const nodeClassName = isCurrentNode ? "animate-pulse-subtle" : "";
148994
- if (isLoopNode) {
148995
- reactFlowNodes.push({
148996
- id: node2.id,
148997
- type: nodeType,
148998
- position: position2,
148999
- parentId,
149000
- extent: parentId ? "parent" : void 0,
149001
- expandParent: true,
149002
- data: {
149003
- ...node2.data,
149004
- label: renderNodeLabel(node2.data, node2.metadata, executions),
149005
- executions,
149006
- isLoopNode: true,
149007
- isAwaitLoop,
149008
- nodeStyle: styles2,
149009
- className: nodeClassName
149010
- }
149011
- });
149012
- } else if (isConditionalNode) {
149013
- reactFlowNodes.push({
149014
- id: node2.id,
149015
- type: nodeType,
149016
- position: position2,
149017
- parentId,
149018
- extent: parentId ? "parent" : void 0,
149019
- expandParent: true,
149020
- data: {
149021
- ...node2.data,
149022
- label: node2.data.label,
149023
- // Show the conditional expression
149024
- executions,
149025
- nodeStyle: styles2,
149026
- className: nodeClassName
149027
- }
149028
- });
149029
- } else {
149030
- reactFlowNodes.push({
149031
- id: node2.id,
149032
- type: nodeType,
149033
- position: position2,
149034
- parentId,
149035
- extent: parentId ? "parent" : void 0,
149036
- expandParent: true,
149037
- data: {
149038
- ...node2.data,
149039
- label: renderNodeLabel(node2.data, node2.metadata, executions),
149040
- executions,
149041
- nodeStyle: styles2,
149042
- className: nodeClassName
149043
- },
149044
- // Styling is handled by ExecutionNodeComponent (keeps running animation behind background)
149045
- style: { width: 220 }
149046
- });
149047
- }
149048
- }
149049
- return reactFlowNodes;
149050
- }
149051
- function convertToReactFlowEdges(workflow, execution) {
149052
- const { additionalEdges } = calculateEnhancedLayout(
149053
- workflow,
149054
- EXECUTION_LAYOUT
149055
- );
149056
- const transformedOriginalEdges = workflow.edges.map((e) => {
149057
- if (e.type === "loop") {
149058
- return {
149059
- ...e,
149060
- id: `loop_back_${e.source}_${e.target}`,
149061
- isOriginal: true
149062
- };
149063
- }
149064
- return { ...e, isOriginal: true };
149065
- });
149066
- const rawEdges = [
149067
- ...transformedOriginalEdges,
149068
- ...additionalEdges.map((e) => ({ ...e, isOriginal: false }))
149069
- ];
149070
- const allEdges = consolidateEdges(rawEdges, workflow.nodes);
149071
- return allEdges.map((edge) => {
149072
- if (edge.type === "selfLoop") {
149073
- return {
149074
- id: edge.id,
149075
- source: edge.source,
149076
- target: edge.target,
149077
- sourceHandle: edge.sourceHandle,
149078
- targetHandle: edge.targetHandle,
149079
- type: "selfLoop",
149080
- label: edge.label,
149081
- markerEnd: {
149082
- type: MarkerType.ArrowClosed,
149083
- width: 12,
149084
- height: 12,
149085
- color: "#a855f7"
149086
- }
149087
- };
149088
- }
149089
- let traversal = execution == null ? void 0 : execution.edgeTraversals.get(edge.id);
149090
- if (!traversal && edge.isConsolidated && edge.originalEdgeIds) {
149091
- for (const originalId of edge.originalEdgeIds) {
149092
- const originalTraversal = execution == null ? void 0 : execution.edgeTraversals.get(originalId);
149093
- if (originalTraversal && originalTraversal.traversalCount > 0) {
149094
- traversal = originalTraversal;
149095
- break;
149096
- }
149097
- }
149098
- }
149099
- const isTraversed = traversal && traversal.traversalCount > 0;
149100
- const hasExecution = !!execution;
149101
- const avgTiming = (traversal == null ? void 0 : traversal.timings.length) ? traversal.timings.reduce((a2, b2) => a2 + b2, 0) / traversal.timings.length : void 0;
149102
- let edgeType = "bezier";
149103
- let strokeDasharray;
149104
- let cfgLabel = edge.label;
149105
- let isConditional = false;
149106
- switch (edge.type) {
149107
- case "parallel":
149108
- edgeType = "smoothstep";
149109
- strokeDasharray = "4,4";
149110
- cfgLabel = void 0;
149111
- break;
149112
- case "loop":
149113
- edgeType = "step";
149114
- strokeDasharray = "8,4";
149115
- break;
149116
- case "conditional":
149117
- edgeType = "smoothstep";
149118
- strokeDasharray = "8,4";
149119
- isConditional = true;
149120
- break;
149121
- default:
149122
- edgeType = "bezier";
149123
- }
149124
- const baseStrokeColor = "#6b7280";
149125
- const finalStrokeColor = isTraversed ? "#22c55e" : baseStrokeColor;
149126
- const finalDasharray = isTraversed ? void 0 : strokeDasharray;
149127
- const opacity = hasExecution && !isTraversed ? 0.35 : 1;
149128
- const strokeWidth = isTraversed ? 2.5 : 1;
149129
- const labelTextColor = isConditional ? "#ffffff" : "#6b7280";
149130
- const labelBgColor = isConditional ? "#374151" : "#f3f4f6";
149131
- const labelBorderColor = isConditional ? "#4b5563" : "#d1d5db";
149132
- return {
149133
- id: edge.id,
149134
- source: edge.source,
149135
- target: edge.target,
149136
- type: edgeType,
149137
- animated: isTraversed && (execution == null ? void 0 : execution.status) === "running",
149138
- label: traversal && traversal.traversalCount > 1 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-0.5", children: [
149139
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "text-xs px-1.5 py-0", children: [
149140
- traversal.traversalCount,
149141
- "×"
149142
- ] }),
149143
- avgTiming && avgTiming > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
149144
- "~",
149145
- formatDuration(avgTiming, true)
149146
- ] })
149147
- ] }) : cfgLabel,
149148
- labelStyle: {
149149
- fill: labelTextColor,
149150
- fontWeight: 500,
149151
- fontSize: "11px"
149152
- },
149153
- labelBgStyle: {
149154
- fill: labelBgColor,
149155
- fillOpacity: 0.95,
149156
- stroke: labelBorderColor,
149157
- strokeWidth: 1
149158
- },
149159
- labelBgPadding: [4, 6],
149160
- labelBgBorderRadius: 4,
149161
- markerEnd: {
149162
- type: MarkerType.ArrowClosed,
149163
- width: isTraversed ? 14 : 10,
149164
- height: isTraversed ? 14 : 10,
149165
- color: finalStrokeColor
149166
- },
149167
- style: {
149168
- strokeWidth,
149169
- stroke: finalStrokeColor,
149170
- opacity,
149171
- strokeDasharray: finalDasharray
149172
- }
149173
- };
149174
- });
149175
- }
149176
- function GraphNodeDetailPanel({
149177
- selectedNode,
149178
- env: env2,
149179
- onClose
149180
- }) {
149181
- const { node: node2, executions, stepId, runId } = selectedNode;
149182
- const latestExecution = executions[executions.length - 1];
149183
- const hasMultipleAttempts = executions.length > 1;
149184
- const { data: stepData, loading: stepLoading } = useWorkflowResourceData(
149185
- env2 ?? {},
149186
- "step",
149187
- stepId ?? "",
149188
- { runId }
149189
- );
149190
- const resolvedInput = (stepData == null ? void 0 : stepData.input) ?? (latestExecution == null ? void 0 : latestExecution.input);
149191
- const resolvedOutput = (stepData == null ? void 0 : stepData.output) ?? (latestExecution == null ? void 0 : latestExecution.output);
149192
- const resolvedError = (stepData == null ? void 0 : stepData.error) ?? (latestExecution == null ? void 0 : latestExecution.error);
149193
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-background border-l", children: [
149194
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b flex-none", children: [
149195
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149196
- "span",
149197
- {
149198
- className: "text-xs font-medium truncate flex-1",
149199
- title: node2.data.label,
149200
- children: node2.data.label
149201
- }
149202
- ),
149203
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-none", children: [
149204
- (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) }),
149205
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-border" }),
149206
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149207
- "button",
149208
- {
149209
- type: "button",
149210
- onClick: onClose,
149211
- className: "p-1 rounded hover:bg-muted transition-colors",
149212
- "aria-label": "Close panel",
149213
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$3, { className: "h-4 w-4 text-muted-foreground" })
149214
- }
149215
- )
149216
- ] })
149217
- ] }),
149218
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto p-3 min-h-0", children: [
149219
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col divide-y rounded-lg border overflow-hidden mb-3", children: [
149220
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149221
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "type" }),
149222
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: node2.data.nodeKind })
149223
- ] }),
149224
- latestExecution && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
149225
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149226
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "status" }),
149227
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149228
- StatusBadge,
149229
- {
149230
- status: mapToStatusBadgeStatus(latestExecution.status)
149231
- }
149232
- )
149233
- ] }),
149234
- latestExecution.duration !== void 0 && latestExecution.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149235
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "duration" }),
149236
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: formatDuration(latestExecution.duration) })
149237
- ] }),
149238
- hasMultipleAttempts && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149239
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "attempts" }),
149240
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: executions.length })
149241
- ] }),
149242
- latestExecution.startedAt && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149243
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "startedAt" }),
149244
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: new Date(latestExecution.startedAt).toLocaleString() })
149245
- ] }),
149246
- latestExecution.completedAt && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-2.5 py-1.5", children: [
149247
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: "completedAt" }),
149248
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono", children: new Date(latestExecution.completedAt).toLocaleString() })
149249
- ] })
149250
- ] })
149251
- ] }),
149252
- stepLoading && stepId && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground mb-3", children: [
149253
- /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }),
149254
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Loading step data..." })
149255
- ] }),
149256
- resolvedInput !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", children: [
149257
- /* @__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: [
149258
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Input" }),
149259
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground ml-1", children: [
149260
- "(",
149261
- Array.isArray(resolvedInput) ? resolvedInput.length : 1,
149262
- " args)"
149263
- ] })
149264
- ] }),
149265
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149266
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149267
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149268
- /* @__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) }) })
149269
- ] })
149270
- ] }),
149271
- resolvedOutput !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", children: [
149272
- /* @__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" }) }),
149273
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149274
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149275
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149276
- /* @__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) }) })
149277
- ] })
149278
- ] }),
149279
- resolvedError && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group mb-3", open: true, children: [
149280
- /* @__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" }) }),
149281
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149282
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-red-300" }),
149283
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-red-300" }),
149284
- /* @__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) }) })
149285
- ] })
149286
- ] }),
149287
- hasMultipleAttempts && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "group", children: [
149288
- /* @__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: [
149289
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: "Attempt History" }),
149290
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground ml-1", children: [
149291
- "(",
149292
- executions.length,
149293
- " attempts)"
149294
- ] })
149295
- ] }),
149296
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative pl-6 mt-3", children: [
149297
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 -top-3 w-px h-3 bg-border" }),
149298
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-3 top-0 w-3 h-3 border-l border-b rounded-bl-lg border-border" }),
149299
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col divide-y rounded-md border overflow-hidden", children: executions.map((exec) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
149300
- "div",
149301
- {
149302
- className: "flex items-center justify-between px-2.5 py-1.5 text-[11px]",
149303
- children: [
149304
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
149305
- "Attempt ",
149306
- exec.attemptNumber
149307
- ] }),
149308
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149309
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149310
- StatusBadge,
149311
- {
149312
- status: mapToStatusBadgeStatus(exec.status)
149313
- }
149314
- ),
149315
- exec.duration !== void 0 && exec.duration > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-muted-foreground", children: formatDuration(exec.duration) })
149316
- ] })
149317
- ]
149318
- },
149319
- exec.attemptNumber
149320
- )) })
149321
- ] })
149322
- ] })
149323
- ] })
149324
- ] });
149325
- }
149326
- function WorkflowGraphExecutionViewer({
149327
- workflow,
149328
- execution,
149329
- env: env2,
149330
- onNodeClick
149331
- }) {
149332
- const [selectedNode, setSelectedNode] = reactExports.useState(
149333
- null
149334
- );
149335
- const panelWidth = 320;
149336
- const initialNodes = reactExports.useMemo(
149337
- () => convertToReactFlowNodes(workflow, execution),
149338
- [workflow, execution]
149339
- );
149340
- const initialEdges = reactExports.useMemo(
149341
- () => convertToReactFlowEdges(workflow, execution),
149342
- [workflow, execution]
149343
- );
149344
- const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
149345
- const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
149346
- reactExports.useEffect(() => {
149347
- setNodes((currentNodes) => {
149348
- const newNodes = convertToReactFlowNodes(workflow, execution);
149349
- const currentPositions = new Map(
149350
- currentNodes.map((n) => [n.id, n.position])
149351
- );
149352
- return newNodes.map((node2) => ({
149353
- ...node2,
149354
- position: currentPositions.get(node2.id) ?? node2.position
149355
- }));
149356
- });
149357
- setEdges(convertToReactFlowEdges(workflow, execution));
149358
- }, [workflow, execution, setNodes, setEdges]);
149359
- const handleNodeClick2 = reactExports.useCallback(
149360
- (_event, node2) => {
149361
- const graphNode = workflow.nodes.find((n) => n.id === node2.id);
149362
- if (graphNode) {
149363
- const executions = node2.data.executions || [];
149364
- const latestExecution = executions[executions.length - 1];
149365
- setSelectedNode({
149366
- nodeId: node2.id,
149367
- node: graphNode,
149368
- executions,
149369
- stepId: latestExecution == null ? void 0 : latestExecution.stepId,
149370
- runId: execution == null ? void 0 : execution.runId
149371
- });
149372
- if (onNodeClick && executions.length > 0) {
149373
- onNodeClick(node2.id, executions);
149374
- }
149375
- }
149376
- },
149377
- [workflow.nodes, execution == null ? void 0 : execution.runId, onNodeClick]
149378
- );
149379
- const handleClosePanel = reactExports.useCallback(() => {
149380
- setSelectedNode(null);
149381
- }, []);
149382
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full w-full border rounded-lg bg-background relative overflow-hidden flex", children: [
149383
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149384
- "div",
149385
- {
149386
- className: "h-full flex-1 min-w-0",
149387
- style: {
149388
- width: selectedNode ? `calc(100% - ${panelWidth}px)` : "100%"
149389
- },
149390
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
149391
- index,
149392
- {
149393
- nodes,
149394
- edges,
149395
- onNodesChange,
149396
- onEdgesChange,
149397
- onNodeClick: handleNodeClick2,
149398
- nodeTypes,
149399
- edgeTypes,
149400
- fitView: true,
149401
- minZoom: 0.1,
149402
- maxZoom: 2,
149403
- defaultViewport: { x: 0, y: 0, zoom: 1 },
149404
- proOptions: { hideAttribution: true },
149405
- children: [
149406
- /* @__PURE__ */ jsxRuntimeExports.jsx(Background, {}),
149407
- /* @__PURE__ */ jsxRuntimeExports.jsx(Controls, {}),
149408
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149409
- Panel,
149410
- {
149411
- position: "top-left",
149412
- className: "bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-lg p-2 text-xs",
149413
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
149414
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-[10px] text-muted-foreground mb-1", children: "Status" }),
149415
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149416
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-green-500 bg-background" }),
149417
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Completed" })
149418
- ] }),
149419
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149420
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-red-500 bg-background" }),
149421
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Failed" })
149422
- ] }),
149423
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149424
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-blue-500 bg-background" }),
149425
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Running" })
149426
- ] }),
149427
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149428
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-yellow-500 bg-background" }),
149429
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Cancelled" })
149430
- ] }),
149431
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 opacity-50", children: [
149432
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-4 rounded border-2 border-gray-400 bg-background" }),
149433
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Pending" })
149434
- ] })
149435
- ] })
149436
- }
149437
- ),
149438
- execution && /* @__PURE__ */ jsxRuntimeExports.jsxs(
149439
- Panel,
149440
- {
149441
- position: "top-right",
149442
- className: "bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-lg p-3 text-xs space-y-1.5",
149443
- children: [
149444
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-semibold text-sm", children: "Execution" }),
149445
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149446
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "Status:" }),
149447
- /* @__PURE__ */ jsxRuntimeExports.jsx(
149448
- Badge,
149449
- {
149450
- variant: execution.status === "completed" ? "default" : execution.status === "failed" ? "destructive" : execution.status === "cancelled" ? "outline" : "secondary",
149451
- className: "text-xs",
149452
- children: execution.status
149453
- }
149454
- )
149455
- ] }),
149456
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
149457
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: "Progress:" }),
149458
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", children: [
149459
- execution.executionPath.length,
149460
- " / ",
149461
- workflow.nodes.length
149462
- ] })
149463
- ] })
149464
- ]
149465
- }
149466
- )
149467
- ]
149468
- }
149469
- )
149470
- }
149471
- ),
149472
- selectedNode && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full flex-none", style: { width: panelWidth }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
149473
- GraphNodeDetailPanel,
149474
- {
149475
- selectedNode,
149476
- env: env2,
149477
- onClose: handleClosePanel
149478
- }
149479
- ) })
149480
- ] });
149481
- }
149482
- function GraphTabContent({
149483
- run,
149484
- allEvents,
149485
- env: env2
149486
- }) {
149487
- const {
149488
- manifest: graphManifest,
149489
- loading: graphLoading,
149490
- error: graphError
149491
- } = useWorkflowGraphManifest();
149492
- const workflowGraph = reactExports.useMemo(() => {
149493
- var _a3;
149494
- if (!graphManifest || !run.workflowName) return null;
149495
- const runWorkflowName = String(run.workflowName).trim();
149496
- const direct = graphManifest.workflows[runWorkflowName];
149497
- if (direct) return direct;
149498
- const runShortName = (_a3 = parseWorkflowName(runWorkflowName)) == null ? void 0 : _a3.shortName;
149499
- const workflows = Object.values(graphManifest.workflows);
149500
- return workflows.find((wf) => {
149501
- var _a4;
149502
- if (wf.workflowId === runWorkflowName) return true;
149503
- if (wf.workflowName === runWorkflowName) return true;
149504
- if (!runShortName) return false;
149505
- return ((_a4 = parseWorkflowName(wf.workflowName)) == null ? void 0 : _a4.shortName) === runShortName;
149506
- }) ?? null;
149507
- }, [graphManifest, run.workflowName]);
149508
- const stepsFromEvents = reactExports.useMemo(() => {
149509
- if (!allEvents) return [];
149510
- const stepEventsMap = /* @__PURE__ */ new Map();
149511
- for (const event of allEvents) {
149512
- if (event.eventType.startsWith("step_") && event.correlationId) {
149513
- const existing = stepEventsMap.get(event.correlationId);
149514
- if (existing) {
149515
- existing.push(event);
149516
- } else {
149517
- stepEventsMap.set(event.correlationId, [event]);
149518
- }
149519
- }
149520
- }
149521
- return Array.from(stepEventsMap.values()).map(stepEventsToStepEntity).filter((s2) => s2 !== null);
149522
- }, [allEvents]);
149523
- const execution = reactExports.useMemo(() => {
149524
- if (!workflowGraph || !run.runId) return null;
149525
- return mapRunToExecution(
149526
- run,
149527
- stepsFromEvents,
149528
- allEvents || [],
149529
- workflowGraph
149530
- );
149531
- }, [workflowGraph, run, stepsFromEvents, allEvents]);
149532
- if (graphLoading) {
149533
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center w-full h-full", children: [
149534
- /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-8 w-8 animate-spin text-muted-foreground" }),
149535
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-4 text-muted-foreground", children: "Loading workflow graph..." })
149536
- ] });
149537
- }
149538
- if (graphError) {
149539
- 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: [
149540
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
149541
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Error Loading Workflow Graph" }),
149542
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: graphError.message })
149543
- ] }) });
149544
- }
149545
- if (!workflowGraph) {
149546
- 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: [
149547
- /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
149548
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Workflow Graph Not Found" }),
149549
- /* @__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." })
149550
- ] }) });
149551
- }
149552
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
149553
- WorkflowGraphExecutionViewer,
149554
- {
149555
- workflow: workflowGraph,
149556
- execution: execution || void 0,
149557
- env: env2
149558
- }
149559
- );
149560
- }
148572
+ });
149561
148573
  function RunDetailView({
149562
148574
  runId,
149563
148575
  // TODO: This should open the right sidebar within the trace viewer
@@ -149572,7 +148584,8 @@ function RunDetailView({
149572
148584
  const [showCancelDialog, setShowCancelDialog] = reactExports.useState(false);
149573
148585
  const [showRerunDialog, setShowRerunDialog] = reactExports.useState(false);
149574
148586
  const env2 = reactExports.useMemo(() => ({}), []);
149575
- const activeTab = searchParams.get("tab") || "trace";
148587
+ const rawTab = searchParams.get("tab") || "trace";
148588
+ const activeTab = rawTab === "graph" ? "trace" : rawTab;
149576
148589
  const selectedStreamId = searchParams.get("streamId");
149577
148590
  const updateSearchParams = reactExports.useCallback(
149578
148591
  (updates) => {
@@ -149655,7 +148668,7 @@ function RunDetailView({
149655
148668
  },
149656
148669
  [env2, runId]
149657
148670
  );
149658
- const isLocalBackend = serverConfig.backendId === "local" || serverConfig.backendId === "@workflow/world-local";
148671
+ serverConfig.backendId === "local" || serverConfig.backendId === "@workflow/world-local";
149659
148672
  const {
149660
148673
  run: runData,
149661
148674
  events: allEvents,
@@ -149908,10 +148921,7 @@ function RunDetailView({
149908
148921
  /* @__PURE__ */ jsxRuntimeExports.jsx(List$1, { className: "h-4 w-4" }),
149909
148922
  "Trace"
149910
148923
  ] }),
149911
- isLocalBackend && /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "graph", className: "gap-2", children: [
149912
- /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "h-4 w-4" }),
149913
- "Graph"
149914
- ] }),
148924
+ false,
149915
148925
  /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "events", className: "gap-2", children: [
149916
148926
  /* @__PURE__ */ jsxRuntimeExports.jsx(List$1, { className: "h-4 w-4" }),
149917
148927
  "Events"
@@ -150071,14 +149081,7 @@ function RunDetailView({
150071
149081
  }
150072
149082
  ) })
150073
149083
  ] }) }) }),
150074
- 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(
150075
- GraphTabContent,
150076
- {
150077
- run,
150078
- allEvents,
150079
- env: env2
150080
- }
150081
- ) }) }) })
149084
+ false
150082
149085
  ]
150083
149086
  }
150084
149087
  ) })
@@ -150254,7 +149257,7 @@ const route4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
150254
149257
  __proto__: null,
150255
149258
  loader
150256
149259
  }, Symbol.toStringTag, { value: "Module" }));
150257
- 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-CxkGJJO9.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/mermaid-3ZIDBTTL-D6v4WgFl.js"], "css": ["/assets/root-DUJPWGN3.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-C884R8Ik.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/use-workflow-graph-WEp5s5k_.js", "/assets/mermaid-3ZIDBTTL-D6v4WgFl.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-D_eXHYm3.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/use-workflow-graph-WEp5s5k_.js", "/assets/mermaid-3ZIDBTTL-D6v4WgFl.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-14123a0c.js", "version": "14123a0c", "sri": void 0 };
149260
+ 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-CADywoAy.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/mermaid-3ZIDBTTL-ClWSYlBT.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-Bg63MGns.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/workflow-graph-viewer-RUyTSlHH.js", "/assets/mermaid-3ZIDBTTL-ClWSYlBT.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-CX8hD4AT.js", "imports": ["/assets/index-DklpUtP3.js", "/assets/workflow-graph-viewer-RUyTSlHH.js", "/assets/mermaid-3ZIDBTTL-ClWSYlBT.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-f52831b8.js", "version": "f52831b8", "sri": void 0 };
150258
149261
  const assetsBuildDirectory = "build/client";
150259
149262
  const basename = "/";
150260
149263
  const future = { "unstable_optimizeDeps": false, "unstable_subResourceIntegrity": false, "unstable_trailingSlashAwareDataRequests": false, "unstable_previewServerPrerendering": false, "v8_middleware": false, "v8_splitRouteModules": false, "v8_viteEnvironmentApi": false };