@voltro/workflow 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2501 @@
1
+ import { E as e, F as t, I as n, M as r, N as i, P as a, T as o, w as s } from "./primitives-CyQZeT1t.js";
2
+ import { Activity as c, DurableClock as l, DurableDeferred as u, Workflow as d, WorkflowEngine as f } from "@effect/workflow";
3
+ import { Cause as p, Effect as m, Either as h, Exit as g, FiberRef as _, Layer as v, Schema as y } from "effect";
4
+ import { and as b, boolean as ee, eq as x, generateId as S, gt as C, gte as te, id as w, inSet as ne, integer as T, isNull as E, json as D, lt as O, or as k, queryFor as A, reference as re, registerRetention as ie, retentionTtlMsFromEnv as ae, table as j, text as M, timestamp as N } from "@voltro/database";
5
+ import { createHash as oe } from "node:crypto";
6
+ import { WorkflowInstance as se } from "@effect/workflow/WorkflowEngine";
7
+ import { publishServerError as ce } from "@voltro/protocol";
8
+ //#region src/inMemoryLayer.ts
9
+ var le = f.layerMemory, P = j("_voltro_workflow_runs", {
10
+ id: w({ prefix: "wfrun" }),
11
+ tag: M(),
12
+ executionId: M().unique(),
13
+ status: M().oneOf([
14
+ "running",
15
+ "succeeded",
16
+ "failed",
17
+ "cancelled",
18
+ "suspended"
19
+ ]).default("running"),
20
+ payload: D(),
21
+ workflowVersion: M().nullable(),
22
+ workflowPatches: D().nullable(),
23
+ runnerEnteredAt: N().nullable(),
24
+ reclaimCount: T().default(0),
25
+ output: D().nullable(),
26
+ subject: D().nullable(),
27
+ source: M().nullable(),
28
+ errorTag: M().nullable(),
29
+ errorMessage: M().nullable(),
30
+ cancelled: ee().default(!1),
31
+ discardedAt: N().nullable(),
32
+ discardedBy: M().nullable(),
33
+ startedAt: N().default("now"),
34
+ completedAt: N().nullable(),
35
+ durationMs: T().nullable(),
36
+ traceId: M().nullable(),
37
+ parentExecutionId: M().nullable(),
38
+ parentClosePolicy: M().oneOf([
39
+ "cancel",
40
+ "terminate",
41
+ "abandon"
42
+ ]).nullable()
43
+ }).index(["tag"]).index(["status"]).index(["source"]).index(["startedAt"]).index(["parentExecutionId"]).index(["parentClosePolicy"]), ue = j("_voltro_workflow_run_steps", {
44
+ id: w({ prefix: "wfstep" }),
45
+ runId: re(() => P, {
46
+ index: !1,
47
+ onDelete: "cascade"
48
+ }),
49
+ stepName: M(),
50
+ attempt: T().default(1),
51
+ status: M().oneOf([
52
+ "running",
53
+ "succeeded",
54
+ "failed"
55
+ ]).default("running"),
56
+ input: D().nullable(),
57
+ retryPolicy: D().nullable(),
58
+ output: D().nullable(),
59
+ errorTag: M().nullable(),
60
+ errorMessage: M().nullable(),
61
+ errorCause: D().nullable(),
62
+ startedAt: N().default("now"),
63
+ completedAt: N().nullable(),
64
+ durationMs: T().nullable()
65
+ }).index(["runId", "stepName"]).index(["startedAt"]), de = j("_voltro_workflow_run_events", {
66
+ id: w({ prefix: "wfev" }),
67
+ runId: re(() => P, {
68
+ index: !1,
69
+ onDelete: "cascade"
70
+ }),
71
+ eventType: M(),
72
+ payload: D().nullable(),
73
+ occurredAt: N().default("now"),
74
+ stepName: M().nullable(),
75
+ attempt: T().nullable()
76
+ }).index(["runId", "occurredAt"]).index(["eventType"]), fe = j("_voltro_workflow_start_contexts", {
77
+ id: w({ prefix: "wfctx" }),
78
+ workflowName: M(),
79
+ executionId: M().unique(),
80
+ subject: D().nullable(),
81
+ traceId: M().nullable(),
82
+ source: M().nullable(),
83
+ parentExecutionId: M().nullable(),
84
+ parentClosePolicy: M().oneOf([
85
+ "cancel",
86
+ "terminate",
87
+ "abandon"
88
+ ]).nullable(),
89
+ createdAt: N().default("now")
90
+ }).index(["workflowName"]).index(["executionId"]).index(["parentExecutionId"]), pe = j("_voltro_workflow_pending", {
91
+ id: w({ prefix: "wfp" }),
92
+ tenantId: M().nullable(),
93
+ workflowName: M(),
94
+ controlKey: M(),
95
+ mode: M().oneOf([
96
+ "debounce",
97
+ "batch",
98
+ "throttle",
99
+ "concurrency",
100
+ "paused"
101
+ ]),
102
+ payload: D(),
103
+ callerContext: D().nullable(),
104
+ priority: T().default(0),
105
+ dueAt: N(),
106
+ deadlineAt: N().nullable(),
107
+ collapsed: T().default(1),
108
+ firstSeenAt: N().default("now"),
109
+ updatedAt: N().default("now"),
110
+ attempts: T().default(0),
111
+ lastError: M().nullable()
112
+ }).index(["workflowName", "controlKey"]).index(["dueAt"]).index(["workflowName", "mode"]).index(["tenantId"]), me = j("_voltro_workflow_admissions", {
113
+ id: w({ prefix: "wfadm" }),
114
+ tenantId: M().nullable(),
115
+ workflowName: M(),
116
+ outcome: M().oneOf([
117
+ "admitted",
118
+ "dropped",
119
+ "skipped",
120
+ "evicted",
121
+ "expired",
122
+ "discarded"
123
+ ]),
124
+ mode: M().nullable(),
125
+ reason: M().nullable(),
126
+ collapsed: T().default(1),
127
+ waitedMs: T().nullable(),
128
+ executionId: M().nullable(),
129
+ runId: M().nullable(),
130
+ singletonKey: M().nullable(),
131
+ concurrencyKey: M().nullable(),
132
+ rateKey: M().nullable(),
133
+ admittedAt: N().default("now"),
134
+ expiresAt: N().nullable(),
135
+ releasedAt: N().nullable()
136
+ }).index(["workflowName", "admittedAt"]).index(["concurrencyKey", "releasedAt"]).index(["singletonKey", "releasedAt"]).index(["rateKey", "admittedAt"]).index(["executionId"]).index(["tenantId"]), he = j("_voltro_workflow_pauses", {
137
+ id: w({ prefix: "wfpause" }),
138
+ pausedAt: N().default("now"),
139
+ pausedBy: M().nullable(),
140
+ reason: M().nullable()
141
+ }), ge = class extends Error {
142
+ workflowName;
143
+ field;
144
+ constructor(e, t, n) {
145
+ super(`workflow '${e}': ${t}(payload) threw — a flow-control key function must be total over every payload the workflow accepts, because it runs before the run exists and there is nowhere to report a partial failure to. Cause: ${n instanceof Error ? n.message : String(n)}`), this.name = "FlowControlKeyError", this.workflowName = e, this.field = t, this.cause = n;
146
+ }
147
+ }, F = (e, t, n, r) => {
148
+ try {
149
+ let e = n(r);
150
+ if (typeof e != "string" || e.length === 0) throw Error(`returned ${e === "" ? "an empty string" : String(e)}; expected a non-empty string`);
151
+ return e;
152
+ } catch (n) {
153
+ throw new ge(e, t, n);
154
+ }
155
+ }, _e = (e, t) => e === void 0 ? t : `pool\u0000${e}\u0000${t}`, I = (e, t) => {
156
+ let n = e.workflowName, r = 0;
157
+ if (e.priority !== void 0) try {
158
+ let n = e.priority(t);
159
+ if (!Number.isFinite(n)) throw Error(`returned ${String(n)}; expected a finite number`);
160
+ r = Math.trunc(n);
161
+ } catch (e) {
162
+ throw new ge(n, "priority", e);
163
+ }
164
+ return {
165
+ ...e.debounce === void 0 ? {} : { debounceKey: F(n, "debounce.key", e.debounce.key, t) },
166
+ ...e.singleton === void 0 ? {} : { singletonKey: F(n, "singleton.key", e.singleton.key, t) },
167
+ ...e.concurrency === void 0 ? {} : { concurrencyKey: _e(e.concurrency.pool, e.concurrency.key === void 0 ? "" : F(n, "concurrency.key", e.concurrency.key, t)) },
168
+ ...e.throttle?.key === void 0 ? e.throttle === void 0 ? {} : { throttleKey: "" } : { throttleKey: F(n, "throttle.key", e.throttle.key, t) },
169
+ ...e.rateLimit?.key === void 0 ? e.rateLimit === void 0 ? {} : { rateLimitKey: "" } : { rateLimitKey: F(n, "rateLimit.key", e.rateLimit.key, t) },
170
+ ...e.batch?.key === void 0 ? e.batch === void 0 ? {} : { batchKey: "" } : { batchKey: F(n, "batch.key", e.batch.key, t) },
171
+ priority: r
172
+ };
173
+ }, ve = (e, t, n, r) => {
174
+ let i = e.filter((e) => e > r - n);
175
+ if (i.length < t) return;
176
+ let a = [...i].sort((e, t) => t - e)[t - 1];
177
+ if (a !== void 0) return a + n;
178
+ }, ye = (e) => {
179
+ let { control: t, keys: n, state: r, now: i, reconsidering: a } = e;
180
+ if (r.paused === !0) return {
181
+ kind: "defer",
182
+ mode: "paused",
183
+ dueAt: i,
184
+ collapse: a ? "hold" : "append",
185
+ keys: n
186
+ };
187
+ if (t.rateLimit !== void 0) {
188
+ let e = ve(r.recentAdmissions ?? [], t.rateLimit.limit, t.rateLimit.periodMs, i);
189
+ if (e !== void 0) return {
190
+ kind: "drop",
191
+ reason: "rate-limit",
192
+ retryAfterMs: Math.max(0, e - i),
193
+ keys: n
194
+ };
195
+ }
196
+ if (t.singleton !== void 0 && t.singleton.mode === "skip" && r.singletonHolder !== void 0) return {
197
+ kind: "skip",
198
+ incumbent: r.singletonHolder,
199
+ keys: n
200
+ };
201
+ if (t.debounce !== void 0) {
202
+ let e = r.debouncePending, o = e?.firstSeenAt ?? i, s = e?.deadlineAt ?? (t.debounce.timeoutMs === void 0 ? void 0 : o + t.debounce.timeoutMs);
203
+ return a ? s !== void 0 && i >= s ? {
204
+ kind: "admit",
205
+ reason: "debounce-deadline",
206
+ keys: n,
207
+ ...L(t, r)
208
+ } : {
209
+ kind: "admit",
210
+ reason: "debounce-elapsed",
211
+ keys: n,
212
+ ...L(t, r)
213
+ } : {
214
+ kind: "defer",
215
+ mode: "debounce",
216
+ dueAt: s === void 0 ? i + t.debounce.periodMs : Math.min(i + t.debounce.periodMs, s),
217
+ ...s === void 0 ? {} : { deadlineAt: s },
218
+ collapse: "replace",
219
+ keys: n
220
+ };
221
+ }
222
+ if (t.batch !== void 0) {
223
+ let e = r.batchPending, o = (e?.count ?? 0) + +!a, s = (e?.firstSeenAt ?? i) + t.batch.timeoutMs;
224
+ return o >= t.batch.maxSize ? {
225
+ kind: "admit",
226
+ reason: "batch-full",
227
+ keys: n,
228
+ ...L(t, r)
229
+ } : a && i >= s ? {
230
+ kind: "admit",
231
+ reason: "batch-timeout",
232
+ keys: n,
233
+ ...L(t, r)
234
+ } : {
235
+ kind: "defer",
236
+ mode: "batch",
237
+ dueAt: s,
238
+ collapse: a ? "hold" : "append",
239
+ keys: n
240
+ };
241
+ }
242
+ if (t.throttle !== void 0) {
243
+ let e = ve(r.recentAdmissions ?? [], t.throttle.limit, t.throttle.periodMs, i);
244
+ if (e !== void 0) return {
245
+ kind: "defer",
246
+ mode: "throttle",
247
+ dueAt: e,
248
+ collapse: a ? "hold" : "append",
249
+ keys: n
250
+ };
251
+ }
252
+ return t.concurrency !== void 0 && (r.inFlight ?? 0) >= t.concurrency.limit ? {
253
+ kind: "defer",
254
+ mode: "concurrency",
255
+ dueAt: i,
256
+ collapse: a ? "hold" : "append",
257
+ keys: n
258
+ } : {
259
+ kind: "admit",
260
+ reason: be(t) ? "under-limits" : "no-controls",
261
+ keys: n,
262
+ ...L(t, r)
263
+ };
264
+ }, be = (e) => e.debounce !== void 0 || e.singleton !== void 0 || e.concurrency !== void 0 || e.throttle !== void 0 || e.rateLimit !== void 0 || e.batch !== void 0, L = (e, t) => e.singleton?.mode === "cancel" && t.singletonHolder !== void 0 ? { evict: t.singletonHolder } : {}, xe = (e, t, n) => {
265
+ let r = e.timeouts?.startMs;
266
+ return r !== void 0 && n - t.firstSeenAt >= r;
267
+ }, Se = (e, t, n) => {
268
+ let r = e.timeouts?.finishMs;
269
+ return r === void 0 || t.terminal ? !1 : n - t.startedAt >= r;
270
+ }, Ce = (e, t) => e.priority === t.priority ? e.firstSeenAt === t.firstSeenAt ? e.id < t.id ? -1 : +(e.id > t.id) : e.firstSeenAt - t.firstSeenAt : t.priority - e.priority, R = "_voltro_workflow_pending", z = "_voltro_workflow_admissions", we = "_voltro_workflow_pauses", Te = 1440 * 60 * 1e3, Ee = (e, t, n) => `wfp_${oe("sha256").update(`${e}\u0000${t}\u0000${n}`).digest("hex").slice(0, 40)}`, B = (e) => {
271
+ if (e instanceof Date) return e.getTime();
272
+ if (typeof e == "number") return e;
273
+ let t = Date.parse(String(e));
274
+ return Number.isNaN(t) ? 0 : t;
275
+ }, V = (e, t) => {
276
+ let n = typeof e == "number" ? e : Number(e);
277
+ return Number.isFinite(n) ? Math.trunc(n) : t;
278
+ }, De = (e) => ({
279
+ id: String(e.id),
280
+ tenantId: e.tenantId === null || e.tenantId === void 0 ? null : String(e.tenantId),
281
+ workflowName: String(e.workflowName),
282
+ controlKey: String(e.controlKey ?? ""),
283
+ mode: String(e.mode),
284
+ payload: e.payload,
285
+ callerContext: e.callerContext ?? null,
286
+ priority: V(e.priority, 0),
287
+ dueAt: B(e.dueAt),
288
+ deadlineAt: e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt),
289
+ collapsed: V(e.collapsed, 1),
290
+ firstSeenAt: B(e.firstSeenAt),
291
+ attempts: V(e.attempts, 0),
292
+ lastError: e.lastError === null || e.lastError === void 0 ? null : String(e.lastError)
293
+ }), H = (e, t, n, r) => ({
294
+ table: e,
295
+ predicate: t,
296
+ order: n,
297
+ take: r,
298
+ skip: void 0,
299
+ projection: void 0
300
+ }), Oe = async (e) => {
301
+ let t = await e.query(H(we, void 0, [], 1e3));
302
+ return new Set(t.map((e) => String(e.id)));
303
+ }, ke = async (e, t, n, r) => {
304
+ await e.upsert(we, {
305
+ id: t,
306
+ pausedAt: /* @__PURE__ */ new Date(),
307
+ pausedBy: n,
308
+ reason: r
309
+ }, {
310
+ conflictColumns: ["id"],
311
+ update: [
312
+ "pausedAt",
313
+ "pausedBy",
314
+ "reason"
315
+ ]
316
+ });
317
+ }, Ae = async (e, t) => e.delete(we, t), je = async (e) => {
318
+ let { store: t, control: n, keys: r, now: i } = e, a = { paused: e.paused }, o = [];
319
+ n.debounce !== void 0 && r.debounceKey !== void 0 && o.push((async () => {
320
+ let e = (await t.query(H(R, b(x("workflowName", n.workflowName), x("controlKey", r.debounceKey), x("mode", "debounce")), [], 1)))[0];
321
+ if (e === void 0) return;
322
+ let i = e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt);
323
+ a.debouncePending = {
324
+ firstSeenAt: B(e.firstSeenAt),
325
+ collapsed: V(e.collapsed, 1),
326
+ ...i === void 0 ? {} : { deadlineAt: i }
327
+ };
328
+ })()), n.batch !== void 0 && r.batchKey !== void 0 && o.push((async () => {
329
+ let e = await t.query(H(R, b(x("workflowName", n.workflowName), x("controlKey", r.batchKey), x("mode", "batch")), [{
330
+ column: "firstSeenAt",
331
+ direction: "asc"
332
+ }], n.batch.maxSize + 1));
333
+ e.length !== 0 && (a.batchPending = {
334
+ count: e.length,
335
+ firstSeenAt: B(e[0].firstSeenAt)
336
+ });
337
+ })()), n.singleton !== void 0 && r.singletonKey !== void 0 && o.push((async () => {
338
+ let e = await Me(t, n.workflowName, r.singletonKey, i);
339
+ e !== void 0 && (a.singletonHolder = e);
340
+ })()), n.concurrency !== void 0 && r.concurrencyKey !== void 0 && o.push((async () => {
341
+ let e = n.concurrency.pool === void 0 ? [x("workflowName", n.workflowName)] : [], o = await t.query(H(z, b(...e, x("concurrencyKey", r.concurrencyKey), E("releasedAt"), C("expiresAt", new Date(i))), [], n.concurrency.limit));
342
+ a.inFlight = o.length;
343
+ })());
344
+ let s = n.rateLimit ?? n.throttle, c = r.rateLimitKey ?? r.throttleKey;
345
+ return s !== void 0 && c !== void 0 && o.push((async () => {
346
+ let e = await t.query(H(z, b(x("workflowName", n.workflowName), x("rateKey", c), x("outcome", "admitted"), C("admittedAt", new Date(i - s.periodMs))), [{
347
+ column: "admittedAt",
348
+ direction: "desc"
349
+ }], s.limit));
350
+ a.recentAdmissions = e.map((e) => B(e.admittedAt));
351
+ })()), await Promise.all(o), a;
352
+ }, Me = async (e, t, n, r) => {
353
+ let i = (await e.query(H(z, b(x("workflowName", t), x("singletonKey", n), E("releasedAt"), C("expiresAt", new Date(r))), [{
354
+ column: "admittedAt",
355
+ direction: "desc"
356
+ }], 1)))[0];
357
+ if (i === void 0) return;
358
+ let a = i.executionId;
359
+ if (a != null) return {
360
+ executionId: String(a),
361
+ runId: i.runId === null || i.runId === void 0 ? "" : String(i.runId),
362
+ admittedAt: B(i.admittedAt)
363
+ };
364
+ }, Ne = async (e) => {
365
+ let { store: t, control: n, decision: r, now: i } = e, a = Fe(r.mode, r.keys);
366
+ if (r.collapse === "hold") {
367
+ let o = e.existingId ?? Ee(n.workflowName, r.mode, a);
368
+ return await t.update(R, o, {
369
+ dueAt: new Date(r.dueAt),
370
+ updatedAt: new Date(i)
371
+ }), o;
372
+ }
373
+ if (r.collapse === "replace") {
374
+ let o = Ee(n.workflowName, r.mode, a);
375
+ return await t.upsert(R, {
376
+ id: o,
377
+ tenantId: e.tenantId,
378
+ workflowName: n.workflowName,
379
+ controlKey: a,
380
+ mode: r.mode,
381
+ payload: e.payload,
382
+ callerContext: e.callerContext ?? null,
383
+ priority: r.keys.priority,
384
+ dueAt: new Date(r.dueAt),
385
+ deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
386
+ collapsed: 1,
387
+ firstSeenAt: new Date(i),
388
+ updatedAt: new Date(i),
389
+ attempts: 0,
390
+ lastError: null
391
+ }, {
392
+ conflictColumns: ["id"],
393
+ update: (t) => ({
394
+ payload: e.payload,
395
+ callerContext: e.callerContext ?? null,
396
+ priority: r.keys.priority,
397
+ dueAt: new Date(r.dueAt),
398
+ deadlineAt: r.deadlineAt === void 0 ? t.deadlineAt ?? null : new Date(r.deadlineAt),
399
+ collapsed: V(t.collapsed, 1) + 1,
400
+ updatedAt: new Date(i)
401
+ })
402
+ }), o;
403
+ }
404
+ let o = await t.insert(R, {
405
+ tenantId: e.tenantId,
406
+ workflowName: n.workflowName,
407
+ controlKey: a,
408
+ mode: r.mode,
409
+ payload: e.payload,
410
+ callerContext: e.callerContext ?? null,
411
+ priority: r.keys.priority,
412
+ dueAt: new Date(r.dueAt),
413
+ deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
414
+ collapsed: 1,
415
+ firstSeenAt: new Date(i),
416
+ updatedAt: new Date(i),
417
+ attempts: 0,
418
+ lastError: null
419
+ });
420
+ return String(o.id);
421
+ }, Pe = async (e) => {
422
+ let t = await e.store.insert(R, {
423
+ tenantId: e.tenantId,
424
+ workflowName: e.workflowName,
425
+ controlKey: "",
426
+ mode: "delayed",
427
+ payload: e.payload,
428
+ callerContext: e.callerContext ?? null,
429
+ priority: 0,
430
+ dueAt: new Date(e.at),
431
+ deadlineAt: null,
432
+ collapsed: 1,
433
+ firstSeenAt: new Date(e.now),
434
+ updatedAt: new Date(e.now),
435
+ attempts: 0,
436
+ lastError: null
437
+ });
438
+ return {
439
+ intentId: String(t.id),
440
+ dueAt: e.at
441
+ };
442
+ }, Fe = (e, t) => {
443
+ switch (e) {
444
+ case "debounce": return t.debounceKey ?? "";
445
+ case "batch": return t.batchKey ?? "";
446
+ case "throttle": return t.throttleKey ?? "";
447
+ case "concurrency": return t.concurrencyKey ?? "";
448
+ default: return "";
449
+ }
450
+ }, U = async (e) => {
451
+ let { control: t, keys: n, now: r } = e, i = t.timeouts?.finishMs ?? 864e5, a = await e.store.insert(z, {
452
+ tenantId: e.tenantId,
453
+ workflowName: t.workflowName,
454
+ outcome: e.outcome,
455
+ mode: e.mode,
456
+ reason: e.reason,
457
+ collapsed: e.collapsed,
458
+ waitedMs: e.waitedMs,
459
+ executionId: e.executionId,
460
+ runId: e.runId,
461
+ singletonKey: n.singletonKey ?? null,
462
+ concurrencyKey: n.concurrencyKey ?? null,
463
+ rateKey: n.rateLimitKey ?? n.throttleKey ?? null,
464
+ admittedAt: new Date(r),
465
+ expiresAt: e.outcome === "admitted" ? new Date(r + i) : null,
466
+ releasedAt: e.outcome === "admitted" ? null : new Date(r)
467
+ });
468
+ return String(a.id);
469
+ }, W = async (e, t, n) => {
470
+ let r = await e.query(H(z, b(x("executionId", t), x("outcome", "admitted"), E("releasedAt")), [], 10));
471
+ return r.length === 0 ? !1 : (await Promise.all(r.map((t) => e.update(z, String(t.id), { releasedAt: new Date(n) }))), !0);
472
+ }, Ie = async (e, t, n) => (await Le(e, t, n)).due, Le = async (e, t, n) => {
473
+ let r = (await e.query(H(R, void 0, [{
474
+ column: "priority",
475
+ direction: "desc"
476
+ }, {
477
+ column: "firstSeenAt",
478
+ direction: "asc"
479
+ }], n))).map(De), i;
480
+ for (let e of r) e.dueAt <= t || (i === void 0 || e.dueAt < i) && (i = e.dueAt);
481
+ return {
482
+ due: r.filter((e) => e.dueAt <= t).sort(Ce),
483
+ nextDueAt: i
484
+ };
485
+ }, Re = async (e, t) => (await e.query(H(R, void 0, [{
486
+ column: "firstSeenAt",
487
+ direction: "asc"
488
+ }], t))).map(De), G = async (e, t) => e.delete(R, t), ze = async (e, t, n, r) => {
489
+ let i = (await e.query(H(R, x("id", t), [], 1)))[0];
490
+ if (i === void 0) return !1;
491
+ let a = De(i);
492
+ try {
493
+ await e.insert(z, {
494
+ tenantId: a.tenantId,
495
+ workflowName: a.workflowName,
496
+ outcome: "discarded",
497
+ mode: a.mode,
498
+ reason: n,
499
+ collapsed: a.collapsed,
500
+ waitedMs: Math.max(0, r - a.firstSeenAt),
501
+ executionId: null,
502
+ runId: null,
503
+ singletonKey: null,
504
+ concurrencyKey: a.controlKey === "" ? null : a.controlKey,
505
+ rateKey: null,
506
+ admittedAt: new Date(r),
507
+ expiresAt: null,
508
+ releasedAt: new Date(r)
509
+ });
510
+ } catch {}
511
+ return e.delete(R, t);
512
+ }, Be = async (e, t, n, r) => {
513
+ await e.update(R, t.id, {
514
+ attempts: t.attempts + 1,
515
+ lastError: n.slice(0, 500),
516
+ updatedAt: new Date(r)
517
+ });
518
+ }, Ve = async (e) => {
519
+ let t = await je({
520
+ store: e.store,
521
+ control: e.control,
522
+ keys: e.keys,
523
+ now: e.now,
524
+ paused: e.paused
525
+ });
526
+ return ye({
527
+ control: e.control,
528
+ keys: e.keys,
529
+ state: t,
530
+ now: e.now,
531
+ reconsidering: e.reconsidering
532
+ });
533
+ }, He = async (e, t, n = 1e3) => {
534
+ let r = await e.query(H(z, void 0, [{
535
+ column: "admittedAt",
536
+ direction: "asc"
537
+ }], n)), i = t.getTime(), a = r.filter((e) => e.releasedAt != null && B(e.admittedAt) < i);
538
+ return await Promise.all(a.map((t) => e.delete(z, String(t.id)))), a.length;
539
+ }, Ue = async (e) => {
540
+ let { store: t, control: n, now: r } = e, i = I(n, e.payload), a = await Ve({
541
+ store: t,
542
+ control: n,
543
+ keys: i,
544
+ paused: e.paused,
545
+ now: r,
546
+ reconsidering: !1
547
+ });
548
+ if (a.kind === "drop") return await U({
549
+ store: t,
550
+ control: n,
551
+ keys: i,
552
+ outcome: "dropped",
553
+ mode: "rateLimit",
554
+ reason: `rate limit reached; retry after ${a.retryAfterMs}ms`,
555
+ collapsed: 1,
556
+ waitedMs: 0,
557
+ executionId: null,
558
+ runId: null,
559
+ tenantId: e.tenantId,
560
+ now: r
561
+ }), {
562
+ kind: "dropped",
563
+ retryAfterMs: a.retryAfterMs
564
+ };
565
+ if (a.kind === "skip") return await U({
566
+ store: t,
567
+ control: n,
568
+ keys: i,
569
+ outcome: "skipped",
570
+ mode: "singleton",
571
+ reason: `singleton key held by ${a.incumbent.executionId}`,
572
+ collapsed: 1,
573
+ waitedMs: 0,
574
+ executionId: a.incumbent.executionId,
575
+ runId: a.incumbent.runId || null,
576
+ tenantId: e.tenantId,
577
+ now: r
578
+ }), {
579
+ kind: "skipped",
580
+ executionId: a.incumbent.executionId,
581
+ runId: a.incumbent.runId
582
+ };
583
+ if (a.kind === "defer") return {
584
+ kind: "queued",
585
+ intentId: await Ne({
586
+ store: t,
587
+ control: n,
588
+ decision: a,
589
+ payload: e.payload,
590
+ callerContext: e.callerContext,
591
+ tenantId: e.tenantId,
592
+ now: r
593
+ }),
594
+ mode: a.mode,
595
+ dueAt: a.dueAt
596
+ };
597
+ let o = e.payload, s = [], c = 1;
598
+ if (n.batch !== void 0 && i.batchKey !== void 0) {
599
+ let r = await We(t, n.workflowName, i.batchKey, n.batch.maxSize);
600
+ o = { items: [...r.map((e) => e.payload), e.payload] }, s = r.map((e) => e.id), c = r.length + 1;
601
+ }
602
+ return {
603
+ kind: "start",
604
+ ledgerId: await U({
605
+ store: t,
606
+ control: n,
607
+ keys: i,
608
+ outcome: "admitted",
609
+ mode: e.waiting ? "immediate" : null,
610
+ reason: a.reason,
611
+ collapsed: c,
612
+ waitedMs: 0,
613
+ executionId: null,
614
+ runId: null,
615
+ tenantId: e.tenantId,
616
+ now: r
617
+ }),
618
+ keys: i,
619
+ payload: o,
620
+ consume: s,
621
+ collapsed: c,
622
+ ...a.evict === void 0 ? {} : { evict: {
623
+ executionId: a.evict.executionId,
624
+ runId: a.evict.runId
625
+ } }
626
+ };
627
+ }, We = async (e, t, n, r) => (await e.query({
628
+ table: "_voltro_workflow_pending",
629
+ predicate: b(x("workflowName", t), x("controlKey", n), x("mode", "batch")),
630
+ order: [{
631
+ column: "firstSeenAt",
632
+ direction: "asc"
633
+ }],
634
+ take: r,
635
+ skip: void 0,
636
+ projection: void 0
637
+ })).map((e) => ({
638
+ id: String(e.id),
639
+ payload: e.payload
640
+ })), Ge = async (e, t, n, r) => {
641
+ await e.update("_voltro_workflow_admissions", t, {
642
+ executionId: n,
643
+ runId: r
644
+ });
645
+ }, Ke = j("_voltro_workflow_watermarks", {
646
+ id: w({ prefix: "wfwm" }),
647
+ positionAt: N(),
648
+ updatedAt: N().default("now")
649
+ }), qe = (e) => {
650
+ let t = e instanceof Error ? e.message : String(e);
651
+ return t.length > 400 ? `${t.slice(0, 400)}…` : t;
652
+ }, Je = (e) => {
653
+ let t = [], n = [], r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = e.payloadSchema === void 0 ? (e) => h.right(e) : (t) => {
654
+ let n = y.decodeUnknownEither(e.payloadSchema)(t);
655
+ return h.isRight(n) ? h.right(n.right) : h.left(qe(n.left));
656
+ }, s = e.runs.map((e) => ({
657
+ run: e,
658
+ decoded: o(e.payload)
659
+ })), c = e.intents.map((e) => ({
660
+ intent: e,
661
+ decoded: o(e.payload)
662
+ }));
663
+ for (let o of e.entries) for (let l of e.events) {
664
+ if (l.name !== o.event) continue;
665
+ let u = y.decodeUnknownEither(o.schema)(l.payload);
666
+ if (h.isLeft(u)) {
667
+ r.push({
668
+ kind: "event-decode",
669
+ workflowName: e.workflowName,
670
+ event: o.event,
671
+ subject: l.id,
672
+ detail: qe(u.left)
673
+ });
674
+ continue;
675
+ }
676
+ let d = u.right, f = (e) => e.getTime() > l.occurredAt.getTime() ? !1 : o.withinMs === void 0 || l.occurredAt.getTime() - e.getTime() <= o.withinMs, p = (t, n) => {
677
+ if (h.isLeft(t)) return r.push({
678
+ kind: "payload-decode",
679
+ workflowName: e.workflowName,
680
+ event: o.event,
681
+ subject: n,
682
+ detail: t.left
683
+ }), !1;
684
+ try {
685
+ return o.match(d, t.right) === !0;
686
+ } catch (t) {
687
+ return r.push({
688
+ kind: "match-threw",
689
+ workflowName: e.workflowName,
690
+ event: o.event,
691
+ subject: n,
692
+ detail: qe(t)
693
+ }), !1;
694
+ }
695
+ };
696
+ for (let { run: e, decoded: n } of s) i.has(e.runId) || f(e.startedAt) && p(n, e.runId) && (i.add(e.runId), t.push({
697
+ runId: e.runId,
698
+ executionId: e.executionId,
699
+ reason: o.reason,
700
+ event: o.event,
701
+ eventId: l.id
702
+ }));
703
+ for (let { intent: e, decoded: t } of c) a.has(e.intentId) || f(e.firstSeenAt) && p(t, e.intentId) && (a.add(e.intentId), n.push({
704
+ intentId: e.intentId,
705
+ reason: o.reason,
706
+ event: o.event,
707
+ eventId: l.id
708
+ }));
709
+ }
710
+ return {
711
+ cancels: t,
712
+ discards: n,
713
+ problems: r
714
+ };
715
+ }, Ye = (e) => {
716
+ let t;
717
+ for (let n of e) (t === void 0 || n.occurredAt.getTime() > t.getTime()) && (t = n.occurredAt);
718
+ return t;
719
+ }, Xe = "_voltro_workflow_watermarks", Ze = "_voltro_workflow_events", K = "cancelOn", Qe = 3600 * 1e3, $e = 500, q = (e) => {
720
+ if (e instanceof Date) return e;
721
+ if (typeof e == "number") return new Date(e);
722
+ if (typeof e == "string") {
723
+ let t = new Date(e);
724
+ if (!Number.isNaN(t.getTime())) return t;
725
+ }
726
+ }, J = (e) => e instanceof Error ? e.message : String(e), et = async (e, t) => q((await e.query({
727
+ table: Xe,
728
+ predicate: x("id", t),
729
+ order: [],
730
+ take: 1,
731
+ skip: void 0,
732
+ projection: void 0
733
+ }))[0]?.positionAt), tt = async (e, t, n) => {
734
+ await e.upsert(Xe, {
735
+ id: t,
736
+ positionAt: n,
737
+ updatedAt: /* @__PURE__ */ new Date()
738
+ }, {
739
+ conflictColumns: ["id"],
740
+ update: (e) => {
741
+ let t = q(e.positionAt);
742
+ return t !== void 0 && t.getTime() >= n.getTime() ? {
743
+ positionAt: t,
744
+ updatedAt: /* @__PURE__ */ new Date()
745
+ } : {
746
+ positionAt: n,
747
+ updatedAt: /* @__PURE__ */ new Date()
748
+ };
749
+ }
750
+ });
751
+ }, nt = async (e, t, n) => {
752
+ let r = async (r) => e.query({
753
+ table: "_voltro_workflow_runs",
754
+ predicate: b(x("tag", t), x("status", r)),
755
+ order: [{
756
+ column: "startedAt",
757
+ direction: "asc"
758
+ }],
759
+ take: n,
760
+ skip: void 0,
761
+ projection: void 0
762
+ });
763
+ return [...await r("running"), ...await r("suspended")].flatMap((e) => {
764
+ let t = e, n = q(t.startedAt);
765
+ return typeof t.id != "string" || typeof t.executionId != "string" || n === void 0 ? [] : [{
766
+ runId: t.id,
767
+ executionId: t.executionId,
768
+ payload: t.payload,
769
+ startedAt: n
770
+ }];
771
+ });
772
+ }, rt = async (e, t, n) => (await e.query({
773
+ table: "_voltro_workflow_pending",
774
+ predicate: x("workflowName", t),
775
+ order: [{
776
+ column: "firstSeenAt",
777
+ direction: "asc"
778
+ }],
779
+ take: n,
780
+ skip: void 0,
781
+ projection: void 0
782
+ })).flatMap((e) => {
783
+ let t = e, n = q(t.firstSeenAt);
784
+ return typeof t.id != "string" || n === void 0 ? [] : [{
785
+ intentId: t.id,
786
+ payload: t.payload,
787
+ firstSeenAt: n
788
+ }];
789
+ }), it = async (e, t) => {
790
+ let n = t.workflows.filter((e) => e.entries.length > 0);
791
+ if (n.length === 0) return {
792
+ examined: !1,
793
+ events: 0,
794
+ cancelled: 0,
795
+ discarded: 0,
796
+ catchingUp: !1,
797
+ sawFullRunPage: !1,
798
+ problems: [],
799
+ failures: [],
800
+ watermark: void 0
801
+ };
802
+ let r = e.now?.() ?? Date.now(), i = t.batch ?? 500, a = t.coldLookbackMs ?? 36e5, o = /* @__PURE__ */ new Set();
803
+ for (let e of n) for (let t of e.entries) o.add(t.event);
804
+ let s = await et(e.store, K), c = s ?? new Date(r - a), l = await e.store.query({
805
+ table: Ze,
806
+ predicate: te("occurredAt", c),
807
+ order: [{
808
+ column: "occurredAt",
809
+ direction: "asc"
810
+ }],
811
+ take: i,
812
+ skip: void 0,
813
+ projection: void 0
814
+ }), u = [];
815
+ for (let e of l) {
816
+ let t = e, n = q(t.occurredAt);
817
+ typeof t.id != "string" || typeof t.name != "string" || n === void 0 || o.has(t.name) && u.push({
818
+ id: t.id,
819
+ name: t.name,
820
+ payload: t.payload,
821
+ occurredAt: n
822
+ });
823
+ }
824
+ let d = [], f = [], p = 0, m = 0, h = !1, g = !1, _ = t.runPage ?? 2e3;
825
+ if (u.length > 0) for (let t of n) {
826
+ let n = u.filter((e) => t.entries.some((t) => t.event === e.name));
827
+ if (n.length === 0) continue;
828
+ let r = [], i = [];
829
+ try {
830
+ r = await nt(e.store, t.workflowName, _), i = await rt(e.store, t.workflowName, _), (r.length >= _ || i.length >= _) && (h = !0);
831
+ } catch (e) {
832
+ f.push({
833
+ subject: t.workflowName,
834
+ detail: J(e)
835
+ }), g = !0;
836
+ continue;
837
+ }
838
+ let a = Je({
839
+ workflowName: t.workflowName,
840
+ entries: t.entries,
841
+ payloadSchema: t.payloadSchema,
842
+ events: n,
843
+ runs: r,
844
+ intents: i
845
+ });
846
+ d.push(...a.problems);
847
+ for (let n of a.cancels) try {
848
+ await e.cancelRun({
849
+ workflowName: t.workflowName,
850
+ runId: n.runId,
851
+ executionId: n.executionId,
852
+ reason: n.reason,
853
+ event: n.event
854
+ }), p += 1, e.log?.info("workflow.cancelOn: run cancelled", {
855
+ workflow: t.workflowName,
856
+ runId: n.runId,
857
+ event: n.event,
858
+ eventId: n.eventId
859
+ });
860
+ } catch (e) {
861
+ f.push({
862
+ subject: n.runId,
863
+ detail: J(e)
864
+ });
865
+ }
866
+ for (let n of a.discards) try {
867
+ await e.discardIntent({
868
+ workflowName: t.workflowName,
869
+ intentId: n.intentId,
870
+ reason: n.reason,
871
+ event: n.event
872
+ }), m += 1;
873
+ } catch (e) {
874
+ f.push({
875
+ subject: n.intentId,
876
+ detail: J(e)
877
+ });
878
+ }
879
+ }
880
+ let v = Ye(u), y = s;
881
+ if (g) e.log?.warn("workflow.cancelOn: holding the watermark — some workflows could not be evaluated", { failures: f.length });
882
+ else if (v !== void 0) try {
883
+ await tt(e.store, K, v), y = v;
884
+ } catch (e) {
885
+ f.push({
886
+ subject: K,
887
+ detail: J(e)
888
+ });
889
+ }
890
+ else if (s === void 0) try {
891
+ await tt(e.store, K, c), y = c;
892
+ } catch (e) {
893
+ f.push({
894
+ subject: K,
895
+ detail: J(e)
896
+ });
897
+ }
898
+ return d.length > 0 && e.log?.warn("workflow.cancelOn: some events could not be evaluated", {
899
+ count: d.length,
900
+ first: d[0]
901
+ }), {
902
+ examined: !0,
903
+ events: u.length,
904
+ cancelled: p,
905
+ discarded: m,
906
+ catchingUp: l.length >= i,
907
+ sawFullRunPage: h,
908
+ problems: d,
909
+ failures: f,
910
+ watermark: y
911
+ };
912
+ }, at = 1800 * 1e3, ot = 200, st = 20, Y = (e) => {
913
+ if (e instanceof Date) return e;
914
+ if (typeof e == "number") return new Date(e);
915
+ if (typeof e == "string") {
916
+ let t = new Date(e);
917
+ if (!Number.isNaN(t.getTime())) return t;
918
+ }
919
+ }, ct = (e) => e instanceof Error ? e.message : String(e), lt = async (e, t, n) => (await e.query({
920
+ table: "_voltro_workflow_run_events",
921
+ predicate: x("runId", t),
922
+ order: [{
923
+ column: "occurredAt",
924
+ direction: "desc"
925
+ }],
926
+ take: n,
927
+ skip: void 0,
928
+ projection: void 0
929
+ })).flatMap((e) => {
930
+ let t = e, n = Y(t.occurredAt);
931
+ return typeof t.eventType != "string" || n === void 0 ? [] : [{
932
+ eventType: t.eventType,
933
+ occurredAt: n,
934
+ payload: t.payload
935
+ }];
936
+ }), ut = async (e, t) => {
937
+ let n = (await e.query({
938
+ table: "_voltro_workflow_run_steps",
939
+ predicate: x("runId", t),
940
+ order: [{
941
+ column: "startedAt",
942
+ direction: "desc"
943
+ }],
944
+ take: 1,
945
+ skip: void 0,
946
+ projection: void 0
947
+ }))[0];
948
+ if (n === void 0) return;
949
+ let r = Y(n.startedAt), i = Y(n.completedAt);
950
+ return r === void 0 ? i : i === void 0 ? r : i.getTime() > r.getTime() ? i : r;
951
+ }, dt = (e, t) => {
952
+ for (let n of e) {
953
+ if (n.eventType === "timer-fired") return !1;
954
+ if (n.eventType !== "timer-set") continue;
955
+ let e = Y(n.payload?.scheduledWakeAt);
956
+ return e !== void 0 && e.getTime() > t;
957
+ }
958
+ return !1;
959
+ }, ft = (e, t) => {
960
+ if (e !== "suspended") return "no-progress";
961
+ for (let e of t) {
962
+ if (e.eventType === "signal-received" || e.eventType === "signal-sent") return "suspended";
963
+ if (e.eventType === "signal-awaited") return "awaiting-signal";
964
+ }
965
+ return "suspended";
966
+ }, pt = async (e, t = {}) => {
967
+ let n = e.now?.() ?? Date.now(), r = t.stallAfterMs ?? 18e5, i = t.runPage ?? 200, a = t.eventLookback ?? 20, o = new Date(n - r), s = [], c = [], l = 0, u = 0, d;
968
+ try {
969
+ d = await e.store.query({
970
+ table: "_voltro_workflow_runs",
971
+ predicate: b(ne("status", ["running", "suspended"]), O("startedAt", o)),
972
+ order: [{
973
+ column: "startedAt",
974
+ direction: "asc"
975
+ }],
976
+ take: i,
977
+ skip: void 0,
978
+ projection: void 0
979
+ });
980
+ } catch (e) {
981
+ return {
982
+ examined: 0,
983
+ stalled: [],
984
+ alreadyReported: 0,
985
+ waitingOnTimer: 0,
986
+ sawFullRunPage: !1,
987
+ failures: [{
988
+ subject: "_voltro_workflow_runs",
989
+ detail: ct(e)
990
+ }]
991
+ };
992
+ }
993
+ for (let t of d) {
994
+ let i = t, o = Y(i.startedAt);
995
+ if (typeof i.id != "string" || typeof i.tag != "string" || typeof i.executionId != "string" || typeof i.status != "string" || o === void 0) continue;
996
+ let d, f;
997
+ try {
998
+ d = await lt(e.store, i.id, a), f = await ut(e.store, i.id);
999
+ } catch (e) {
1000
+ s.push({
1001
+ subject: i.id,
1002
+ detail: ct(e)
1003
+ });
1004
+ continue;
1005
+ }
1006
+ if (dt(d, n)) {
1007
+ u += 1;
1008
+ continue;
1009
+ }
1010
+ let p = d.find((e) => e.eventType !== "run-stalled")?.occurredAt, m = o;
1011
+ for (let e of [f, p]) e !== void 0 && e.getTime() > m.getTime() && (m = e);
1012
+ let h = n - m.getTime();
1013
+ if (h < r) continue;
1014
+ if (d.some((e) => e.eventType === "run-stalled" && e.occurredAt.getTime() > m.getTime())) {
1015
+ l += 1;
1016
+ continue;
1017
+ }
1018
+ let g = {
1019
+ runId: i.id,
1020
+ tag: i.tag,
1021
+ executionId: i.executionId,
1022
+ status: i.status,
1023
+ lastProgressAt: m,
1024
+ idleMs: h,
1025
+ reason: ft(i.status, d)
1026
+ };
1027
+ if (c.push(g), e.log?.warn("workflow.staleness: run has made no progress", {
1028
+ workflow: g.tag,
1029
+ runId: g.runId,
1030
+ idleMs: g.idleMs,
1031
+ reason: g.reason
1032
+ }), e.recordEvent !== void 0) try {
1033
+ await e.recordEvent({
1034
+ runId: g.runId,
1035
+ eventType: "run-stalled",
1036
+ payload: {
1037
+ idleMs: g.idleMs,
1038
+ stallAfterMs: r,
1039
+ lastProgressAt: g.lastProgressAt.toISOString(),
1040
+ reason: g.reason,
1041
+ tag: g.tag,
1042
+ executionId: g.executionId
1043
+ }
1044
+ });
1045
+ } catch (e) {
1046
+ s.push({
1047
+ subject: g.runId,
1048
+ detail: ct(e)
1049
+ });
1050
+ }
1051
+ if (e.onStalled !== void 0) try {
1052
+ await e.onStalled(g);
1053
+ } catch (e) {
1054
+ s.push({
1055
+ subject: `${g.runId}:onStalled`,
1056
+ detail: ct(e)
1057
+ });
1058
+ }
1059
+ }
1060
+ return {
1061
+ examined: d.length,
1062
+ stalled: c,
1063
+ alreadyReported: l,
1064
+ waitingOnTimer: u,
1065
+ sawFullRunPage: d.length >= i,
1066
+ failures: s
1067
+ };
1068
+ }, mt = {
1069
+ scanned: 0,
1070
+ admitted: 0,
1071
+ deferred: 0,
1072
+ dropped: 0,
1073
+ skipped: 0,
1074
+ expired: 0,
1075
+ evicted: 0,
1076
+ failed: 0,
1077
+ timedOut: 0,
1078
+ examined: !1
1079
+ }, ht = 200, gt = async (e, t = {}) => {
1080
+ let n = e.now ?? (() => Date.now()), r = e.log, i = t.batchSize ?? 200, a, o, s;
1081
+ try {
1082
+ a = await Oe(e.store);
1083
+ let t = await Le(e.store, n(), i);
1084
+ o = t.due, s = t.nextDueAt;
1085
+ } catch (e) {
1086
+ return r?.warn?.("workflow flow control: could not read the admission queue", { cause: String(e) }), mt;
1087
+ }
1088
+ let c = {
1089
+ scanned: o.length,
1090
+ admitted: 0,
1091
+ deferred: 0,
1092
+ dropped: 0,
1093
+ skipped: 0,
1094
+ expired: 0,
1095
+ evicted: 0,
1096
+ failed: 0,
1097
+ timedOut: 0
1098
+ }, l = /* @__PURE__ */ new Map(), u = [];
1099
+ for (let e of o) {
1100
+ if (e.mode === "batch") {
1101
+ let t = `${e.workflowName}\u0000${e.controlKey}`, n = l.get(t);
1102
+ n === void 0 ? l.set(t, [e]) : n.push(e);
1103
+ continue;
1104
+ }
1105
+ u.push(e);
1106
+ }
1107
+ for (let t of u) try {
1108
+ await _t(e, t, a, c, n());
1109
+ } catch (i) {
1110
+ c.failed++, r?.warn?.("workflow flow control: an intent failed to drain", {
1111
+ workflow: t.workflowName,
1112
+ intent: t.id,
1113
+ cause: String(i)
1114
+ }), await Be(e.store, t, String(i), n()).catch(() => {});
1115
+ }
1116
+ for (let t of l.values()) try {
1117
+ await yt(e, t, a, c, n());
1118
+ } catch (i) {
1119
+ c.failed++;
1120
+ let a = t[0];
1121
+ r?.warn?.("workflow flow control: a batch failed to drain", {
1122
+ workflow: a?.workflowName,
1123
+ size: t.length,
1124
+ cause: String(i)
1125
+ }), a !== void 0 && await Be(e.store, a, String(i), n()).catch(() => {});
1126
+ }
1127
+ return c.timedOut = await xt(e, n()).catch(() => 0), {
1128
+ ...c,
1129
+ examined: !0,
1130
+ ...s === void 0 ? {} : { nextDueAt: s }
1131
+ };
1132
+ }, _t = async (e, t, n, r, i) => {
1133
+ if (t.mode === "delayed") return vt(e, t, n, r, i);
1134
+ let a = e.controls.get(t.workflowName);
1135
+ if (a === void 0) {
1136
+ await e.onAbandoned({
1137
+ workflowName: t.workflowName,
1138
+ payload: t.payload,
1139
+ callerContext: t.callerContext,
1140
+ reason: `workflow '${t.workflowName}' is no longer registered — it was renamed or removed while this start was waiting in the admission queue`
1141
+ }), await G(e.store, t.id), r.expired++;
1142
+ return;
1143
+ }
1144
+ if (xe(a, t, i)) {
1145
+ await U({
1146
+ store: e.store,
1147
+ control: a,
1148
+ keys: I(a, t.payload),
1149
+ outcome: "expired",
1150
+ mode: t.mode,
1151
+ reason: `timeouts.start elapsed after ${i - t.firstSeenAt}ms`,
1152
+ collapsed: t.collapsed,
1153
+ waitedMs: i - t.firstSeenAt,
1154
+ executionId: null,
1155
+ runId: null,
1156
+ tenantId: t.tenantId,
1157
+ now: i
1158
+ }), await e.onAbandoned({
1159
+ workflowName: t.workflowName,
1160
+ payload: t.payload,
1161
+ callerContext: t.callerContext,
1162
+ reason: `timeouts.start (${a.timeouts?.startMs}ms) elapsed while this start waited in the admission queue; ${t.collapsed} start(s) had collapsed into it`
1163
+ }), await G(e.store, t.id), r.expired++;
1164
+ return;
1165
+ }
1166
+ let o = I(a, t.payload);
1167
+ await bt(e, {
1168
+ control: a,
1169
+ intent: t,
1170
+ decision: await Ve({
1171
+ store: e.store,
1172
+ control: a,
1173
+ keys: o,
1174
+ paused: n.has(t.workflowName),
1175
+ now: i,
1176
+ reconsidering: !0
1177
+ }),
1178
+ keys: o,
1179
+ counters: r,
1180
+ now: i,
1181
+ items: void 0
1182
+ });
1183
+ }, vt = async (e, t, n, r, i) => {
1184
+ if (e.registeredWorkflows !== void 0 && !e.registeredWorkflows.has(t.workflowName)) {
1185
+ await e.onAbandoned({
1186
+ workflowName: t.workflowName,
1187
+ payload: t.payload,
1188
+ callerContext: t.callerContext,
1189
+ reason: `workflow '${t.workflowName}' is no longer registered — it was renamed or removed while this delayed start waited for its 'at' instant`
1190
+ }), await G(e.store, t.id), r.expired++;
1191
+ return;
1192
+ }
1193
+ let a = e.controls.get(t.workflowName) ?? { workflowName: t.workflowName }, o = await Ue({
1194
+ store: e.store,
1195
+ control: a,
1196
+ payload: t.payload,
1197
+ callerContext: t.callerContext,
1198
+ tenantId: t.tenantId,
1199
+ paused: n.has(t.workflowName),
1200
+ now: i,
1201
+ waiting: !1
1202
+ });
1203
+ if (o.kind === "queued") {
1204
+ await G(e.store, t.id), r.deferred++;
1205
+ return;
1206
+ }
1207
+ if (o.kind === "dropped") {
1208
+ await G(e.store, t.id), r.dropped++;
1209
+ return;
1210
+ }
1211
+ if (o.kind === "skipped") {
1212
+ await G(e.store, t.id), r.skipped++;
1213
+ return;
1214
+ }
1215
+ let s = await e.startAdmitted(a.workflowName, o.payload, t.callerContext);
1216
+ o.evict !== void 0 && (await e.cancelRun(a.workflowName, o.evict.executionId).catch(() => {}), await W(e.store, o.evict.executionId, i).catch(() => {}), r.evicted++);
1217
+ for (let t of o.consume) await G(e.store, t).catch(() => {});
1218
+ o.ledgerId !== void 0 && await Ge(e.store, o.ledgerId, s.executionId, s.runId ?? null).catch(() => {}), await G(e.store, t.id), r.admitted++;
1219
+ }, yt = async (e, t, n, r, i) => {
1220
+ let a = t[0];
1221
+ if (a === void 0) return;
1222
+ let o = e.controls.get(a.workflowName);
1223
+ if (o === void 0 || o.batch === void 0) {
1224
+ for (let n of t) await G(e.store, n.id);
1225
+ r.expired += t.length;
1226
+ return;
1227
+ }
1228
+ let s = [...t].sort((e, t) => e.firstSeenAt - t.firstSeenAt), c = s[0];
1229
+ if (xe(o, c, i)) {
1230
+ await e.onAbandoned({
1231
+ workflowName: a.workflowName,
1232
+ payload: { items: s.map((e) => e.payload) },
1233
+ callerContext: c.callerContext,
1234
+ reason: `timeouts.start elapsed with ${s.length} item(s) accumulated in the batch`
1235
+ });
1236
+ for (let t of s) await G(e.store, t.id);
1237
+ r.expired += s.length;
1238
+ return;
1239
+ }
1240
+ let l = I(o, c.payload);
1241
+ await bt(e, {
1242
+ control: o,
1243
+ intent: c,
1244
+ decision: await Ve({
1245
+ store: e.store,
1246
+ control: o,
1247
+ keys: l,
1248
+ paused: n.has(a.workflowName),
1249
+ now: i,
1250
+ reconsidering: !0
1251
+ }),
1252
+ keys: l,
1253
+ counters: r,
1254
+ now: i,
1255
+ items: s
1256
+ });
1257
+ }, bt = async (e, t) => {
1258
+ let { control: n, intent: r, decision: i, keys: a, counters: o, now: s, items: c } = t;
1259
+ if (i.kind === "defer") {
1260
+ await Ne({
1261
+ store: e.store,
1262
+ control: n,
1263
+ decision: i,
1264
+ payload: r.payload,
1265
+ callerContext: r.callerContext,
1266
+ tenantId: r.tenantId,
1267
+ now: s,
1268
+ existingId: r.id
1269
+ }), o.deferred++;
1270
+ return;
1271
+ }
1272
+ if (i.kind === "drop") {
1273
+ await U({
1274
+ store: e.store,
1275
+ control: n,
1276
+ keys: a,
1277
+ outcome: "dropped",
1278
+ mode: "rateLimit",
1279
+ reason: `rate limit reached while queued; retry after ${i.retryAfterMs}ms`,
1280
+ collapsed: r.collapsed,
1281
+ waitedMs: s - r.firstSeenAt,
1282
+ executionId: null,
1283
+ runId: null,
1284
+ tenantId: r.tenantId,
1285
+ now: s
1286
+ });
1287
+ for (let t of c ?? [r]) await G(e.store, t.id);
1288
+ o.dropped++;
1289
+ return;
1290
+ }
1291
+ if (i.kind === "skip") {
1292
+ await U({
1293
+ store: e.store,
1294
+ control: n,
1295
+ keys: a,
1296
+ outcome: "skipped",
1297
+ mode: "singleton",
1298
+ reason: `singleton key held by ${i.incumbent.executionId}`,
1299
+ collapsed: r.collapsed,
1300
+ waitedMs: s - r.firstSeenAt,
1301
+ executionId: i.incumbent.executionId,
1302
+ runId: i.incumbent.runId || null,
1303
+ tenantId: r.tenantId,
1304
+ now: s
1305
+ });
1306
+ for (let t of c ?? [r]) await G(e.store, t.id);
1307
+ o.skipped++;
1308
+ return;
1309
+ }
1310
+ i.evict !== void 0 && (await e.cancelRun(n.workflowName, i.evict.executionId), await W(e.store, i.evict.executionId, s), await U({
1311
+ store: e.store,
1312
+ control: n,
1313
+ keys: a,
1314
+ outcome: "evicted",
1315
+ mode: "singleton",
1316
+ reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
1317
+ collapsed: 1,
1318
+ waitedMs: null,
1319
+ executionId: i.evict.executionId,
1320
+ runId: i.evict.runId || null,
1321
+ tenantId: r.tenantId,
1322
+ now: s
1323
+ }), o.evicted++);
1324
+ let l = c === void 0 ? r.payload : { items: c.map((e) => e.payload) }, u = c === void 0 ? r.collapsed : c.reduce((e, t) => e + t.collapsed, 0), d = await e.startAdmitted(n.workflowName, l, r.callerContext);
1325
+ await U({
1326
+ store: e.store,
1327
+ control: n,
1328
+ keys: a,
1329
+ outcome: "admitted",
1330
+ mode: r.mode,
1331
+ reason: i.reason,
1332
+ collapsed: u,
1333
+ waitedMs: s - r.firstSeenAt,
1334
+ executionId: d.executionId,
1335
+ runId: d.runId ?? null,
1336
+ tenantId: r.tenantId,
1337
+ now: s
1338
+ });
1339
+ for (let t of c ?? [r]) await G(e.store, t.id);
1340
+ o.admitted++;
1341
+ }, xt = async (e, t) => {
1342
+ if (e.listRunningRuns === void 0) return 0;
1343
+ let n = 0;
1344
+ for (let r of e.controls.values()) {
1345
+ if (r.timeouts?.finishMs === void 0) continue;
1346
+ let i = await e.listRunningRuns(r.workflowName);
1347
+ for (let a of i) Se(r, {
1348
+ startedAt: a.startedAt,
1349
+ terminal: !1
1350
+ }, t) && (await e.cancelRun(r.workflowName, a.executionId), await W(e.store, a.executionId, t), await e.onAbandoned({
1351
+ workflowName: r.workflowName,
1352
+ payload: null,
1353
+ callerContext: null,
1354
+ reason: `timeouts.finish (${r.timeouts.finishMs}ms) elapsed; the run was cancelled after ${t - a.startedAt}ms`
1355
+ }), n++);
1356
+ }
1357
+ return n;
1358
+ }, St = 5 * 6e4, Ct, wt = (e) => {
1359
+ Ct = e !== void 0 && Number.isFinite(e) && e > 0 ? e : void 0;
1360
+ }, Tt = () => {
1361
+ let e = process.env.VOLTRO_WORKFLOW_SUSPEND_HINT_MS;
1362
+ if (e !== void 0) {
1363
+ let t = Number(e);
1364
+ if (Number.isFinite(t) && t > 0) return t;
1365
+ }
1366
+ return Ct ?? 3e5;
1367
+ }, Et = /* @__PURE__ */ new Set(), Dt = () => {
1368
+ Et.clear();
1369
+ }, Ot = (e) => {
1370
+ let t = Tt();
1371
+ if (!(e.timeoutMs > t)) return !1;
1372
+ let n = `${e.workflowName ?? ""}\u0000${e.signalName}`;
1373
+ if (Et.has(n)) return !1;
1374
+ Et.add(n);
1375
+ let r = e.workflowName === void 0 ? "" : ` in workflow '${e.workflowName}'`;
1376
+ return (e.warn ?? ((e) => console.warn(e)))(`awaitSignal('${e.signalName}')${r} declares a ${Math.round(e.timeoutMs / 1e3)}s timeout — a wait that long holds a worker fiber for its whole duration. For human-approval-length waits, awaitSignalSuspending (same call shape, from @voltro/workflow) SUSPENDS the run and frees the slot until the signal arrives. This is a hint, not a behaviour change; it is logged once per workflow. Threshold: workflows.suspendSignalHintMs in app.config.ts, or VOLTRO_WORKFLOW_SUSPEND_HINT_MS.`), !0;
1377
+ }, kt = async (e, t) => {
1378
+ if (e) try {
1379
+ await e.recordEvent(t);
1380
+ } catch {}
1381
+ }, At = (e, t) => {
1382
+ let r = m.gen(function* () {
1383
+ let r = t.pollIntervalMs ?? 200, i = t.maxPollIntervalMs ?? 5e3, o = t.timeoutMs ?? 1440 * 6e4, s = yield* m.serviceOption(se);
1384
+ Ot({
1385
+ workflowName: s._tag === "Some" ? s.value.workflow.name : void 0,
1386
+ signalName: t.name,
1387
+ timeoutMs: o
1388
+ });
1389
+ let c = yield* a, l = yield* m.serviceOption(n), u = l._tag === "Some" ? l.value : void 0;
1390
+ if (c === void 0) return yield* m.die(/* @__PURE__ */ Error("awaitSignal: no active workflow run id in scope"));
1391
+ let d = c;
1392
+ yield* m.promise(() => kt(u, {
1393
+ runId: d,
1394
+ eventType: "signal-awaited",
1395
+ payload: { signalName: t.name }
1396
+ }));
1397
+ let f = Date.now(), p = r;
1398
+ for (;;) {
1399
+ let n = Date.now() - f;
1400
+ if (n > o) return yield* m.die(/* @__PURE__ */ Error(`awaitSignal('${t.name}') timed out after ${n}ms`));
1401
+ let r = {
1402
+ table: "_voltro_workflow_run_events",
1403
+ order: [{
1404
+ column: "occurredAt",
1405
+ direction: "asc"
1406
+ }],
1407
+ predicate: b(x("runId", d), x("eventType", "signal-sent")),
1408
+ projection: void 0,
1409
+ skip: void 0,
1410
+ take: 1e3
1411
+ }, a = (yield* m.tryPromise({
1412
+ try: () => e.store.query(r),
1413
+ catch: (e) => e
1414
+ })).find((e) => e.payload?.signalName === t.name);
1415
+ if (a !== void 0) {
1416
+ let e = yield* y.decodeUnknown(t.schema)(a.payload?.value);
1417
+ return yield* m.promise(() => kt(u, {
1418
+ runId: d,
1419
+ eventType: "signal-received",
1420
+ payload: {
1421
+ signalName: t.name,
1422
+ value: a.payload?.value
1423
+ }
1424
+ })), e;
1425
+ }
1426
+ yield* m.sleep(`${p} millis`), p = Math.min(p * 2, i);
1427
+ }
1428
+ });
1429
+ return c.make({
1430
+ name: `await-signal:${t.name}`,
1431
+ success: t.schema,
1432
+ execute: r
1433
+ });
1434
+ }, jt = async (e, t) => {
1435
+ if (e !== void 0) try {
1436
+ await e.recordEvent(t);
1437
+ } catch {}
1438
+ }, Mt = (e, t) => {
1439
+ let r = m.gen(function* () {
1440
+ let r = t.pollIntervalMs ?? 200, i = t.maxPollIntervalMs ?? 5e3, o = t.timeoutMs ?? 1440 * 6e4, s = t.take ?? 500, c = yield* a, l = yield* m.serviceOption(n), u = l._tag === "Some" ? l.value : void 0;
1441
+ if (c === void 0) return yield* m.die(/* @__PURE__ */ Error("awaitEvent: no active workflow run id in scope"));
1442
+ let d = c, f = yield* t.since === "run-start" ? Nt(e, d) : m.succeed(/* @__PURE__ */ new Date());
1443
+ yield* m.promise(() => jt(u, {
1444
+ runId: d,
1445
+ eventType: "event-awaited",
1446
+ payload: {
1447
+ event: t.event,
1448
+ since: t.since ?? "wait-start",
1449
+ cutoff: f.toISOString()
1450
+ }
1451
+ }));
1452
+ let p = Date.now(), h = r, g = 0;
1453
+ for (;;) {
1454
+ let n = Date.now() - p;
1455
+ if (n > o) return yield* m.die(/* @__PURE__ */ Error(`awaitEvent('${t.event}') timed out after ${n}ms having examined ${g} candidate event(s). ${g === 0 ? "NONE were published under that name in the window — check the spelling against ctx.events.publish, and consider since: 'run-start' if the event may have arrived before this step began." : "The predicate rejected all of them — log one payload and compare it with what `match` expects."}`));
1456
+ let r = {
1457
+ table: "_voltro_workflow_events",
1458
+ predicate: b(x("name", t.event), te("occurredAt", f)),
1459
+ order: [{
1460
+ column: "occurredAt",
1461
+ direction: "asc"
1462
+ }],
1463
+ take: s,
1464
+ skip: void 0,
1465
+ projection: void 0
1466
+ }, a = yield* m.tryPromise({
1467
+ try: () => e.store.query(r),
1468
+ catch: (e) => e
1469
+ });
1470
+ g = a.length;
1471
+ for (let e of a) {
1472
+ let n = yield* y.decodeUnknown(t.schema)(e.payload);
1473
+ if (t.match(n)) return yield* m.promise(() => jt(u, {
1474
+ runId: d,
1475
+ eventType: "event-received",
1476
+ payload: {
1477
+ event: t.event,
1478
+ eventId: e.id
1479
+ }
1480
+ })), n;
1481
+ }
1482
+ yield* m.sleep(`${h} millis`), h = Math.min(h * 2, i);
1483
+ }
1484
+ });
1485
+ return c.make({
1486
+ name: `awaitEvent:${t.event}`,
1487
+ success: t.schema,
1488
+ execute: r
1489
+ });
1490
+ }, Nt = (e, t) => m.gen(function* () {
1491
+ let n = (yield* m.tryPromise({
1492
+ try: () => e.store.query({
1493
+ table: "_voltro_workflow_runs",
1494
+ predicate: x("id", t),
1495
+ order: [],
1496
+ take: 1,
1497
+ skip: void 0,
1498
+ projection: void 0
1499
+ }),
1500
+ catch: (e) => e
1501
+ }))[0]?.startedAt;
1502
+ if (n instanceof Date) return n;
1503
+ if (typeof n == "string" || typeof n == "number") {
1504
+ let e = new Date(n);
1505
+ if (!Number.isNaN(e.getTime())) return e;
1506
+ }
1507
+ return /* @__PURE__ */ new Date(0);
1508
+ }), Pt = (e) => new Promise((t) => setTimeout(t, e)), Ft = () => {
1509
+ let e = globalThis.crypto;
1510
+ return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1511
+ }, It = () => `wfu_${Ft()}`, Lt = async (e, t) => {
1512
+ let n = t.id ?? t.executionId;
1513
+ if (!n) throw Error("workflow message target requires target.id or target.executionId");
1514
+ let r = await e.query({
1515
+ table: "_voltro_workflow_runs",
1516
+ order: [],
1517
+ predicate: x("id", n),
1518
+ projection: void 0,
1519
+ skip: void 0,
1520
+ take: 1
1521
+ });
1522
+ if (r[0]) return r[0];
1523
+ let i = (await e.query({
1524
+ table: "_voltro_workflow_runs",
1525
+ order: [],
1526
+ predicate: x("executionId", n),
1527
+ projection: void 0,
1528
+ skip: void 0,
1529
+ take: 1
1530
+ }))[0];
1531
+ if (!i) throw Error(`workflow message target not found: ${n}`);
1532
+ return i;
1533
+ }, Rt = async (e) => {
1534
+ let t = await Lt(e.store, e.target);
1535
+ return { eventId: (await e.recorder.recordEvent({
1536
+ runId: t.id,
1537
+ eventType: "signal-sent",
1538
+ payload: {
1539
+ signalName: e.signalName,
1540
+ value: e.payload
1541
+ }
1542
+ })).id };
1543
+ }, zt = async (e) => {
1544
+ let t = await Lt(e.store, e.target), n = It(), r = await e.recorder.recordEvent({
1545
+ runId: t.id,
1546
+ eventType: "update-requested",
1547
+ payload: {
1548
+ updateId: n,
1549
+ updateName: e.updateName,
1550
+ value: e.payload
1551
+ }
1552
+ }), i = Date.now(), a = e.options?.timeoutMs ?? 3e4, o = e.options?.pollIntervalMs ?? 100;
1553
+ for (;;) {
1554
+ let s = {
1555
+ table: "_voltro_workflow_run_events",
1556
+ order: [{
1557
+ column: "occurredAt",
1558
+ direction: "asc"
1559
+ }],
1560
+ predicate: x("runId", t.id),
1561
+ projection: void 0,
1562
+ skip: void 0,
1563
+ take: 1e3
1564
+ }, c = await e.store.query(s), l = c.find((e) => e.eventType === "update-completed" && e.payload?.updateId === n);
1565
+ if (l) return {
1566
+ eventId: r.id,
1567
+ updateId: n,
1568
+ completedEventId: l.id,
1569
+ result: l.payload?.result
1570
+ };
1571
+ let u = c.find((e) => e.eventType === "update-failed" && e.payload?.updateId === n);
1572
+ if (u) {
1573
+ let t = Error(u.payload?.errorMessage ?? `workflow update '${e.updateName}' failed`);
1574
+ throw Object.assign(t, {
1575
+ updateId: n,
1576
+ eventId: r.id,
1577
+ errorTag: u.payload?.errorTag ?? null
1578
+ }), t;
1579
+ }
1580
+ if (Date.now() - i >= a) throw Error(`Timed out waiting for workflow update '${e.updateName}' (${n})`);
1581
+ await Pt(o);
1582
+ }
1583
+ }, Bt = 1440 * 6e4, Vt = "voltro/suspending-signal", Ht = (e, t) => `${Vt}/${e}/${t}`, Ut = (e) => u.make(e, { success: y.Unknown }), Wt = async (e, t) => {
1584
+ if (e) try {
1585
+ await e.recordEvent(t);
1586
+ } catch {}
1587
+ }, Gt = (e, t) => m.gen(function* () {
1588
+ let e = t.timeoutMs ?? Bt, r = Ut(Ht((yield* f.WorkflowInstance).workflow.name, t.name)), i = yield* a, o = yield* m.serviceOption(n), s = o._tag === "Some" ? o.value : void 0;
1589
+ i !== void 0 && (yield* m.promise(() => Wt(s, {
1590
+ runId: i,
1591
+ eventType: "signal-awaited",
1592
+ payload: { signalName: t.name }
1593
+ })));
1594
+ let c = u.await(r), d = Number.isFinite(e) ? yield* m.race(c, l.sleep({
1595
+ name: `await-signal-timeout/${t.name}`,
1596
+ duration: `${e} millis`
1597
+ }).pipe(m.andThen(m.die(/* @__PURE__ */ Error(`awaitSignalSuspending('${t.name}') timed out after ${e}ms`))))) : yield* c, p = yield* y.decodeUnknown(t.schema)(d);
1598
+ return i !== void 0 && (yield* m.promise(() => Wt(s, {
1599
+ runId: i,
1600
+ eventType: "signal-received",
1601
+ payload: {
1602
+ signalName: t.name,
1603
+ value: p
1604
+ }
1605
+ }))), p;
1606
+ }), Kt = (e) => m.gen(function* () {
1607
+ let t = e.target.executionId, n = e.target.workflowName;
1608
+ if (t === void 0 || n === void 0) {
1609
+ let r = e.store;
1610
+ if (r === void 0) return yield* m.die(/* @__PURE__ */ Error("completeSuspendingSignal: provide a store, or target.executionId AND target.workflowName"));
1611
+ let i = yield* m.tryPromise({
1612
+ try: () => Lt(r, e.target),
1613
+ catch: (e) => e
1614
+ });
1615
+ t ??= i.executionId, n ??= i.tag;
1616
+ }
1617
+ if (t === void 0 || n === void 0) return { completed: !1 };
1618
+ let r = Ht(n, e.signalName), i = Ut(r), a = new u.TokenParsed({
1619
+ workflowName: n,
1620
+ executionId: t,
1621
+ deferredName: r
1622
+ }).asToken;
1623
+ return yield* u.done(i, {
1624
+ token: a,
1625
+ exit: g.succeed(e.payload)
1626
+ }), { completed: !0 };
1627
+ }), X = "_voltro_budget_holds", qt = "budget-hold", Jt = (e) => `${qt}:${e}`, Yt = (e) => `${e.executionId}/${e.stepName}/${e.budget}#${e.generation}`, Xt = async (e, t) => (await e.query({
1628
+ table: X,
1629
+ predicate: b(x("executionId", t.executionId), x("stepName", t.stepName), x("budget", t.budget)),
1630
+ order: []
1631
+ })).length, Zt = j(X, {
1632
+ id: w({ prefix: "bhd" }),
1633
+ holdKey: M().maxLength(191),
1634
+ budget: M(),
1635
+ tenantId: M().nullable(),
1636
+ executionId: M(),
1637
+ workflowName: M(),
1638
+ signalName: M(),
1639
+ stepName: M(),
1640
+ spentMicroUsd: M().nullable(),
1641
+ limitMicroUsd: M().nullable(),
1642
+ heldAt: N().default("now"),
1643
+ releasedAt: N().nullable(),
1644
+ outcome: M().nullable()
1645
+ }).index(["budget", "releasedAt"]), Qt = () => {
1646
+ ie({
1647
+ source: "framework",
1648
+ table: X,
1649
+ timeColumn: "releasedAt",
1650
+ ttlMs: ae(process.env.VOLTRO_BUDGET_HOLDS_TTL_HOURS, 720)
1651
+ });
1652
+ }, $t = class extends Error {
1653
+ budget;
1654
+ holdKey;
1655
+ constructor(e, t, n) {
1656
+ super(`budget '${e}': the run was suspended waiting for headroom and gave up after ${n}ms (hold ${t}). Nothing was spent. Raise the budget, reset its window, or lift the hold, then re-drive the run.`), this.name = "BudgetHoldExpired", this.budget = e, this.holdKey = t;
1657
+ }
1658
+ }, en = 10080 * 6e4, tn = (e) => m.gen(function* () {
1659
+ Qt();
1660
+ let t = e.timeoutMs ?? 6048e5, n = e.recheckEveryMs ?? 9e5, r = {
1661
+ executionId: e.executionId,
1662
+ stepName: e.stepName,
1663
+ budget: e.budget
1664
+ };
1665
+ for (;;) {
1666
+ let i = yield* m.promise(() => rn(e.store, r)), a = i.length, o = i.length === 0 ? Date.now() : nn(i[0]?.heldAt), s = Number.isFinite(t) ? t - (Date.now() - o) : Infinity, c = Yt({
1667
+ ...r,
1668
+ generation: a
1669
+ });
1670
+ if (s <= 0) return yield* m.promise(() => an(e.store, r, "expired")), yield* m.fail(new $t(e.budget, c, t));
1671
+ let l = Jt(c);
1672
+ yield* m.promise(() => e.store.insertIgnore(X, {
1673
+ id: S({
1674
+ kind: "typeid",
1675
+ prefix: "bhd"
1676
+ }, X),
1677
+ holdKey: c,
1678
+ budget: e.budget,
1679
+ tenantId: e.tenantId,
1680
+ executionId: e.executionId,
1681
+ workflowName: e.workflowName,
1682
+ signalName: l,
1683
+ stepName: e.stepName,
1684
+ spentMicroUsd: e.spentMicroUsd === void 0 ? null : String(Math.round(e.spentMicroUsd)),
1685
+ limitMicroUsd: e.limitMicroUsd === void 0 ? null : String(Math.round(e.limitMicroUsd)),
1686
+ heldAt: /* @__PURE__ */ new Date(),
1687
+ releasedAt: null,
1688
+ outcome: null
1689
+ }, { conflictColumns: ["holdKey"] }));
1690
+ let u = Math.min(n, s);
1691
+ if (yield* Gt({ store: e.store }, {
1692
+ name: l,
1693
+ schema: y.Unknown,
1694
+ timeoutMs: u
1695
+ }).pipe(m.catchAllCause((e) => p.isInterruptedOnly(e) ? m.failCause(e) : m.void)), yield* m.promise(() => e.store.updateMany(X, {
1696
+ releasedAt: /* @__PURE__ */ new Date(),
1697
+ outcome: "recheck"
1698
+ }, { where: b(x("holdKey", c), E("releasedAt")) })), yield* e.hasHeadroom) return;
1699
+ }
1700
+ }), nn = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : Date.now(), rn = async (e, t) => [...await e.query({
1701
+ table: X,
1702
+ predicate: b(x("executionId", t.executionId), x("stepName", t.stepName), x("budget", t.budget)),
1703
+ order: []
1704
+ })].sort((e, t) => String(e.id).localeCompare(String(t.id))), an = async (e, t, n) => {
1705
+ await e.updateMany(X, {
1706
+ releasedAt: /* @__PURE__ */ new Date(),
1707
+ outcome: n
1708
+ }, { where: b(x("executionId", t.executionId), x("stepName", t.stepName), x("budget", t.budget), E("releasedAt")) });
1709
+ }, on = (e) => m.gen(function* () {
1710
+ let t = e.tenantId === void 0 ? b(x("budget", e.budget), E("releasedAt")) : b(x("budget", e.budget), x("tenantId", e.tenantId), E("releasedAt")), n = yield* m.promise(() => e.store.query({
1711
+ table: X,
1712
+ predicate: t,
1713
+ order: []
1714
+ })), r = 0;
1715
+ for (let t of n) (yield* m.promise(() => e.store.updateMany("_voltro_budget_holds", {
1716
+ releasedAt: /* @__PURE__ */ new Date(),
1717
+ outcome: e.outcome ?? "released"
1718
+ }, { where: b(x("id", String(t.id)), E("releasedAt")) }))) === 1 && (yield* Kt({
1719
+ target: {
1720
+ executionId: String(t.executionId),
1721
+ workflowName: String(t.workflowName)
1722
+ },
1723
+ signalName: String(t.signalName),
1724
+ payload: {
1725
+ released: !0,
1726
+ budget: e.budget
1727
+ }
1728
+ }).pipe(m.catchAll(() => m.succeed({ completed: !1 }))), r += 1);
1729
+ return { released: r };
1730
+ }), sn = async (e, t) => {
1731
+ let n = t?.budget === void 0 ? E("releasedAt") : b(x("budget", t.budget), E("releasedAt"));
1732
+ return (await e.query({
1733
+ table: X,
1734
+ predicate: n,
1735
+ order: []
1736
+ })).map((e) => ({
1737
+ id: String(e.id),
1738
+ holdKey: String(e.holdKey),
1739
+ budget: String(e.budget),
1740
+ tenantId: e.tenantId ?? null,
1741
+ executionId: String(e.executionId),
1742
+ workflowName: String(e.workflowName),
1743
+ stepName: String(e.stepName),
1744
+ heldAt: e.heldAt instanceof Date ? e.heldAt.toISOString() : String(e.heldAt ?? "")
1745
+ }));
1746
+ }, cn = async (e) => {
1747
+ let t = await sn(e), n = /* @__PURE__ */ new Map();
1748
+ for (let e of t) {
1749
+ let t = `${e.budget}\u0000${e.tenantId ?? ""}`;
1750
+ n.has(t) || n.set(t, {
1751
+ budget: e.budget,
1752
+ tenantId: e.tenantId
1753
+ });
1754
+ }
1755
+ return [...n.values()];
1756
+ }, ln = async (e, t) => {
1757
+ if (e) try {
1758
+ await e.recordEvent(t);
1759
+ } catch {}
1760
+ }, un = (e) => {
1761
+ let t = p.failureOption(e), n = Array.from(p.defects(e)), r = t._tag === "Some" ? t.value : n[0] ?? p.squash(e);
1762
+ return {
1763
+ errorTag: r && typeof r == "object" && "_tag" in r ? String(r._tag) : null,
1764
+ errorMessage: r?.message ?? String(r)
1765
+ };
1766
+ }, dn = (e, t) => {
1767
+ let r = m.gen(function* () {
1768
+ let r = t.pollIntervalMs ?? 200, i = t.maxPollIntervalMs ?? 5e3, o = t.timeoutMs ?? 3e4, s = yield* a, c = yield* m.serviceOption(n), l = c._tag === "Some" ? c.value : void 0;
1769
+ if (s === void 0) return yield* m.die(/* @__PURE__ */ Error("awaitUpdate: no active workflow run id in scope"));
1770
+ let u = s, d = Date.now(), f = r;
1771
+ for (;;) {
1772
+ let n = Date.now() - d;
1773
+ if (n > o) return yield* m.die(/* @__PURE__ */ Error(`awaitUpdate('${t.name}') timed out after ${n}ms`));
1774
+ let r = {
1775
+ table: "_voltro_workflow_run_events",
1776
+ order: [{
1777
+ column: "occurredAt",
1778
+ direction: "asc"
1779
+ }],
1780
+ predicate: x("runId", u),
1781
+ projection: void 0,
1782
+ skip: void 0,
1783
+ take: 1e3
1784
+ }, a = yield* m.tryPromise({
1785
+ try: () => e.store.query(r),
1786
+ catch: (e) => e
1787
+ }), s = new Set(a.filter((e) => e.eventType === "update-completed" || e.eventType === "update-failed").map((e) => e.payload?.updateId).filter((e) => typeof e == "string" && e.length > 0)), c = a.find((e) => e.eventType === "update-requested" && e.payload?.updateName === t.name && typeof e.payload.updateId == "string" && !s.has(e.payload.updateId));
1788
+ if (c !== void 0) {
1789
+ let e = c.payload.updateId;
1790
+ yield* m.promise(() => ln(l, {
1791
+ runId: u,
1792
+ eventType: "update-received",
1793
+ payload: {
1794
+ updateId: e,
1795
+ updateName: t.name
1796
+ }
1797
+ }));
1798
+ let n = yield* y.decodeUnknown(t.schema)(c.payload?.value).pipe(m.tapErrorCause((n) => m.promise(() => ln(l, {
1799
+ runId: u,
1800
+ eventType: "update-failed",
1801
+ payload: {
1802
+ updateId: e,
1803
+ updateName: t.name,
1804
+ ...un(n)
1805
+ }
1806
+ })))), r = yield* (t.handle ? t.handle(n) : m.succeed(n)).pipe(m.flatMap((e) => t.success ? y.decodeUnknown(t.success)(e) : m.succeed(e))).pipe(m.tapErrorCause((n) => m.promise(() => ln(l, {
1807
+ runId: u,
1808
+ eventType: "update-failed",
1809
+ payload: {
1810
+ updateId: e,
1811
+ updateName: t.name,
1812
+ ...un(n)
1813
+ }
1814
+ }))));
1815
+ return yield* m.promise(() => ln(l, {
1816
+ runId: u,
1817
+ eventType: "update-completed",
1818
+ payload: {
1819
+ updateId: e,
1820
+ updateName: t.name,
1821
+ result: r
1822
+ }
1823
+ })), r;
1824
+ }
1825
+ yield* m.sleep(`${f} millis`), f = Math.min(f * 2, i);
1826
+ }
1827
+ });
1828
+ return c.make({
1829
+ name: `await-update:${t.name}`,
1830
+ success: t.success ?? t.schema,
1831
+ execute: r
1832
+ });
1833
+ }, fn = 8 * 1024, pn = 3, mn = 2e3, hn = () => {
1834
+ let e = (e) => {
1835
+ if (e === void 0) return;
1836
+ let t = Number(e);
1837
+ return Number.isFinite(t) && t > 0 ? Math.floor(t) : void 0;
1838
+ }, t = e(process.env.VOLTRO_WORKFLOW_MAX_RECLAIMS), n = e(process.env.VOLTRO_WORKFLOW_REPLAY_SHAPE_LIMIT);
1839
+ return {
1840
+ ...t === void 0 ? {} : { maxRunReclaims: t },
1841
+ ...n === void 0 ? {} : { replayShapeLimit: n }
1842
+ };
1843
+ }, gn = (e) => {
1844
+ let t = typeof e == "string" ? (() => {
1845
+ try {
1846
+ return JSON.parse(e);
1847
+ } catch {
1848
+ return;
1849
+ }
1850
+ })() : e;
1851
+ if (Array.isArray(t)) return t.filter((e) => typeof e == "string");
1852
+ }, _n = () => {
1853
+ let e = globalThis.crypto;
1854
+ return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1855
+ }, vn = (e) => `${e}_${_n()}`, Z = (e, t = fn) => {
1856
+ if (e == null) return e;
1857
+ try {
1858
+ let n = JSON.stringify(e);
1859
+ return n.length <= t ? e : {
1860
+ __truncated: !0,
1861
+ bytes: n.length,
1862
+ sample: n.slice(0, t)
1863
+ };
1864
+ } catch {
1865
+ return { __unserialisable: String(e) };
1866
+ }
1867
+ }, Q = (e) => {
1868
+ let t = {};
1869
+ for (let [n, r] of Object.entries(e)) t[n] = r instanceof Date ? r.toISOString() : r;
1870
+ return t;
1871
+ }, yn = (e) => {
1872
+ let t = e.truncateBytes ?? fn, n = e.makeId ?? vn, r = (t, n) => e.log?.warn(t, n), i = e.encryptStepPayload ?? ((e) => e), a = e.emit, o = e.recording === "coarse";
1873
+ return {
1874
+ startStep: async ({ runId: s, stepName: c, attempt: l, stepInput: u, retryPolicy: d }) => {
1875
+ if (!o) try {
1876
+ let r = await e.store.insert("_voltro_workflow_run_steps", {
1877
+ id: n("ws"),
1878
+ runId: s,
1879
+ stepName: c,
1880
+ attempt: l,
1881
+ status: "running",
1882
+ input: u === void 0 ? null : i(Z(u, t)),
1883
+ retryPolicy: d ?? null,
1884
+ output: null,
1885
+ errorTag: null,
1886
+ errorMessage: null,
1887
+ startedAt: /* @__PURE__ */ new Date(),
1888
+ completedAt: null,
1889
+ durationMs: null
1890
+ });
1891
+ return a?.("workflowSteps", {
1892
+ op: "insert",
1893
+ row: Q(r)
1894
+ }), r.id;
1895
+ } catch (e) {
1896
+ r("failed to record step start (continuing)", {
1897
+ runId: s,
1898
+ stepName: c,
1899
+ attempt: l,
1900
+ reason: e?.message ?? String(e)
1901
+ });
1902
+ return;
1903
+ }
1904
+ },
1905
+ endStepSuccess: async ({ stepRecordId: n, output: s, durationMs: c }) => {
1906
+ if (!o) try {
1907
+ let r = await e.store.update("_voltro_workflow_run_steps", n, {
1908
+ status: "succeeded",
1909
+ output: i(Z(s, t)),
1910
+ completedAt: /* @__PURE__ */ new Date(),
1911
+ durationMs: c
1912
+ });
1913
+ r && a?.("workflowSteps", {
1914
+ op: "update",
1915
+ row: Q(r)
1916
+ });
1917
+ } catch (e) {
1918
+ r("failed to record step success", {
1919
+ stepRecordId: n,
1920
+ reason: e?.message ?? String(e)
1921
+ });
1922
+ }
1923
+ },
1924
+ endStepFailure: async ({ stepRecordId: n, errorTag: s, errorMessage: c, errorCause: l, durationMs: u }) => {
1925
+ if (!o) try {
1926
+ let r = await e.store.update("_voltro_workflow_run_steps", n, {
1927
+ status: "failed",
1928
+ errorTag: s,
1929
+ errorMessage: c,
1930
+ errorCause: l === void 0 ? null : i(Z(l, t)),
1931
+ completedAt: /* @__PURE__ */ new Date(),
1932
+ durationMs: u
1933
+ });
1934
+ r && a?.("workflowSteps", {
1935
+ op: "update",
1936
+ row: Q(r)
1937
+ });
1938
+ } catch (e) {
1939
+ r("failed to record step failure", {
1940
+ stepRecordId: n,
1941
+ reason: e?.message ?? String(e)
1942
+ });
1943
+ }
1944
+ },
1945
+ recordEvent: async ({ runId: t, eventType: i, payload: o, stepName: s, attempt: c }) => {
1946
+ let l = n("wfev");
1947
+ try {
1948
+ let n = await e.store.insert("_voltro_workflow_run_events", {
1949
+ id: l,
1950
+ runId: t,
1951
+ eventType: i,
1952
+ payload: o ?? null,
1953
+ occurredAt: /* @__PURE__ */ new Date(),
1954
+ stepName: s ?? null,
1955
+ attempt: c ?? null
1956
+ });
1957
+ a?.("workflowEvents", {
1958
+ op: "insert",
1959
+ row: Q(n)
1960
+ });
1961
+ } catch (e) {
1962
+ r("failed to record workflow event (continuing)", {
1963
+ runId: t,
1964
+ eventType: i,
1965
+ reason: e?.message ?? String(e)
1966
+ });
1967
+ }
1968
+ if (e.wakeups !== void 0) {
1969
+ let n = o?.scheduledWakeAt, r = typeof n == "string" ? new Date(n) : void 0, a = o?.tenantId, s = typeof a == "string" ? a : void 0;
1970
+ i === "timer-set" && r !== void 0 && !Number.isNaN(r.getTime()) ? await e.wakeups.register(t, r, s).catch(() => {}) : (i === "timer-fired" || i === "run-succeeded" || i === "run-failed" || i === "run-cancelled") && await e.wakeups.cancel(t, s).catch(() => {});
1971
+ }
1972
+ return { id: l };
1973
+ }
1974
+ };
1975
+ }, bn = (e, t, n) => m.gen(function* () {
1976
+ let r = e.store.query;
1977
+ if (r === void 0) return;
1978
+ let i = e.replayShapeLimit ?? 2e3, a = yield* m.promise(() => r({
1979
+ table: "_voltro_workflow_run_steps",
1980
+ order: [{
1981
+ column: "startedAt",
1982
+ direction: "asc"
1983
+ }],
1984
+ predicate: x("runId", t),
1985
+ projection: ["stepName"],
1986
+ skip: void 0,
1987
+ take: i + 1
1988
+ }).catch((e) => (n("failed to read the replay shape (nondeterminism tripwire disabled for this attempt)", {
1989
+ runId: t,
1990
+ reason: e?.message ?? String(e)
1991
+ }), [])));
1992
+ if (a.length === 0) return;
1993
+ if (a.length > i) {
1994
+ n("replay shape exceeds the step limit — nondeterminism tripwire disabled for this run", {
1995
+ runId: t,
1996
+ limit: i
1997
+ });
1998
+ return;
1999
+ }
2000
+ let s = a.flatMap((e) => {
2001
+ let t = e.stepName;
2002
+ return typeof t == "string" ? [{ stepName: t }] : [];
2003
+ });
2004
+ return s.length === 0 ? void 0 : o(s);
2005
+ }), xn = (o, c) => {
2006
+ let l = o.truncateBytes ?? fn, u = o.makeId ?? vn, f = o.recorder ?? yn(o), h = (e, t) => o.log?.warn(e, t), v = o.emit, y = (e, t, n) => m.promise(async () => {
2007
+ if (o.onParentClose) try {
2008
+ await o.onParentClose({
2009
+ workflowName: o.name,
2010
+ executionId: e,
2011
+ ...n === void 0 ? {} : { runId: n },
2012
+ status: t
2013
+ });
2014
+ } catch (n) {
2015
+ h("failed to apply workflow parent-close policy", {
2016
+ tag: o.name,
2017
+ executionId: e,
2018
+ status: t,
2019
+ reason: n?.message ?? String(n)
2020
+ });
2021
+ }
2022
+ }), b = (e, t, n) => m.promise(async () => {
2023
+ if (o.onTerminal) try {
2024
+ await o.onTerminal({
2025
+ workflowName: o.name,
2026
+ executionId: e,
2027
+ ...n === void 0 ? {} : { runId: n },
2028
+ status: t
2029
+ });
2030
+ } catch (n) {
2031
+ h("failed to release the workflow admission lease", {
2032
+ tag: o.name,
2033
+ executionId: e,
2034
+ status: t,
2035
+ reason: n?.message ?? String(n)
2036
+ });
2037
+ }
2038
+ });
2039
+ return (ee, S) => m.gen(function* () {
2040
+ let C = Date.now(), te = yield* _.get(r), w = o.parentExecutionId ?? te ?? null, ne = o.parentClosePolicy ?? null, T, E = (e, t) => t.pipe(m.catchAllCause((t) => p.isInterrupted(t) ? m.failCause(t) : m.sync(() => {
2041
+ let n = p.squash(t);
2042
+ h(e, {
2043
+ tag: o.name,
2044
+ executionId: S,
2045
+ reason: n?.message ?? String(n)
2046
+ });
2047
+ }))), D = (o.store.query ? yield* m.promise(() => o.store.query({
2048
+ table: "_voltro_workflow_runs",
2049
+ order: [],
2050
+ predicate: x("executionId", S),
2051
+ projection: void 0,
2052
+ skip: void 0,
2053
+ take: 1
2054
+ })) : [])[0], O = D?.workflowVersion ?? null;
2055
+ if (D?.id !== void 0 && O !== null && o.workflowCompatibleVersions !== void 0 && o.workflowCompatibleVersions !== null && !o.workflowCompatibleVersions.includes(O)) {
2056
+ let e = `Workflow '${o.name}' run '${S}' was started on version ${O}, but current code is compatible with ${o.workflowCompatibleVersions.join(", ")}`, t = yield* m.promise(() => o.store.update("_voltro_workflow_runs", D.id, {
2057
+ status: "failed",
2058
+ errorTag: "WorkflowVersionIncompatible",
2059
+ errorMessage: e,
2060
+ completedAt: /* @__PURE__ */ new Date(),
2061
+ runnerEnteredAt: null
2062
+ }));
2063
+ return t && v?.("workflowRuns", {
2064
+ op: "update",
2065
+ row: Q(t)
2066
+ }), yield* m.promise(() => f.recordEvent({
2067
+ runId: D.id,
2068
+ eventType: "run-failed",
2069
+ payload: {
2070
+ errorTag: "WorkflowVersionIncompatible",
2071
+ errorMessage: e,
2072
+ workflowVersion: o.workflowVersion ?? null,
2073
+ compatibleWith: o.workflowCompatibleVersions,
2074
+ previousVersion: O
2075
+ }
2076
+ })), yield* m.sync(() => o.recordRun?.({
2077
+ name: o.name,
2078
+ status: "failed",
2079
+ durationMs: 0
2080
+ })), yield* m.fail(Error(e));
2081
+ }
2082
+ let k = o.workflowPatches ?? [], A;
2083
+ if (D?.id !== void 0) {
2084
+ T = D.id, k = gn(D.workflowPatches) ?? k;
2085
+ let e = D.runnerEnteredAt !== null && D.runnerEnteredAt !== void 0, t = typeof D.reclaimCount == "number" ? D.reclaimCount : Number(D.reclaimCount ?? 0), n = e ? (Number.isFinite(t) ? t : 0) + 1 : 0, r = o.maxRunReclaims ?? 3;
2086
+ if (e && n >= r) {
2087
+ let e = `Workflow '${o.name}' run '${S}' killed its runner ${n} times in a row; parked instead of reclaimed again (maxRunReclaims=${r}).`;
2088
+ yield* E("failed to record workflow crash-loop park", m.gen(function* () {
2089
+ let t = yield* m.promise(() => o.store.update("_voltro_workflow_runs", T, {
2090
+ status: "suspended",
2091
+ errorTag: "WorkflowCrashLooped",
2092
+ errorMessage: e,
2093
+ reclaimCount: n,
2094
+ runnerEnteredAt: null
2095
+ }));
2096
+ t && v?.("workflowRuns", {
2097
+ op: "update",
2098
+ row: Q(t)
2099
+ }), yield* m.promise(() => f.recordEvent({
2100
+ runId: T,
2101
+ eventType: "run-crashlooped",
2102
+ payload: {
2103
+ reclaimCount: n,
2104
+ maxRunReclaims: r,
2105
+ executionId: S,
2106
+ tag: o.name
2107
+ }
2108
+ }));
2109
+ })), h("workflow run parked after repeated runner deaths", {
2110
+ tag: o.name,
2111
+ executionId: S,
2112
+ runId: T,
2113
+ reclaimCount: n,
2114
+ maxRunReclaims: r
2115
+ });
2116
+ let t = yield* se;
2117
+ return yield* d.suspend(t);
2118
+ }
2119
+ A = yield* bn(o, T, h), yield* E("failed to record workflow re-entry", m.gen(function* () {
2120
+ let t = yield* m.promise(() => o.store.update("_voltro_workflow_runs", T, {
2121
+ status: "running",
2122
+ errorTag: null,
2123
+ errorMessage: null,
2124
+ completedAt: null,
2125
+ reclaimCount: n,
2126
+ runnerEnteredAt: /* @__PURE__ */ new Date()
2127
+ }));
2128
+ t && v?.("workflowRuns", {
2129
+ op: "update",
2130
+ row: Q(t)
2131
+ }), e && (yield* m.promise(() => f.recordEvent({
2132
+ runId: T,
2133
+ eventType: "run-resumed",
2134
+ payload: {
2135
+ reason: "runner-reclaim",
2136
+ reclaimCount: n,
2137
+ maxRunReclaims: r
2138
+ }
2139
+ })));
2140
+ }));
2141
+ } else yield* E("failed to record workflow start (continuing)", m.gen(function* () {
2142
+ let e = yield* m.promise(() => o.store.insert("_voltro_workflow_runs", {
2143
+ id: u("wr"),
2144
+ tag: o.name,
2145
+ executionId: S,
2146
+ status: "running",
2147
+ payload: ee,
2148
+ workflowVersion: o.workflowVersion ?? null,
2149
+ workflowPatches: o.workflowPatches ?? null,
2150
+ output: null,
2151
+ subject: o.subject ?? null,
2152
+ source: o.source ?? null,
2153
+ errorTag: null,
2154
+ errorMessage: null,
2155
+ cancelled: !1,
2156
+ startedAt: /* @__PURE__ */ new Date(),
2157
+ completedAt: null,
2158
+ durationMs: null,
2159
+ traceId: o.traceId ?? null,
2160
+ parentExecutionId: w,
2161
+ parentClosePolicy: ne,
2162
+ runnerEnteredAt: /* @__PURE__ */ new Date(),
2163
+ reclaimCount: 0
2164
+ }));
2165
+ if (T = e.id, v?.("workflowRuns", {
2166
+ op: "insert",
2167
+ row: Q(e)
2168
+ }), T) {
2169
+ let e = T;
2170
+ yield* m.promise(() => f.recordEvent({
2171
+ runId: e,
2172
+ eventType: "run-started",
2173
+ payload: {
2174
+ tag: o.name,
2175
+ executionId: S,
2176
+ source: o.source ?? null,
2177
+ workflowVersion: o.workflowVersion ?? null,
2178
+ workflowPatches: o.workflowPatches ?? null,
2179
+ parentExecutionId: w,
2180
+ parentClosePolicy: ne
2181
+ }
2182
+ }));
2183
+ }
2184
+ }));
2185
+ let re = o.subject?.tenantId, ie = c(ee, S).pipe(m.locally(a, T), m.locally(r, S), m.locally(t, typeof re == "string" ? re : void 0), m.locally(i, k), m.locally(s, A), m.provideService(n, f)), ae = o.pluginWorkflowStepLayer ? ie.pipe(m.provide(o.pluginWorkflowStepLayer)) : ie, j = yield* d.intoResult(ae);
2186
+ if (d.isResult(j) && j._tag === "Suspended") {
2187
+ let e = j.cause, t = e !== void 0 && !p.isEmpty(e), n = t ? p.squash(e) : void 0, r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, i = t ? n?.message ?? String(n) : null;
2188
+ t && (yield* m.sync(() => ce({
2189
+ error: n,
2190
+ source: "workflow",
2191
+ name: o.name,
2192
+ ...o.traceId ? { traceId: o.traceId } : {},
2193
+ fields: {
2194
+ executionId: S,
2195
+ suspendedOnFailure: !0,
2196
+ ...r ? { errorTag: r } : {},
2197
+ ...T ? { runId: T } : {}
2198
+ }
2199
+ }))), T && (yield* E("failed to record workflow suspend", m.gen(function* () {
2200
+ let e = yield* m.promise(() => o.store.update("_voltro_workflow_runs", T, {
2201
+ status: "suspended",
2202
+ runnerEnteredAt: null,
2203
+ ...t ? {
2204
+ errorTag: r,
2205
+ errorMessage: i
2206
+ } : {}
2207
+ }));
2208
+ e && v?.("workflowRuns", {
2209
+ op: "update",
2210
+ row: Q(e)
2211
+ }), yield* m.promise(() => f.recordEvent({
2212
+ runId: T,
2213
+ eventType: "run-suspended",
2214
+ payload: t ? {
2215
+ reason: "suspend-on-failure",
2216
+ errorTag: r,
2217
+ errorMessage: i
2218
+ } : { reason: "workflow-suspend" }
2219
+ }));
2220
+ })));
2221
+ let a = yield* se;
2222
+ return yield* d.suspend(a);
2223
+ }
2224
+ let M = j;
2225
+ if (A !== void 0 && T !== void 0) {
2226
+ let t = A.settle();
2227
+ if (t.length > 0) {
2228
+ let n = T;
2229
+ h("workflow replay reached a different step shape than this run recorded", {
2230
+ tag: o.name,
2231
+ executionId: S,
2232
+ runId: n,
2233
+ findings: t.map((e) => `${e.kind}:${e.stepName}`)
2234
+ }), yield* E("failed to record nondeterminism findings", m.promise(async () => {
2235
+ for (let r of t) await f.recordEvent({
2236
+ runId: n,
2237
+ eventType: "nondeterminism-suspected",
2238
+ payload: e(r)
2239
+ }).catch(() => void 0);
2240
+ }));
2241
+ }
2242
+ }
2243
+ if (g.isFailure(M.exit)) {
2244
+ let e = M.exit.cause, t = p.failureOption(e), n = t._tag === "Some" ? t.value : p.squash(e), r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, i = n?.message ?? String(n);
2245
+ return yield* m.sync(() => ce({
2246
+ error: n,
2247
+ source: "workflow",
2248
+ name: o.name,
2249
+ ...o.traceId ? { traceId: o.traceId } : {},
2250
+ fields: {
2251
+ executionId: S,
2252
+ ...r ? { errorTag: r } : {},
2253
+ ...T ? { runId: T } : {}
2254
+ }
2255
+ })), T && (yield* E("failed to record workflow failure", m.gen(function* () {
2256
+ let e = yield* m.promise(() => o.store.update("_voltro_workflow_runs", T, {
2257
+ status: "failed",
2258
+ errorTag: r,
2259
+ errorMessage: i,
2260
+ completedAt: /* @__PURE__ */ new Date(),
2261
+ durationMs: Date.now() - C,
2262
+ runnerEnteredAt: null
2263
+ }));
2264
+ e && v?.("workflowRuns", {
2265
+ op: "update",
2266
+ row: Q(e)
2267
+ }), yield* m.promise(() => f.recordEvent({
2268
+ runId: T,
2269
+ eventType: "run-failed",
2270
+ payload: {
2271
+ errorTag: r,
2272
+ errorMessage: i,
2273
+ durationMs: Date.now() - C
2274
+ }
2275
+ })), yield* y(S, "failed", T);
2276
+ }))), yield* b(S, "failed", T), yield* m.sync(() => o.recordRun?.({
2277
+ name: o.name,
2278
+ status: "failed",
2279
+ durationMs: Date.now() - C
2280
+ })), yield* m.failCause(e);
2281
+ }
2282
+ let N = M.exit.value;
2283
+ return T && (yield* E("failed to record workflow success", m.gen(function* () {
2284
+ let e = yield* m.promise(() => o.store.update("_voltro_workflow_runs", T, {
2285
+ status: "succeeded",
2286
+ output: Z(N, l),
2287
+ completedAt: /* @__PURE__ */ new Date(),
2288
+ durationMs: Date.now() - C,
2289
+ runnerEnteredAt: null
2290
+ }));
2291
+ e && v?.("workflowRuns", {
2292
+ op: "update",
2293
+ row: Q(e)
2294
+ }), yield* m.promise(() => f.recordEvent({
2295
+ runId: T,
2296
+ eventType: "run-succeeded",
2297
+ payload: { durationMs: Date.now() - C }
2298
+ })), yield* y(S, "succeeded", T);
2299
+ }))), yield* b(S, "succeeded", T), yield* m.sync(() => o.recordRun?.({
2300
+ name: o.name,
2301
+ status: "succeeded",
2302
+ durationMs: Date.now() - C,
2303
+ completedAtSec: Date.now() / 1e3
2304
+ })), N;
2305
+ });
2306
+ }, Sn = (e) => e === "cancel" || e === "terminate", Cn = (e) => e === "running" || e === "suspended", wn = async (e) => {
2307
+ let t = await e.store.query({
2308
+ table: "_voltro_workflow_runs",
2309
+ order: [{
2310
+ column: "startedAt",
2311
+ direction: "asc"
2312
+ }],
2313
+ predicate: x("parentExecutionId", e.parentExecutionId),
2314
+ projection: void 0,
2315
+ skip: void 0,
2316
+ take: e.limit ?? 1e3
2317
+ }), n = [];
2318
+ for (let r of t) {
2319
+ let t = {
2320
+ runId: r.id,
2321
+ workflowName: r.tag,
2322
+ executionId: r.executionId,
2323
+ policy: r.parentClosePolicy
2324
+ };
2325
+ if (r.parentClosePolicy === "abandon") {
2326
+ n.push({
2327
+ ...t,
2328
+ action: "abandoned"
2329
+ });
2330
+ continue;
2331
+ }
2332
+ if (!Sn(r.parentClosePolicy)) {
2333
+ n.push({
2334
+ ...t,
2335
+ action: "skipped",
2336
+ reason: "no-parent-close-policy"
2337
+ });
2338
+ continue;
2339
+ }
2340
+ if (!Cn(r.status)) {
2341
+ n.push({
2342
+ ...t,
2343
+ action: "skipped",
2344
+ reason: `status:${r.status}`
2345
+ });
2346
+ continue;
2347
+ }
2348
+ try {
2349
+ await e.interruptChild(r.tag, r.executionId, r.parentClosePolicy);
2350
+ let i = await e.store.update("_voltro_workflow_runs", r.id, {
2351
+ status: "cancelled",
2352
+ cancelled: !0,
2353
+ completedAt: /* @__PURE__ */ new Date()
2354
+ });
2355
+ i && e.emit?.("workflowRuns", {
2356
+ op: "update",
2357
+ row: Q(i)
2358
+ }), await e.recorder?.recordEvent({
2359
+ runId: r.id,
2360
+ eventType: "run-cancelled",
2361
+ payload: {
2362
+ reason: "parent-close",
2363
+ parentExecutionId: e.parentExecutionId,
2364
+ parentStatus: e.parentStatus,
2365
+ parentClosePolicy: r.parentClosePolicy,
2366
+ action: r.parentClosePolicy
2367
+ }
2368
+ }), n.push({
2369
+ ...t,
2370
+ action: "cancelled"
2371
+ });
2372
+ } catch (i) {
2373
+ let a = i?.message ?? String(i);
2374
+ e.log?.warn("workflow.parentClose.childInterrupt failed", {
2375
+ parentExecutionId: e.parentExecutionId,
2376
+ childExecutionId: r.executionId,
2377
+ childWorkflowName: r.tag,
2378
+ parentClosePolicy: r.parentClosePolicy,
2379
+ reason: a
2380
+ }), n.push({
2381
+ ...t,
2382
+ action: "failed",
2383
+ reason: a
2384
+ });
2385
+ }
2386
+ }
2387
+ return n;
2388
+ }, Tn = (e) => {
2389
+ if (e == null) return null;
2390
+ if (e instanceof Date) return e;
2391
+ if (typeof e == "string" || typeof e == "number") {
2392
+ let t = new Date(e);
2393
+ return Number.isNaN(t.getTime()) ? null : t;
2394
+ }
2395
+ return null;
2396
+ }, En = (e) => typeof e == "number" ? e : e == null ? null : Number(e), $ = (e) => e == null ? null : String(e), Dn = (e) => {
2397
+ let t = /* @__PURE__ */ new Map();
2398
+ for (let n of e) {
2399
+ let e = String(n.stepName), r = t.get(e);
2400
+ r === void 0 ? t.set(e, [n]) : r.push(n);
2401
+ }
2402
+ let n = [];
2403
+ for (let [e, r] of t) {
2404
+ r.sort((e, t) => (En(e.attempt) ?? 0) - (En(t.attempt) ?? 0));
2405
+ let t = r[r.length - 1], i = $(t.errorTag), a = $(t.errorMessage), o = i !== null || a !== null ? {
2406
+ tag: i,
2407
+ message: a ?? ""
2408
+ } : null;
2409
+ n.push({
2410
+ name: e,
2411
+ attempt: En(t.attempt) ?? r.length,
2412
+ attempts: r.length,
2413
+ status: t.status ?? "running",
2414
+ input: t.input ?? null,
2415
+ output: t.output ?? null,
2416
+ error: o,
2417
+ durationMs: En(t.durationMs)
2418
+ });
2419
+ }
2420
+ return n.sort((t, n) => {
2421
+ let r = e.find((e) => String(e.stepName) === t.name), i = e.find((e) => String(e.stepName) === n.name);
2422
+ return (Tn(r?.startedAt)?.getTime() ?? 0) - (Tn(i?.startedAt)?.getTime() ?? 0);
2423
+ }), n;
2424
+ }, On = (e) => {
2425
+ if (e == null) return null;
2426
+ if (typeof e == "string") try {
2427
+ return JSON.parse(e);
2428
+ } catch {
2429
+ return null;
2430
+ }
2431
+ return typeof e == "object" ? e : null;
2432
+ }, kn = async (e, t) => {
2433
+ let n = A(P), r = (await t.query(n.where(k(x("id", e), x("executionId", e))).limit(1).descriptor))[0];
2434
+ if (r === void 0) return null;
2435
+ let i = String(r.id), a = A(ue), o = await t.query(a.where(x("runId", i)).descriptor);
2436
+ return {
2437
+ id: i,
2438
+ executionId: $(r.executionId) ?? "",
2439
+ name: $(r.tag) ?? "",
2440
+ status: r.status ?? "running",
2441
+ input: r.payload ?? null,
2442
+ output: r.output ?? null,
2443
+ subject: On(r.subject),
2444
+ source: $(r.source),
2445
+ steps: Dn(o),
2446
+ startedAt: Tn(r.startedAt) ?? /* @__PURE__ */ new Date(0),
2447
+ finishedAt: Tn(r.completedAt),
2448
+ traceId: $(r.traceId),
2449
+ parentExecutionId: $(r.parentExecutionId),
2450
+ parentClosePolicy: $(r.parentClosePolicy)
2451
+ };
2452
+ }, An = () => {
2453
+ let e = [], t = [], r = 0, i = 0;
2454
+ return {
2455
+ layer: v.succeed(n, {
2456
+ startStep: async ({ runId: t, stepName: n, attempt: i, stepInput: a, retryPolicy: o }) => {
2457
+ let s = `wfstep_mem_${++r}`;
2458
+ return e.push({
2459
+ id: s,
2460
+ runId: t,
2461
+ stepName: n,
2462
+ attempt: i,
2463
+ status: "running",
2464
+ input: a ?? null,
2465
+ retryPolicy: o ?? null,
2466
+ output: null,
2467
+ errorTag: null,
2468
+ errorMessage: null,
2469
+ errorCause: null,
2470
+ startedAt: /* @__PURE__ */ new Date(),
2471
+ completedAt: null,
2472
+ durationMs: null
2473
+ }), s;
2474
+ },
2475
+ endStepSuccess: async ({ stepRecordId: t, output: n, durationMs: r }) => {
2476
+ let i = e.find((e) => e.id === t);
2477
+ i !== void 0 && (i.status = "succeeded", i.output = n, i.completedAt = /* @__PURE__ */ new Date(), i.durationMs = r);
2478
+ },
2479
+ endStepFailure: async ({ stepRecordId: t, errorTag: n, errorMessage: r, errorCause: i, durationMs: a }) => {
2480
+ let o = e.find((e) => e.id === t);
2481
+ o !== void 0 && (o.status = "failed", o.errorTag = n, o.errorMessage = r, o.errorCause = i ?? null, o.completedAt = /* @__PURE__ */ new Date(), o.durationMs = a);
2482
+ },
2483
+ recordEvent: async ({ runId: e, eventType: n, payload: r, stepName: a, attempt: o }) => {
2484
+ let s = `wfev_mem_${++i}`;
2485
+ return t.push({
2486
+ id: s,
2487
+ runId: e,
2488
+ eventType: n,
2489
+ payload: r ?? null,
2490
+ stepName: a ?? null,
2491
+ attempt: o ?? null,
2492
+ occurredAt: /* @__PURE__ */ new Date()
2493
+ }), { id: s };
2494
+ }
2495
+ }),
2496
+ readSteps: () => e,
2497
+ readEvents: () => t
2498
+ };
2499
+ };
2500
+ //#endregion
2501
+ export { Je as $, zt as A, _e as At, at as B, tn as C, Ae as Ct, It as D, Se as Dt, Ht as E, ye as Et, Dt as F, fe as Ft, Qe as G, ot as H, Tt as I, de as It, Xe as J, $e as K, wt as L, ue as Lt, At as M, me as Mt, St as N, he as Nt, Lt as O, xe as Ot, Ot as P, pe as Pt, Ye as Q, ht as R, P as Rt, on as S, W as St, Kt as T, Ce as Tt, pt as U, st as V, K as W, it as X, et as Y, tt as Z, Xt as _, Ne as _t, mn as a, we as at, cn as b, Oe as bt, hn as c, G as ct, xn as d, Ve as dt, Ke as et, dn as f, Be as ft, Zt as g, Le as gt, en as h, Ee as ht, pn as i, Te as it, Mt as j, I as jt, Rt as k, ve as kt, Q as l, ze as lt, $t as m, ke as mt, kn as n, Ge as nt, yn as o, R as ot, X as p, Pe as pt, Ze as q, wn as r, z as rt, gn as s, Re as st, An as t, Ue as tt, Z as u, Ie as ut, Yt as v, He as vt, Gt as w, ge as wt, sn as x, U as xt, Jt as y, je as yt, gt as z, le as zt };