@voltro/plugin-ai-flows 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1748 +1,53 @@
1
- import { FLOW_RUN_WORKFLOW as e, HUMAN_RESPONSE_SIGNAL_PREFIX as t, flowRunWorkflow as n, humanResponseSignalName as r } from "./workflow.js";
2
- import { A as i, B as a, C as o, D as s, E as c, F as l, H as u, I as d, L as f, M as p, N as m, O as h, P as g, R as ee, S as _, T as te, V as v, _ as ne, a as re, b as y, c as ie, d as b, f as x, g as ae, h as oe, i as S, j as se, k as ce, l as le, m as ue, n as de, o as C, p as fe, r as pe, s as me, t as he, u as ge, v as _e, w as ve, x as ye, y as be, z as xe } from "./ir-Cjk1kQl9.js";
3
- import { FlowBriefIncomplete as Se, FlowCapabilityMissing as w, FlowDependencyError as Ce, FlowNotAwaitingResponse as we, FlowNotFound as Te, FlowReviewDeliveryError as Ee, FlowRunNotFound as T, FlowValidationError as De } from "./errors.js";
4
- import { n as Oe, t as ke } from "./cadence-_9Izk_fL.js";
5
- import { Cause as E, Effect as D, Exit as Ae, Result as O, Schema as k } from "effect";
6
- import { WorkflowControlResultSchema as je, WorkflowRunHandleSchema as Me, definePlugin as Ne, pluginInstanceName as Pe } from "@voltro/protocol";
7
- import { and as Fe, boolean as Ie, eq as A, id as Le, inSet as Re, integer as j, json as M, notInSet as ze, queryFor as N, registerRetention as Be, table as Ve, text as P, timestamp as He } from "@voltro/database";
8
- import { tenant as Ue } from "@voltro/plugin-multitenancy/mixin";
9
- import { audit as We } from "@voltro/plugin-audit/mixin";
10
- import { softDelete as Ge } from "@voltro/plugin-soft-delete/mixin";
11
- import { SuspensionUnavailable as Ke, awaitSignalSuspending as qe, step as F } from "@voltro/workflow";
12
- import { defineTool as Je, estimateCostUsd as Ye, gatewayCostUsd as Xe, generateImage as Ze, generateObject as Qe, generateObjectJson as $e, generateObjectWithTools as et, generateSpeech as tt, generateText as nt, generateVideo as rt, isMeteredUsage as it } from "@voltro/ai";
13
- import { createHash as at } from "node:crypto";
14
- //#region src/registry.ts
15
- var I = /* @__PURE__ */ new Map(), ot = (e) => {
16
- I.set(e.name, e);
17
- }, st = (e) => I.get(e), ct = () => [...I.values()], lt = () => I.clear(), L = Ve("_voltro_ai_flows", {
18
- id: Le({ prefix: "aifl" }),
19
- name: P(),
20
- description: P().nullable(),
21
- mode: P().default("deterministic"),
22
- status: P().default("draft"),
23
- visibility: P().default("private"),
24
- orchestratorModel: P().nullable(),
25
- orchestratorInstructions: P().nullable(),
26
- maxSteps: j().default(30),
27
- steps: M().nullable(),
28
- inputSchema: M().nullable(),
29
- chainTo: M().nullable(),
30
- cadence: M().nullable(),
31
- humanTimeoutMs: j().nullable(),
32
- isEnabled: Ie().default(!0),
33
- metadata: M().nullable(),
34
- icon: P().nullable(),
35
- color: P().nullable(),
36
- avatarUrl: P().nullable(),
37
- usageCount: j().default(0),
38
- ownerId: P().nullable()
39
- }).renamedFrom("ai_flows").with(Ue(), We(), Ge()).index(["status"]).index(["visibility"]), R = Ve("_voltro_ai_flow_runs", {
40
- id: Le({ prefix: "aifr" }),
41
- flowRef: P(),
42
- flowName: P().nullable(),
43
- mode: P().default("deterministic"),
44
- status: P().default("pending"),
45
- source: P().nullable(),
46
- requestId: P(),
47
- workflowStart: M().nullable(),
48
- input: M().nullable(),
49
- output: M().nullable(),
50
- steps: M().nullable(),
51
- currentStep: j().default(0),
52
- totalSteps: j().default(0),
53
- humanResponse: M().nullable(),
54
- chainPending: M().nullable(),
55
- chainRefusal: P().nullable(),
56
- costMicroUsd: j().default(0),
57
- costCompleteness: P().default("unknown"),
58
- durationMs: j().nullable(),
59
- error: P().nullable(),
60
- errorMessage: P().nullable(),
61
- startedAt: He().nullable(),
62
- completedAt: He().nullable(),
63
- cancelledAt: He().nullable(),
64
- sessionId: P().nullable(),
65
- sessionName: P().nullable(),
66
- ownerId: P().nullable(),
67
- metadata: M().nullable()
68
- }).renamedFrom("ai_flow_runs").with(Ue(), We()).index(["flowRef"]).index(["status"]).index(["requestId"]), ut = [L, R], dt = k.Struct({
69
- id: k.NonEmptyString,
70
- workflowName: k.Literal(e),
71
- status: k.Literal("queued")
72
- }), ft = (t) => ({
73
- id: t,
74
- workflowName: e,
75
- executionId: t,
76
- status: "running"
77
- }), pt = (e) => {
78
- let t = `flow start was not executed: ${e.reason}`;
79
- return e.incumbentExecutionId === null ? e.failureId === null ? t : `${t} (failure report ${e.failureId})` : `${t} (incumbent execution ${e.incumbentExecutionId})`;
80
- }, mt = async (e, t = {}) => {
81
- let n = e.workflows;
82
- if (!n) throw Error("workflow runtime unavailable; flow starts cannot be reconciled");
83
- if (n.startsDeferredUntilCommit === !0) return {
84
- examined: 0,
85
- accepted: 0,
86
- notExecuted: 0,
87
- pending: 0,
88
- failures: []
89
- };
90
- let r = t.take ?? 200, i = await e.store.query({
91
- table: R.tableName,
92
- predicate: A("status", "pending"),
93
- order: [],
94
- take: r,
95
- skip: void 0,
96
- projection: void 0
97
- }), a = {
98
- examined: 0,
99
- accepted: 0,
100
- notExecuted: 0,
101
- pending: 0,
102
- failures: []
103
- };
104
- for (let t of i) {
105
- let r = t.id;
106
- if (typeof r != "string") continue;
107
- let i = k.decodeUnknownOption(dt)(t.workflowStart);
108
- if (i._tag !== "None") {
109
- a.examined++;
110
- try {
111
- let t = await n.readStart({
112
- ...i.value,
113
- executionId: null
114
- });
115
- if (t.kind === "pending") {
116
- a.pending++;
117
- continue;
118
- }
119
- let o = (/* @__PURE__ */ new Date()).toISOString();
120
- if (t.kind === "accepted") {
121
- if (await e.store.update(R.tableName, r, { workflowStart: ft(t.executionId) }) === null) throw Error("flow run disappeared while recording its accepted start");
122
- a.accepted++;
123
- continue;
124
- }
125
- if (await e.store.update(R.tableName, r, {
126
- status: "failed",
127
- error: "FlowStartNotExecuted",
128
- errorMessage: pt(t),
129
- completedAt: o
130
- }) === null) throw Error("flow run disappeared while recording that its start will not execute");
131
- a.notExecuted++;
132
- } catch (e) {
133
- a.failures.push({
134
- runId: r,
135
- cause: e
136
- });
137
- }
138
- }
139
- }
140
- return a;
141
- }, ht = 168, gt = "VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS", _t = 2160, vt = "VOLTRO_AI_FLOW_RUNS_TTL_HOURS", yt = 5, bt = "VOLTRO_AI_FLOW_MAX_CHAIN_DEPTH", xt = { current: {} }, St = (e) => {
142
- xt.current = e;
143
- }, Ct = () => xt.current, wt = () => {
144
- xt.current = {};
145
- }, Tt = (e, t) => {
146
- if (e === void 0 || e.trim() === "") return t * 36e5;
147
- let n = Number(e);
148
- return !Number.isFinite(n) || n < 0 ? t * 36e5 : n * 36e5;
149
- }, Et = (e) => Number.isFinite(e) && e > 0 ? e : Infinity, Dt = (e) => {
150
- let t = e.env ?? process.env;
151
- return Et(e.step?.timeoutMs ?? e.flow?.humanTimeoutMs ?? e.deps?.humanReviewTimeoutMs ?? Ct().humanReviewTimeoutMs ?? Tt(t.VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS, 168));
152
- }, Ot = (e) => {
153
- let t = e?.env ?? process.env, n = Number(t[bt]), r = e?.maxChainDepth ?? Ct().maxChainDepth ?? (Number.isFinite(n) && n >= 1 ? n : 5);
154
- return Number.isFinite(r) && r >= 1 ? r : 5;
155
- }, kt = /\{\{\s*([\w.-]+)\s*\}\}/g, At = (e) => {
156
- let t = [];
157
- for (let n of e.matchAll(kt)) t.push(n[1]);
158
- return t;
159
- }, jt = (e, t) => e.replace(kt, (e, n) => {
160
- let r = t[n];
161
- return r == null ? "" : typeof r == "string" ? r : JSON.stringify(r);
162
- }), Mt = (e, t) => {
163
- let n = /* @__PURE__ */ new Set();
164
- for (let r of At(e)) t[r] == null && !n.has(r) && n.add(r);
165
- return [...n];
166
- }, Nt = (e) => {
167
- let t = [], n;
168
- if (e.forEach((e, r) => {
169
- let i = e.group;
170
- if (i !== void 0 && n !== void 0 && n.group === i) {
171
- n.steps.push({
172
- index: r,
173
- step: e
174
- });
175
- return;
176
- }
177
- n !== void 0 && t.push({
178
- ...n.group === void 0 ? {} : { group: n.group },
179
- steps: n.steps
180
- }), n = {
181
- ...i === void 0 ? {} : { group: i },
182
- steps: [{
183
- index: r,
184
- step: e
185
- }]
186
- };
187
- }), n !== void 0) {
188
- let e = n;
189
- t.push({
190
- ...e.group === void 0 ? {} : { group: e.group },
191
- steps: e.steps
192
- });
193
- }
194
- return t;
195
- }, Pt = (e) => {
196
- let t = /* @__PURE__ */ new Map();
197
- for (let n of e) n.group !== void 0 && t.set(n.group, (t.get(n.group) ?? 0) + 1);
198
- return [...t.entries()].filter(([, e]) => e > 1).map(([e]) => e).sort();
199
- }, Ft = k.suspend(() => k.Union([
200
- k.Null,
201
- k.Boolean,
202
- k.Finite,
203
- k.String,
204
- k.Array(Ft).pipe(k.mutable),
205
- k.Record(k.String, Ft)
206
- ])), z = k.Record(k.String, k.Record(k.String, Ft)), It = k.Struct({
207
- maxTokens: k.optionalKey(k.Int.pipe(k.check(k.isGreaterThan(0)), k.check(k.isLessThanOrEqualTo(2 ** 53 - 1)))),
208
- temperature: k.optionalKey(k.Finite.pipe(k.check(k.isGreaterThanOrEqualTo(0)))),
209
- providerOptions: k.optionalKey(z)
210
- }), Lt = [
211
- "maxTokens",
212
- "temperature",
213
- "providerOptions"
214
- ], Rt = (e) => {
215
- if (typeof e != "object" || !e || Array.isArray(e)) return "params must be an object";
216
- let t = Object.keys(e), n = t.filter((e) => !Lt.includes(e)).sort(), r = t.filter((t) => Lt.includes(t) && k.decodeUnknownOption(It)({ [t]: e[t] })._tag === "None").sort();
217
- return [...n.length > 0 ? [`unsupported field${n.length === 1 ? "" : "s"}: ${n.join(", ")}`] : [], ...r.length > 0 ? [`invalid value for: ${r.join(", ")}`] : []].join("; ");
218
- }, zt = (e) => D.try({
219
- try: () => k.decodeUnknownSync(It, { onExcessProperty: "error" })(e === void 0 ? {} : e),
220
- catch: () => `invalid text params (${Rt(e)}): expected maxTokens (positive safe integer), temperature (finite nonnegative number), and/or providerOptions (provider-keyed JSON object); other fields are not supported`
221
- }), B = k.String.pipe(k.check(k.makeFilter((e) => {
222
- try {
223
- let t = new URL(e);
224
- return (t.protocol === "https:" || t.protocol === "http:") && t.username === "" && t.password === "";
225
- } catch {
226
- return !1;
227
- }
228
- }))), Bt = k.Record(k.String, B), Vt = (e, t, n = {}) => D.try({
229
- try: () => {
230
- let r = k.decodeUnknownSync(_, { onExcessProperty: "error" })(e === void 0 ? {} : e), i = Object.fromEntries(Object.entries(r).map(([e, r]) => [e, r.from === "upload" ? r.url : r.artifact === void 0 ? Object.hasOwn(t, r.ref) ? t[r.ref] : void 0 : Object.hasOwn(n, r.ref) ? n[r.ref]?.[r.artifact]?.url : void 0]));
231
- return k.decodeUnknownSync(Bt)(i);
232
- },
233
- catch: () => "invalid or unresolved media input: each slot must resolve to an absolute HTTP(S) URL without embedded credentials"
234
- }), Ht = k.Struct({
235
- url: B,
236
- mediaType: k.NonEmptyString
237
- });
238
- k.Record(k.String, Ht);
239
- var Ut = (e, t = {}) => {
240
- let n = k.decodeUnknownOption(_)(e === void 0 ? {} : e);
241
- if (n._tag === "None") return {};
242
- let r = {};
243
- for (let [e, i] of Object.entries(n.value)) {
244
- if (i.from === "upload") {
245
- i.mediaType !== void 0 && k.is(B)(i.url) && (r[e] = {
246
- url: i.url,
247
- mediaType: i.mediaType
248
- });
249
- continue;
250
- }
251
- if (i.artifact === void 0 || !Object.hasOwn(t, i.ref)) continue;
252
- let n = t[i.ref]?.[i.artifact];
253
- n !== void 0 && k.is(B)(n.url) && (r[e] = {
254
- url: n.url,
255
- mediaType: n.mediaType
256
- });
257
- }
258
- return r;
259
- }, Wt = (e, t) => D.try({
260
- try: () => {
261
- let n = k.decodeUnknownSync(Bt)(t === void 0 ? {} : t), r = e === "image" ? ["referenceImageUrl", "maskImageUrl"] : e === "video" ? [
262
- "referenceImageUrl",
263
- "firstFrameImageUrl",
264
- "lastFrameImageUrl",
265
- "referenceVideoUrl"
266
- ] : [];
267
- if (Object.keys(n).some((e) => !r.includes(e))) throw Error("unsupported slot");
268
- if (e === "image" && n.maskImageUrl !== void 0 && n.referenceImageUrl === void 0) throw Error("mask requires reference");
269
- return n;
270
- },
271
- catch: () => `invalid or unsupported media input for ${e}; check the built-in adapter's slot contract`
272
- }), Gt = k.Struct({
273
- artifacts: y,
274
- costMicroUsd: k.optional(k.Finite.pipe(k.check(k.isGreaterThanOrEqualTo(0)))),
275
- costSource: k.optional(S),
276
- requestId: k.optional(k.NonEmptyString),
277
- usage: k.optional(m)
278
- }), Kt = (e) => D.try({
279
- try: () => k.decodeUnknownSync(Gt, { onExcessProperty: "error" })(e),
280
- catch: () => "invalid media result: expected artifacts with URL, mediaType and role, exactly one primary artifact, and optional storage references"
281
- }), V = (e) => e, qt = (e) => e._tag === "FlowAgentUnavailable" ? e.publicMessage ?? "agent unavailable" : "agent not found", Jt = k.Struct({
282
- value: k.optional(k.Unknown),
283
- text: k.optional(k.String),
284
- url: k.optional(k.String),
285
- artifacts: k.optional(y),
286
- costMicroUsd: k.optional(k.Number),
287
- costSource: k.optional(S),
288
- requestId: k.optional(k.String),
289
- usage: k.optional(m),
290
- error: k.optional(k.String)
291
- }), Yt = (e) => Kt(e).pipe(D.map((e) => {
292
- let t = e.artifacts.find((e) => e.role === "primary");
293
- return {
294
- value: t.url,
295
- url: t.url,
296
- artifacts: e.artifacts,
297
- ...e.requestId === void 0 ? {} : { requestId: e.requestId },
298
- ...e.costMicroUsd === void 0 ? {} : { costMicroUsd: e.costMicroUsd },
299
- ...e.costSource === void 0 ? {} : { costSource: e.costSource },
300
- ...e.usage === void 0 ? {} : { usage: e.usage }
301
- };
302
- }), D.catch((e) => D.succeed({ error: e }))), H = (e) => ({
303
- ...e.requestId ? { requestId: e.requestId } : {},
304
- ...e.costMicroUsd ? { costMicroUsd: e.costMicroUsd } : {},
305
- ...e.costSource === void 0 ? {} : { costSource: e.costSource },
306
- ...e.usage === void 0 ? {} : { usage: e.usage }
307
- }), U = () => (/* @__PURE__ */ new Date()).toISOString(), Xt = (e) => Math.round(e * 1e6), Zt = (e) => ({
308
- name: "gateway",
309
- model: e
310
- }), W = (e, t) => e.resolveModel?.(t) ?? Zt(t), Qt = (e, t, n, r) => D.gen(function* () {
311
- return t.maxSteps !== void 0 && (!Number.isSafeInteger(t.maxSteps) || t.maxSteps < 1) ? yield* D.fail(new w({
312
- capability: "resolveAgent",
313
- message: "agent maxSteps must be a positive safe integer"
314
- })) : yield* nt({
315
- ...r,
316
- system: t.system,
317
- prompt: n,
318
- provider: W(e, t.model),
319
- ...t.tools === void 0 ? {} : { tools: t.tools },
320
- ...t.maxSteps === void 0 ? {} : { maxSteps: t.maxSteps }
321
- });
322
- }), $t = (e, t, n) => G(e, t, n).costMicroUsd, G = (e, t, n) => {
323
- let r = Xe(t);
324
- if (typeof r == "number") return {
325
- costMicroUsd: Xt(r),
326
- costSource: "gateway"
327
- };
328
- let i = Ye(e, { model: n ?? "unknown" });
329
- return {
330
- costMicroUsd: i.costMicroUsd ?? 0,
331
- costSource: i.costSource ?? "unpriced"
332
- };
333
- }, K = (e) => {
334
- let t = e.filter((e) => (e.status === "succeeded" || e.status === "failed") && (e.costSource !== void 0 || e.costMicroUsd !== void 0));
335
- if (t.length === 0) return "unknown";
336
- let n = t.map((e) => e.costSource ?? "unpriced");
337
- return n.every((e) => e === "gateway") ? "actual" : n.some((e) => e === "unpriced") ? "incomplete" : "estimated";
338
- }, q = (e, t, n) => D.promise(() => e.store.update(R.tableName, t, n).then(() => void 0)).pipe(D.catchCause(() => D.void)), en = (e, t, n, r) => D.promise(async () => {
339
- let i = await e.store.query(N(R).where(A("id", t)).descriptor), a = i[0]?.[r];
340
- i[0] !== void 0 && a == null && await e.store.update(R.tableName, t, n);
341
- }).pipe(D.catchCause(() => D.void)), tn = (e, t) => D.promise(async () => {
342
- let n = (await e.store.query(N(R).where(A("id", t)).descriptor))[0]?.status;
343
- return n === "cancelling" || n === "cancelled";
344
- }).pipe(D.catchCause(() => D.succeed(!1))), nn = (e, t) => D.promise(() => e.store.updateMany(R.tableName, {
345
- status: "cancelled",
346
- completedAt: U()
347
- }, { where: Fe(A("id", t), A("status", "cancelling")) }).then(() => void 0)).pipe(D.catchCause(() => D.void)), rn = (e, t) => D.gen(function* () {
348
- let n = st(t);
349
- if (n) return n;
350
- let r = (yield* D.promise(() => e.store.query(N(L).where(A("id", t)).descriptor)))[0];
351
- return r ? d({
352
- name: r.name ?? t,
353
- mode: r.mode,
354
- steps: r.steps ?? [],
355
- maxSteps: r.maxSteps ?? null,
356
- brief: r.inputSchema ?? [],
357
- orchestratorModel: r.orchestratorModel ?? null,
358
- orchestratorInstructions: r.orchestratorInstructions ?? null,
359
- chain: r.chainTo ?? null,
360
- cadence: r.cadence ?? null,
361
- humanTimeoutMs: r.humanTimeoutMs ?? null
362
- }) : yield* D.fail(new Te({
363
- flowRef: t,
364
- message: `no flow registered or stored for "${t}"`
365
- }));
366
- }), an = (e, t, n, r, i, a) => D.gen(function* () {
367
- let e = jt(n.prompt ?? "", r), o = yield* zt(n.type === "agent" || n.type === "structured" || n.type === "generate" && (n.modality ?? "text") === "text" ? n.params : void 0).pipe(D.result);
368
- if (O.isFailure(o)) return { error: `step "${n.id}": ${o.failure}` };
369
- if (n.mediaInputs !== void 0 && (n.type !== "generate" || (n.modality ?? "text") === "text")) return { error: `step "${n.id}": media inputs require an image, video or audio generation step` };
370
- let s = Mt(n.prompt ?? "", r);
371
- if (s.length > 0) return { error: new Ce({
372
- stepId: n.id,
373
- unresolvedRef: s[0],
374
- message: `step "${n.id}" references unresolved {{${s[0]}}}`
375
- }).message };
376
- switch (n.type) {
377
- case "note": return {
378
- value: e,
379
- text: e,
380
- costMicroUsd: 0,
381
- costSource: "gateway"
382
- };
383
- case "agent": {
384
- if (!n.agentRef) return { error: "agent step missing agentRef" };
385
- if (!t.resolveAgent) return { error: new w({
386
- capability: "resolveAgent",
387
- message: "no agent resolver configured"
388
- }).message };
389
- let r = yield* V(t.resolveAgent(n.agentRef, i)).pipe(D.map((e) => ({
390
- ok: !0,
391
- a: e
392
- })), D.catch((e) => D.succeed({
393
- ok: !1,
394
- e
395
- })));
396
- if (!r.ok) return { error: r.e.message };
397
- let a = yield* Qt(t, r.a, e, o.success).pipe(D.map((e) => ({
398
- ok: !0,
399
- r: e
400
- })), D.catch((e) => D.succeed({
401
- ok: !1,
402
- e
403
- })));
404
- return a.ok ? {
405
- value: a.r.text,
406
- text: a.r.text,
407
- ...G(a.r.usage, a.r.providerMetadata, r.a.model)
408
- } : { error: String(a.e.message ?? a.e) };
409
- }
410
- case "structured": {
411
- if (n.schema === void 0) return { error: `step "${n.id}": structured step requires a JSON Schema` };
412
- let r = n.model ?? t.defaultModels?.text, i = yield* $e({
413
- ...o.success,
414
- prompt: e,
415
- jsonSchema: n.schema,
416
- ...r ? { provider: W(t, r) } : {}
417
- }).pipe(D.map((e) => ({
418
- ok: !0,
419
- r: e
420
- })), D.catch((e) => D.succeed({
421
- ok: !1,
422
- e
423
- })));
424
- return i.ok ? {
425
- value: i.r.object,
426
- text: JSON.stringify(i.r.object, null, 2),
427
- ...G(i.r.usage, i.r.providerMetadata, r)
428
- } : { error: String(i.e.message ?? i.e) };
429
- }
430
- case "generate": {
431
- let s = n.modality ?? "text";
432
- if (s === "text") {
433
- let r = n.model ?? t.defaultModels?.text, i = yield* nt({
434
- ...o.success,
435
- prompt: e,
436
- ...r ? { provider: W(t, r) } : {}
437
- }).pipe(D.map((e) => ({
438
- ok: !0,
439
- r: e
440
- })), D.catch((e) => D.succeed({
441
- ok: !1,
442
- e
443
- })));
444
- return i.ok ? {
445
- value: i.r.text,
446
- text: i.r.text,
447
- ...G(i.r.usage, i.r.providerMetadata, r)
448
- } : { error: String(i.e.message ?? i.e) };
449
- }
450
- if (!t.generateMedia) return { error: new w({
451
- capability: `media:${s}`,
452
- message: `no media generator configured for ${s}`
453
- }).message };
454
- let c = yield* Vt(n.mediaInputs, r, a).pipe(D.result);
455
- if (O.isFailure(c)) return { error: `step "${n.id}": ${c.failure}` };
456
- let l = Ut(n.mediaInputs, a), u = n.model ?? t.defaultModels?.[s], d = yield* V(t.generateMedia({
457
- modality: s,
458
- ...u ? { model: u } : {},
459
- prompt: e,
460
- ...n.params ? { params: n.params } : {},
461
- ...n.mediaInputs === void 0 ? {} : { inputs: c.success },
462
- ...Object.keys(l).length > 0 ? { inputRefs: l } : {},
463
- run: i
464
- })).pipe(D.map((e) => ({
465
- ok: !0,
466
- m: e
467
- })), D.catch((e) => D.succeed({
468
- ok: !1,
469
- e
470
- })));
471
- if (!d.ok) {
472
- let e = d.e.receipt;
473
- return {
474
- error: d.e.message,
475
- ...e === void 0 ? {} : e
476
- };
477
- }
478
- return yield* Yt(d.m);
479
- }
480
- case "human": return { error: new w({
481
- capability: "human",
482
- message: "human step reached the step interpreter — it should have been parked by the deterministic executor (routing bug)"
483
- }).message };
484
- default: return { error: `unknown step type: ${String(n.type)}` };
485
- }
486
- }), on = (e, t, n, i, o, s) => D.gen(function* () {
487
- let c = Object.assign(Object.create(null), o), l = Object.create(null), u = i.steps.map((e, t) => ({
488
- id: t,
489
- title: e.title ?? `Step ${t + 1}`,
490
- type: e.type,
491
- status: "pending",
492
- ...e.description ? { description: e.description } : {}
493
- })), d = 0;
494
- yield* en(e, n, {
495
- status: "running",
496
- steps: u,
497
- totalSteps: i.steps.length,
498
- currentStep: 0,
499
- startedAt: U()
500
- }, "startedAt");
501
- for (let o of Nt(i.steps)) {
502
- if (yield* tn(e, n)) return yield* nn(e, n), {
503
- runId: n,
504
- status: "cancelled"
505
- };
506
- if (o.steps.length > 1) {
507
- let r = [];
508
- for (let { index: e, step: t } of o.steps) {
509
- if (t.when !== void 0 && !v(t.when, c)) {
510
- u[e] = {
511
- ...u[e],
512
- status: "skipped",
513
- completedAt: U(),
514
- skipReason: a(t.when)
515
- };
516
- continue;
517
- }
518
- r.push({
519
- index: e,
520
- step: t
521
- }), u[e] = {
522
- ...u[e],
523
- status: "running",
524
- startedAt: U()
525
- };
526
- }
527
- yield* q(e, n, {
528
- steps: u,
529
- currentStep: o.steps[0].index
530
- });
531
- let i = yield* D.all(r.map(({ index: r, step: i }) => F({
532
- name: `flow-${r}-${i.id}`,
533
- input: { index: r },
534
- success: Jt,
535
- execute: an(e, t, i, c, {
536
- runId: n,
537
- tenantId: s.tenantId,
538
- ownerId: s.ownerId
539
- }, l)
540
- }).pipe(D.map((e) => ({
541
- index: r,
542
- step: i,
543
- result: e
544
- })))), { concurrency: "unbounded" }), f = i.find((e) => e.result.error);
545
- for (let { index: e, step: t, result: n } of i) {
546
- if (n.error) {
547
- d += n.costMicroUsd ?? 0, u[e] = {
548
- ...u[e],
549
- status: "failed",
550
- completedAt: U(),
551
- errorMessage: n.error,
552
- ...H(n)
553
- };
554
- continue;
555
- }
556
- t.outputKey && n.value !== void 0 && (c[t.outputKey] = n.value), t.outputKey && n.artifacts !== void 0 && (l[t.outputKey] = n.artifacts), d += n.costMicroUsd ?? 0, u[e] = {
557
- ...u[e],
558
- status: "succeeded",
559
- completedAt: U(),
560
- ...n.text ? { output: { text: n.text } } : {},
561
- ...n.url ? { url: n.url } : {},
562
- ...n.artifacts === void 0 ? {} : { artifacts: n.artifacts },
563
- ...H(n)
564
- };
565
- }
566
- if (f !== void 0) return yield* q(e, n, {
567
- steps: u,
568
- status: "failed",
569
- errorMessage: f.result.error,
570
- completedAt: U(),
571
- costMicroUsd: d,
572
- costCompleteness: K(u)
573
- }), {
574
- runId: n,
575
- status: "failed"
576
- };
577
- yield* q(e, n, {
578
- steps: u,
579
- currentStep: o.steps[o.steps.length - 1].index + 1,
580
- costMicroUsd: d,
581
- costCompleteness: K(u)
582
- });
583
- continue;
584
- }
585
- let { index: f, step: p } = o.steps[0];
586
- if (p.when !== void 0 && !v(p.when, c)) {
587
- u[f] = {
588
- ...u[f],
589
- status: "skipped",
590
- completedAt: U(),
591
- skipReason: a(p.when)
592
- }, yield* q(e, n, {
593
- steps: u,
594
- currentStep: f + 1
595
- });
596
- continue;
597
- }
598
- if (p.type === "human") {
599
- let a = {
600
- mode: p.reviewMode ?? "approve",
601
- ...p.options ? { options: p.options } : {},
602
- prompt: jt(p.prompt ?? "", c)
603
- };
604
- u[f] = {
605
- ...u[f],
606
- status: "waiting",
607
- startedAt: U(),
608
- review: a
609
- }, yield* q(e, n, {
610
- steps: u,
611
- status: "waiting",
612
- currentStep: f
613
- }), t.onEvent && (yield* V(t.onEvent({
614
- kind: "review-needed",
615
- runId: n,
616
- flowName: i.name,
617
- ownerId: s.ownerId,
618
- source: s.source
619
- })).pipe(D.catchCause(() => D.void)));
620
- let o = Dt({
621
- step: p,
622
- flow: i,
623
- deps: t
624
- }), l = yield* qe(e, {
625
- name: r(f),
626
- schema: ue,
627
- timeoutMs: o
628
- }).pipe(D.map((e) => ({
629
- ok: !0,
630
- a: e
631
- })), D.catchCause((e) => E.hasInterruptsOnly(e) ? D.failCause(e) : D.succeed({
632
- ok: !1,
633
- cause: e
634
- })));
635
- if (!l.ok) {
636
- let t = Number.isFinite(o) ? `human review timed out after ${o}ms` : "human review failed";
637
- return u[f] = {
638
- ...u[f],
639
- status: "failed",
640
- completedAt: U(),
641
- errorMessage: t
642
- }, yield* q(e, n, {
643
- steps: u,
644
- status: "failed",
645
- errorMessage: t,
646
- completedAt: U(),
647
- costMicroUsd: d,
648
- costCompleteness: K(u)
649
- }), {
650
- runId: n,
651
- status: "failed"
652
- };
653
- }
654
- let m = l.a;
655
- if (m.decision === "reject") return u[f] = {
656
- ...u[f],
657
- status: "failed",
658
- completedAt: U(),
659
- errorMessage: "rejected by reviewer"
660
- }, yield* q(e, n, {
661
- steps: u,
662
- status: "cancelled",
663
- humanResponse: m,
664
- completedAt: U(),
665
- costMicroUsd: d,
666
- costCompleteness: K(u)
667
- }), {
668
- runId: n,
669
- status: "cancelled"
670
- };
671
- p.outputKey && (c[p.outputKey] = m.value ?? m.text ?? m.decision ?? !0), u[f] = {
672
- ...u[f],
673
- status: "succeeded",
674
- completedAt: U(),
675
- output: { text: String(m.text ?? m.value ?? m.decision ?? "approved") }
676
- }, yield* q(e, n, {
677
- steps: u,
678
- status: "running",
679
- humanResponse: m,
680
- currentStep: f + 1
681
- });
682
- continue;
683
- }
684
- u[f] = {
685
- ...u[f],
686
- status: "running",
687
- startedAt: U()
688
- }, yield* q(e, n, {
689
- steps: u,
690
- currentStep: f
691
- });
692
- let m = yield* F({
693
- name: `flow-${f}-${p.id}`,
694
- input: { index: f },
695
- success: Jt,
696
- execute: an(e, t, p, c, {
697
- runId: n,
698
- tenantId: s.tenantId,
699
- ownerId: s.ownerId
700
- }, l)
701
- });
702
- if (m.error) return d += m.costMicroUsd ?? 0, u[f] = {
703
- ...u[f],
704
- status: "failed",
705
- completedAt: U(),
706
- errorMessage: m.error,
707
- ...H(m)
708
- }, yield* q(e, n, {
709
- steps: u,
710
- status: "failed",
711
- errorMessage: m.error,
712
- completedAt: U(),
713
- costMicroUsd: d,
714
- costCompleteness: K(u)
715
- }), {
716
- runId: n,
717
- status: "failed"
718
- };
719
- p.outputKey && m.value !== void 0 && (c[p.outputKey] = m.value), p.outputKey && m.artifacts !== void 0 && (l[p.outputKey] = m.artifacts), d += m.costMicroUsd ?? 0, u[f] = {
720
- ...u[f],
721
- status: "succeeded",
722
- completedAt: U(),
723
- ...m.text ? { output: { text: m.text } } : {},
724
- ...m.url ? { url: m.url } : {},
725
- ...m.artifacts === void 0 ? {} : { artifacts: m.artifacts },
726
- ...H(m)
727
- }, yield* q(e, n, {
728
- steps: u,
729
- currentStep: f + 1,
730
- costMicroUsd: d,
731
- costCompleteness: K(u)
732
- });
733
- }
734
- let f = Object.create(null);
735
- for (let e of i.steps) e.outputKey && c[e.outputKey] !== void 0 && (f[e.outputKey] = c[e.outputKey]);
736
- return yield* q(e, n, {
737
- status: "succeeded",
738
- output: f,
739
- completedAt: U(),
740
- costMicroUsd: d
741
- }), {
742
- runId: n,
743
- status: "succeeded",
744
- output: f
745
- };
746
- }), sn = (e, t, n, r, i, a, o) => D.gen(function* () {
747
- let s = n.chain;
748
- if (!s) return;
749
- let c = [...a.chainPath ?? [], a.flowRef];
750
- if (s.flowRef === n.name || s.flowRef === a.flowRef) return;
751
- if (c.includes(s.flowRef)) {
752
- yield* q(e, t, { chainRefusal: `chain to "${s.flowRef}" refused — it is already in this run's chain (${c.join(" → ")}), which would loop` });
753
- return;
754
- }
755
- let l = Ot(o);
756
- if (c.length >= l) {
757
- yield* q(e, t, { chainRefusal: `chain to "${s.flowRef}" refused — depth ${c.length} reached the limit of ${l} (${c.join(" → ")})` });
758
- return;
759
- }
760
- let u = {
761
- ...r,
762
- ...i
763
- }, d = {};
764
- for (let e of s.mappings) e.sourceKey in u && (d[e.targetKey] = u[e.sourceKey]);
765
- if (s.requireConfirmation) {
766
- yield* q(e, t, { chainPending: {
767
- flowRef: s.flowRef,
768
- input: d,
769
- status: "pending"
770
- } });
771
- return;
772
- }
773
- let f = e.workflows;
774
- if (!f) return;
775
- let p = `${t}--chain`, m = `${a.requestId}--chain`;
776
- yield* D.promise(async () => {
777
- try {
778
- await e.store.insert(R.tableName, {
779
- id: p,
780
- flowRef: s.flowRef,
781
- flowName: s.flowRef,
782
- status: "pending",
783
- source: a.source,
784
- requestId: m,
785
- input: d
786
- });
787
- } catch {}
788
- await f.child("flow.run", {
789
- runId: p,
790
- flowRef: s.flowRef,
791
- input: d,
792
- source: a.source,
793
- requestId: m,
794
- chainPath: c
795
- });
796
- }).pipe(D.catchCause(() => D.void));
797
- }), cn = (e) => e.type === "agent" ? e.agentRef ? `agent step, agent "${e.agentRef}"` : "agent step" : e.type === "generate" ? `${e.modality ?? "media"} generation step` : `${e.type} step`, ln = (e) => e.steps.length === 0 ? "" : "Suggested plan (you MAY reorder, insert, or skip steps):\n" + e.steps.map((e, t) => `${t + 1}. ${e.title ?? e.id}${e.prompt ? `: ${e.prompt}` : ""} (${cn(e)})`).join("\n"), un = "an agentic flow runs its planner and every tool inside one durable step, which cannot park. Call the provider directly from the tool (generateImage, generateVideo, …), or give the work its own deterministic flow step", dn = k.optional(k.String.annotate({ description: "One short sentence: what this call is for. Shown to the user in the run timeline." })), fn = (e) => e === void 0 || e.trim() === "" ? {} : { description: e.trim().slice(0, 200) }, pn = k.Struct({ json: k.String.annotate({ description: "The requested JSON object, serialized as a JSON string." }) }), mn = (e) => {
798
- try {
799
- let t = JSON.parse(e);
800
- return typeof t == "object" && t && !Array.isArray(t) ? t : void 0;
801
- } catch {
802
- return;
803
- }
804
- }, hn = (e) => {
805
- if (Ae.isSuccess(e)) return "the tool returned without recording a result";
806
- if (E.hasInterruptsOnly(e.cause)) return "interrupted before it finished — nothing waited for its result";
807
- let t = E.squash(e.cause);
808
- return t instanceof Error ? t.message : String(t);
809
- }, gn = (e) => {
810
- let t = Object.entries(e);
811
- return t.length === 0 ? "Execute the flow." : "Brief for this run:\n" + t.map(([e, t]) => `- ${e}: ${typeof t == "string" ? t : JSON.stringify(t)}`).join("\n");
812
- }, _n = (e) => [
813
- e.orchestrator?.instructions ?? "You are an orchestrator that uses the available tools to produce a bundled result.",
814
- ln(e),
815
- "When finished, emit a JSON object mapping each deliverable name (outputKey) to its value, serialized as a string in the json field."
816
- ].filter(Boolean).join("\n\n"), vn = k.Struct({
817
- object: k.Record(k.String, k.Unknown),
818
- planCostMicroUsd: k.Number,
819
- planCostSource: k.optional(S),
820
- toolCostMicroUsd: k.Number,
821
- steps: k.Array(i),
822
- error: k.optional(k.String)
823
- }), yn = (e, t, n, r, i, a, o, s) => D.gen(function* () {
824
- yield* en(e, n, {
825
- status: "running",
826
- startedAt: U(),
827
- totalSteps: r.steps.length
828
- }, "startedAt");
829
- let c = yield* F({
830
- name: "flow-agentic",
831
- input: { flowRef: r.name },
832
- success: vn,
833
- execute: D.gen(function* () {
834
- let c = [], l = 0, u = (e) => {
835
- let t = c.length;
836
- return c.push({
837
- id: t,
838
- status: "running",
839
- startedAt: U(),
840
- ...e
841
- }), t;
842
- }, d = (e, t) => {
843
- c[e] = {
844
- ...c[e],
845
- completedAt: U(),
846
- ...t
847
- };
848
- }, f = () => q(e, n, {
849
- steps: c,
850
- currentStep: c.length,
851
- costMicroUsd: l
852
- }), p = (e, t) => D.suspend(() => {
853
- let n = u(e);
854
- return D.andThen(f(), t(n)).pipe(D.onExit((e) => c[n]?.status === "running" ? (d(n, {
855
- status: "failed",
856
- errorMessage: hn(e)
857
- }), D.ignore(f())) : D.void));
858
- }), m = yield* (t.listAgents ? V(t.listAgents({
859
- runId: n,
860
- tenantId: o,
861
- ownerId: a
862
- })) : D.succeed(void 0)).pipe(D.result);
863
- if (O.isFailure(m)) return yield* D.logWarning(`flow agent listing failed for run ${n}: ${m.failure.message}`).pipe(D.annotateLogs({ scope: "voltro:ai-flows" })), {
864
- object: {},
865
- planCostMicroUsd: 0,
866
- toolCostMicroUsd: 0,
867
- steps: c,
868
- error: "flow agent listing failed"
869
- };
870
- let h = m.success, g = h ?? [...new Set(r.steps.flatMap((e) => e.type === "agent" && e.agentRef ? [e.agentRef] : []))].map((e) => ({ ref: e })), ee = g.map((e) => e.ref), _ = ee.length > 0 ? k.Literals(ee) : k.String, te = Je({
871
- name: "run_agent",
872
- description: "Delegate a text task to an allowed sub-agent. Returns the agent's text." + (g.length > 0 ? ` Agents you may call: ${g.map((e) => e.description ? `${e.ref} (${e.description})` : e.ref).join("; ")}.` : ""),
873
- input: k.Struct({
874
- agentRef: _,
875
- prompt: k.String,
876
- purpose: dn
877
- }),
878
- execute: ({ agentRef: e, prompt: r, purpose: i }) => p({
879
- title: `agent:${e}`,
880
- type: "agent",
881
- agentRef: e,
882
- ...fn(i)
883
- }, (i) => D.gen(function* () {
884
- if (!t.resolveAgent) return d(i, {
885
- status: "failed",
886
- errorMessage: "no agent resolver configured"
887
- }), yield* f(), "ERROR: no agent resolver configured";
888
- let s = yield* V(t.resolveAgent(e, {
889
- runId: n,
890
- tenantId: o,
891
- ownerId: a
892
- })).pipe(D.map((e) => ({
893
- ok: !0,
894
- a: e
895
- })), D.catch((e) => D.succeed({
896
- ok: !1,
897
- e
898
- })));
899
- if (!s.ok) return d(i, {
900
- status: "failed",
901
- errorMessage: s.e.message
902
- }), yield* f(), `ERROR: ${qt(s.e)}`;
903
- let c = yield* Qt(t, s.a, r, {}).pipe(D.map((e) => ({
904
- ok: !0,
905
- r: e
906
- })), D.catch((e) => D.succeed({
907
- ok: !1,
908
- e
909
- })));
910
- if (!c.ok) {
911
- let e = String(c.e.message ?? c.e);
912
- return d(i, {
913
- status: "failed",
914
- errorMessage: e
915
- }), yield* f(), `ERROR: ${e}`;
916
- }
917
- let u = $t(c.r.usage, c.r.providerMetadata, s.a.model);
918
- return l += u, d(i, {
919
- status: "succeeded",
920
- output: { text: c.r.text },
921
- costMicroUsd: u
922
- }), yield* f(), c.r.text;
923
- }))
924
- }), v = Je({
925
- name: "generate_media",
926
- description: "Generate image, video, or audio artifacts. Returns every artifact with its URL, role, media type and optional storage reference.",
927
- input: k.Struct({
928
- modality: k.Literals([
929
- "image",
930
- "video",
931
- "audio"
932
- ]),
933
- prompt: k.String,
934
- purpose: dn,
935
- model: k.optional(k.String),
936
- inputs: k.optional(Bt),
937
- params: k.optional(k.Record(k.String, k.Unknown))
938
- }),
939
- execute: ({ modality: e, prompt: r, purpose: i, model: s, inputs: c, params: u }) => p({
940
- title: `media:${e}`,
941
- type: "generate",
942
- modality: e,
943
- ...fn(i)
944
- }, (i) => D.gen(function* () {
945
- if (!t.generateMedia) return d(i, {
946
- status: "failed",
947
- errorMessage: `no media generator for ${e}`
948
- }), yield* f(), `ERROR: no media generator configured for ${e}`;
949
- let p = yield* V(t.generateMedia({
950
- modality: e,
951
- prompt: r,
952
- ...s ? { model: s } : {},
953
- ...c === void 0 ? {} : { inputs: c },
954
- ...u === void 0 ? {} : { params: u },
955
- run: {
956
- runId: n,
957
- tenantId: o,
958
- ownerId: a
959
- }
960
- })).pipe(D.map((e) => ({
961
- ok: !0,
962
- r: e
963
- })), D.catch((e) => D.succeed({
964
- ok: !1,
965
- e
966
- })));
967
- if (!p.ok) return d(i, {
968
- status: "failed",
969
- errorMessage: p.e.message
970
- }), yield* f(), `ERROR: ${p.e.message}`;
971
- let m = yield* Yt(p.r);
972
- return m.error ? (d(i, {
973
- status: "failed",
974
- errorMessage: m.error
975
- }), yield* f(), { error: m.error }) : (l += m.costMicroUsd ?? 0, d(i, {
976
- status: "succeeded",
977
- url: m.url,
978
- artifacts: m.artifacts,
979
- ...m.requestId ? { requestId: m.requestId } : {},
980
- costMicroUsd: m.costMicroUsd ?? 0,
981
- costSource: m.costSource ?? "unpriced"
982
- }), yield* f(), { artifacts: m.artifacts });
983
- }))
984
- }), ne = Je({
985
- name: "pick_structured",
986
- description: "Produce a JSON object for a task. Returns the object.",
987
- input: k.Struct({
988
- prompt: k.String,
989
- purpose: dn,
990
- model: k.optional(k.String)
991
- }),
992
- execute: ({ prompt: e, purpose: n, model: r }) => p({
993
- title: "structured",
994
- type: "structured",
995
- ...fn(n)
996
- }, (n) => D.gen(function* () {
997
- let i = yield* Qe({
998
- prompt: `${e}\n\nReturn the JSON object serialized as a string in the \`json\` field.`,
999
- schema: pn,
1000
- ...r ? { provider: W(t, r) } : {}
1001
- }).pipe(D.map((e) => ({
1002
- ok: !0,
1003
- r: e
1004
- })), D.catch((e) => D.succeed({
1005
- ok: !1,
1006
- e
1007
- })));
1008
- if (!i.ok) {
1009
- let e = String(i.e.message ?? i.e);
1010
- return d(n, {
1011
- status: "failed",
1012
- errorMessage: e
1013
- }), yield* f(), { error: e };
1014
- }
1015
- let a = $t(i.r.usage, i.r.providerMetadata, r);
1016
- l += a;
1017
- let o = mn(i.r.object.json);
1018
- if (o === void 0) {
1019
- let e = "the model's `json` field is not a JSON object";
1020
- return d(n, {
1021
- status: "failed",
1022
- errorMessage: e,
1023
- costMicroUsd: a
1024
- }), yield* f(), { error: e };
1025
- }
1026
- return d(n, {
1027
- status: "succeeded",
1028
- output: { text: JSON.stringify(o) },
1029
- costMicroUsd: a
1030
- }), yield* f(), o;
1031
- }))
1032
- }), re = {
1033
- run_agent: te,
1034
- generate_media: v,
1035
- pick_structured: ne
1036
- }, y = yield* (t.resolveTools ? V(t.resolveTools(s, {
1037
- runId: n,
1038
- tenantId: o,
1039
- ownerId: a
1040
- }, { provider: () => r.orchestrator?.model ? W(t, r.orchestrator.model) : void 0 })) : D.succeed({})).pipe(D.result);
1041
- if (O.isFailure(y)) return yield* D.logWarning(`flow tool resolution failed for run ${n}: ${y.failure.message}`).pipe(D.annotateLogs({ scope: "voltro:ai-flows" })), {
1042
- object: {},
1043
- planCostMicroUsd: 0,
1044
- toolCostMicroUsd: 0,
1045
- steps: c,
1046
- error: "flow tool resolution failed"
1047
- };
1048
- if (Object.keys(y.success).some((e) => Object.hasOwn(re, e))) return {
1049
- object: {},
1050
- planCostMicroUsd: 0,
1051
- toolCostMicroUsd: 0,
1052
- steps: c,
1053
- error: "flow tools cannot replace reserved planner tools"
1054
- };
1055
- let ie = t.memoryPrefix ? yield* V(t.memoryPrefix(a)).pipe(D.catch(() => D.succeed(""))) : "", b = ie ? `${ie}\n\n${_n(r)}` : _n(r), x = yield* et({
1056
- system: b,
1057
- prompt: gn(i),
1058
- schema: pn,
1059
- tools: {
1060
- ...y.success,
1061
- ...h?.length === 0 ? {
1062
- generate_media: v,
1063
- pick_structured: ne
1064
- } : re
1065
- },
1066
- maxSteps: r.maxSteps,
1067
- ...r.orchestrator?.model ? { provider: W(t, r.orchestrator.model) } : {}
1068
- }).pipe(D.provideService(Ke, un), D.map((e) => ({
1069
- ok: !0,
1070
- r: e
1071
- })), D.catch((e) => D.succeed({
1072
- ok: !1,
1073
- e
1074
- })));
1075
- for (let e of c) e.status === "running" && d(e.id, {
1076
- status: "failed",
1077
- errorMessage: "not finished — the run ended first"
1078
- });
1079
- if (!x.ok) return {
1080
- object: {},
1081
- planCostMicroUsd: 0,
1082
- toolCostMicroUsd: l,
1083
- steps: c,
1084
- error: String(x.e.message ?? x.e)
1085
- };
1086
- let ae = mn(x.r.object.json);
1087
- return {
1088
- object: ae ?? {},
1089
- ...ae === void 0 ? { error: "the planner's `json` field is not a JSON object" } : {},
1090
- planCostMicroUsd: $t(x.r.usage, x.r.providerMetadata, r.orchestrator?.model),
1091
- planCostSource: G(x.r.usage, x.r.providerMetadata, r.orchestrator?.model).costSource,
1092
- toolCostMicroUsd: l,
1093
- steps: c
1094
- };
1095
- })
1096
- }), l = c.planCostMicroUsd + c.toolCostMicroUsd, u = K([...c.steps, {
1097
- status: "succeeded",
1098
- costMicroUsd: c.planCostMicroUsd,
1099
- costSource: c.planCostSource ?? "unpriced"
1100
- }]);
1101
- return c.error ? (yield* q(e, n, {
1102
- status: "failed",
1103
- steps: c.steps,
1104
- errorMessage: c.error,
1105
- completedAt: U(),
1106
- costMicroUsd: l,
1107
- costCompleteness: u
1108
- }), {
1109
- runId: n,
1110
- status: "failed"
1111
- }) : (yield* q(e, n, {
1112
- status: "succeeded",
1113
- steps: c.steps,
1114
- output: c.object,
1115
- completedAt: U(),
1116
- costMicroUsd: l,
1117
- costCompleteness: u
1118
- }), {
1119
- runId: n,
1120
- status: "succeeded",
1121
- output: c.object
1122
- });
1123
- }), bn = (e, t = {}) => (n, r) => D.gen(function* () {
1124
- let { runId: r, flowRef: i, input: a } = n, o = yield* D.tryPromise(() => e.store.query(N(R).where(A("id", r)).descriptor)).pipe(D.flatMap(k.decodeUnknownEffect(k.Tuple([k.Struct({
1125
- id: k.Literal(r),
1126
- tenantId: k.NullOr(k.NonEmptyString),
1127
- ownerId: k.optional(k.NullOr(k.String))
1128
- })]))), D.result);
1129
- if (O.isFailure(o)) return yield* q(e, r, {
1130
- status: "failed",
1131
- errorMessage: "flow run context unavailable: expected one matching run row with an explicit tenantId (string or null)",
1132
- completedAt: U()
1133
- }), {
1134
- runId: r,
1135
- status: "failed"
1136
- };
1137
- let { tenantId: s, ownerId: c = null } = o.success[0], l = yield* F({
1138
- name: "flow-0-resolve",
1139
- input: { flowRef: i },
1140
- success: k.Struct({
1141
- ir: k.Unknown,
1142
- error: k.optional(k.String)
1143
- }),
1144
- execute: rn(e, i).pipe(D.flatMap((e) => {
1145
- for (let t of e.steps) {
1146
- if (!(t.type === "agent" || t.type === "structured" || t.type === "generate" && (t.modality ?? "text") === "text") || t.params === void 0) continue;
1147
- let e = D.runSyncExit(zt(t.params));
1148
- if (Ae.isFailure(e)) return D.succeed({
1149
- ir: null,
1150
- error: `step "${t.id}": ${E.squash(e.cause)}`
1151
- });
1152
- }
1153
- return D.succeed({ ir: JSON.parse(JSON.stringify(e)) });
1154
- }), D.catch((e) => D.succeed({
1155
- ir: null,
1156
- error: e.message
1157
- })))
1158
- });
1159
- if (l.error || !l.ir) return yield* q(e, r, {
1160
- status: "failed",
1161
- errorMessage: l.error ?? "flow not found",
1162
- completedAt: U()
1163
- }), {
1164
- runId: r,
1165
- status: "failed"
1166
- };
1167
- let u = l.ir, d = u.mode === "agentic" ? yield* yn(e, t, r, u, a, c, s, i) : yield* on(e, t, r, u, a, {
1168
- ownerId: c,
1169
- tenantId: s,
1170
- source: n.source
1171
- });
1172
- return d.status === "succeeded" && u.chain && (yield* sn(e, r, u, a, d.output ?? {}, n, t)), t.onEvent && (d.status === "succeeded" || d.status === "failed") && (yield* V(t.onEvent({
1173
- kind: d.status,
1174
- runId: r,
1175
- flowName: u.name,
1176
- ownerId: c,
1177
- source: n.source
1178
- })).pipe(D.catchCause(() => D.void))), d;
1179
- }), xn = {
1180
- text: (e) => ({
1181
- type: "generate",
1182
- modality: "text",
1183
- ...e
1184
- }),
1185
- media: (e, t) => ({
1186
- type: "generate",
1187
- modality: e,
1188
- ...t
1189
- }),
1190
- agent: (e) => ({
1191
- type: "agent",
1192
- ...e
1193
- }),
1194
- structured: (e) => ({
1195
- type: "structured",
1196
- ...e
1197
- }),
1198
- note: (e) => ({
1199
- type: "note",
1200
- ...e
1201
- }),
1202
- human: (e) => ({
1203
- type: "human",
1204
- ...e
1205
- })
1206
- }, Sn = (e) => e.map((e, t) => "id" in e && e.id ? e : {
1207
- id: `step-${t}`,
1208
- ...e
1209
- }), Cn = (e) => {
1210
- let t = [], n = Nt(e.steps);
1211
- for (let e of Pt(n)) t.push(`group "${e}" is not contiguous — only CONSECUTIVE steps sharing a group run concurrently, so this would execute as two separate fan-outs`);
1212
- let r = new Set(e.brief.map((e) => e.key));
1213
- for (let e of n) {
1214
- for (let { step: n } of e.steps) {
1215
- n.type === "human" && n.group !== void 0 && t.push(`step "${n.id}" is a human review inside group "${n.group}" — a review SUSPENDS the whole run, which one branch of a fan-out cannot do`);
1216
- for (let i of At(n.prompt ?? "")) r.has(i) || t.push(e.steps.length > 1 ? `step "${n.id}" references {{${i}}} which is produced inside its OWN group "${n.group}" or does not exist — grouped steps run concurrently, so they cannot read each other` : `step "${n.id}" references {{${i}}} which is not a brief field or a prior step outputKey`);
1217
- for (let [e, i] of Object.entries(n.mediaInputs ?? {})) i.from === "step" && !r.has(i.ref) && t.push(`step "${n.id}" media input "${e}" references "${i.ref}" which is not a brief field or an earlier segment's outputKey`);
1218
- n.when !== void 0 && !r.has(n.when.ref) && t.push(`step "${n.id}" has a when-condition on {{${n.when.ref}}} which is not a brief field or a prior step outputKey — it would never run`);
1219
- }
1220
- for (let { step: t } of e.steps) t.outputKey && r.add(f(t.outputKey));
1221
- }
1222
- if (t.length > 0) throw new De({
1223
- flowRef: e.name,
1224
- message: `flow "${e.name}" has ${t.length} problem(s)`,
1225
- issues: t
1226
- });
1227
- }, wn = (e) => {
1228
- let t = d({
1229
- name: e.name,
1230
- mode: e.mode,
1231
- steps: Sn(e.steps),
1232
- maxSteps: e.maxSteps,
1233
- brief: e.brief,
1234
- orchestratorModel: e.orchestrator?.model,
1235
- orchestratorInstructions: e.orchestrator?.instructions,
1236
- chain: e.chain,
1237
- cadence: e.cadence,
1238
- humanTimeoutMs: e.humanTimeoutMs
1239
- });
1240
- return Cn(t), ot(t), t;
1241
- }, Tn = async (e, t, n) => {
1242
- let r = k.decodeUnknownSync(Me.pipe(k.check(k.makeFilter((e) => e.workflowName === "flow.run" && e.id.length > 0))))(n);
1243
- if (await e.store.update(R.tableName, t, { workflowStart: r }) === null) throw Error("flow start receipt could not be recorded; workflow submission may have succeeded");
1244
- return r;
1245
- }, En = (e, t, n) => {
1246
- if (!Number.isFinite(t.getTime())) throw Error("cadence timestamp must be valid");
1247
- return `cron-${at("sha256").update(JSON.stringify([
1248
- n,
1249
- e,
1250
- Math.floor(t.getTime() / 6e4)
1251
- ])).digest("hex")}`;
1252
- }, Dn = async (e) => {
1253
- let t = [];
1254
- for (let n of ct()) n.cadence && (n.cadence.repeats?.length ?? 0) > 0 && t.push({
1255
- tenantId: e.request.subject.tenantId,
1256
- flowRef: n.name,
1257
- cadence: n.cadence,
1258
- defaultInput: n.cadence.defaultInput ?? {}
1259
- });
1260
- let n = await e.store.select("_voltro_ai_flows").where("isEnabled", !0).all();
1261
- for (let r of n) r.id && r.cadence && (r.cadence.repeats?.length ?? 0) > 0 && t.push({
1262
- tenantId: r.tenantId ?? e.request.subject.tenantId,
1263
- flowRef: r.id,
1264
- cadence: r.cadence,
1265
- defaultInput: r.cadence.defaultInput ?? {}
1266
- });
1267
- return t;
1268
- }, On = async (e, t = /* @__PURE__ */ new Date()) => {
1269
- let r = [], i = 0, a = [], o = e.workflows ? await mt(e) : {
1270
- examined: 0,
1271
- accepted: 0,
1272
- notExecuted: 0,
1273
- pending: 0,
1274
- failures: []
1275
- };
1276
- a.push(...o.failures.map((e) => Error(`flow run ${e.runId}: start reconciliation failed`, { cause: e.cause })));
1277
- let s = await Dn(e);
1278
- for (let o of s) {
1279
- if (!ke(o.cadence, t)) continue;
1280
- i += 1;
1281
- let s = En(o.flowRef, t, o.tenantId), c = `run-${s}`;
1282
- try {
1283
- if (!e.workflows) throw Error("workflow runtime unavailable; no cadence start was submitted");
1284
- (await e.transaction(async (e) => {
1285
- let t = e.workflows;
1286
- if (!t) throw Error("workflow runtime unavailable in transaction; no cadence start was submitted");
1287
- await e.store.insertIgnoreWithOutcome("_voltro_ai_flow_runs", {
1288
- id: c,
1289
- flowRef: o.flowRef,
1290
- flowName: o.flowRef,
1291
- status: "pending",
1292
- source: "cron",
1293
- requestId: s,
1294
- input: o.defaultInput
1295
- }, { conflictColumns: ["id"] });
1296
- let r = await e.store.select("_voltro_ai_flow_runs").where("id", c).first();
1297
- if (!r) throw Error("cadence run is not readable after persistence");
1298
- let i = k.decodeUnknownSync(n.payloadSchema.pipe(k.check(k.makeFilter((e) => e.runId === c && e.flowRef === o.flowRef && e.requestId === s && e.source === "cron"))))({
1299
- ...r,
1300
- runId: r.id
1301
- });
1302
- return Tn(e, c, await t.start("flow.run", i));
1303
- }, o.tenantId === null ? void 0 : { tenantId: o.tenantId })).status === "running" && r.push(s);
1304
- } catch (e) {
1305
- a.push(e);
1306
- }
1307
- }
1308
- if (a.length > 0) throw AggregateError(a, `${a.length} cadence submission(s) failed`);
1309
- return {
1310
- matched: i,
1311
- started: r,
1312
- reconciled: o
1313
- };
1314
- }, J = (e) => k.optionalKey(e), kn = k.Int.pipe(k.check(k.isGreaterThan(0)), k.check(k.isLessThanOrEqualTo(2 ** 53 - 1))), An = k.Int.pipe(k.check(k.isBetween({
1315
- minimum: -(2 ** 53 - 1),
1316
- maximum: 2 ** 53 - 1
1317
- }))), jn = k.TemplateLiteral([
1318
- k.Number,
1319
- "x",
1320
- k.Number
1321
- ]).pipe(k.check(k.isPattern(/^[1-9]\d*x[1-9]\d*$/))), Mn = k.TemplateLiteral([
1322
- k.Number,
1323
- ":",
1324
- k.Number
1325
- ]).pipe(k.check(k.isPattern(/^[1-9]\d*:[1-9]\d*$/))), Nn = k.Struct({
1326
- n: J(kn),
1327
- seed: J(An),
1328
- size: J(jn),
1329
- aspectRatio: J(Mn),
1330
- providerOptions: J(z)
1331
- }), Pn = k.Struct({
1332
- voice: J(k.NonEmptyString),
1333
- outputFormat: J(k.NonEmptyString),
1334
- instructions: J(k.String),
1335
- speed: J(k.Finite.pipe(k.check(k.isGreaterThan(0)))),
1336
- language: J(k.NonEmptyString),
1337
- providerOptions: J(z)
1338
- }), Fn = k.Struct({
1339
- aspectRatio: J(Mn),
1340
- durationSeconds: J(k.Finite.pipe(k.check(k.isGreaterThan(0)))),
1341
- resolution: J(jn),
1342
- fps: J(k.Finite.pipe(k.check(k.isGreaterThan(0)))),
1343
- seed: J(An),
1344
- generateAudio: J(k.Boolean),
1345
- maxInlineBytes: J(kn),
1346
- providerOptions: J(z)
1347
- }), Y = (e, t, n) => D.try({
1348
- try: () => k.decodeUnknownSync(e, { onExcessProperty: "error" })(t === void 0 ? {} : t),
1349
- catch: () => `invalid ${n} media params: check the built-in adapter's supported options and value ranges`
1350
- }), In = (e) => Y(Nn, e, "image"), Ln = (e) => Y(Pn, e, "audio"), Rn = (e) => Y(Fn, e, "video"), zn = (e) => ({
1351
- name: "gateway",
1352
- model: e
1353
- }), Bn = (e) => Math.round(e * 1e6), X = (e, t, n) => {
1354
- let r = Xe(t);
1355
- if (typeof r == "number") return {
1356
- costMicroUsd: Bn(r),
1357
- costSource: "gateway"
1358
- };
1359
- if (e) {
1360
- let t = Ye(e, { model: n ?? "unknown" });
1361
- return {
1362
- costMicroUsd: t.costMicroUsd ?? 0,
1363
- costSource: t.costSource ?? "unpriced"
1364
- };
1365
- }
1366
- return {
1367
- costMicroUsd: 0,
1368
- costSource: "unpriced"
1369
- };
1370
- }, Z = (e) => {
1371
- if (e === void 0) return { status: "unreported" };
1372
- let [t, n, r] = it(e) ? [
1373
- e.unit,
1374
- e.input,
1375
- e.output
1376
- ] : [
1377
- "tokens",
1378
- e.inputTokens,
1379
- e.outputTokens
1380
- ];
1381
- return n === void 0 && r === void 0 ? { status: "unreported" } : {
1382
- status: "reported",
1383
- unit: t,
1384
- ...n === void 0 ? {} : { input: n },
1385
- ...r === void 0 ? {} : { output: r }
1386
- };
1387
- }, Q = (e, t, n) => ({
1388
- ...X(e, t, n),
1389
- usage: Z(e)
1390
- }), Vn = (e, t) => (n) => {
1391
- let r = n.model, i = (e) => t?.resolveModel?.(e) ?? zn(e);
1392
- return D.gen(function* () {
1393
- let t = yield* Wt(n.modality, n.inputs).pipe(D.mapError((e) => new w({
1394
- capability: `media:${n.modality}`,
1395
- message: e
1396
- })));
1397
- if (n.modality === "image") {
1398
- let a = yield* In(n.params).pipe(D.mapError((e) => new w({
1399
- capability: "media:image",
1400
- message: e
1401
- }))), o = t.referenceImageUrl, s = t.maskImageUrl, c = yield* Ze({
1402
- ...a,
1403
- prompt: n.prompt,
1404
- ...o === void 0 ? {} : { inputs: {
1405
- images: [o],
1406
- ...s === void 0 ? {} : { mask: s }
1407
- } },
1408
- ...r ? { provider: i(r) } : {}
1409
- });
1410
- if (c.images.length === 0) return yield* D.fail(new w({
1411
- capability: "media:image",
1412
- message: "no image produced"
1413
- }));
1414
- let l = [];
1415
- for (let [t, i] of c.images.entries()) {
1416
- let a = yield* e.put({
1417
- data: i.data,
1418
- mediaType: i.mediaType,
1419
- run: n.run
1420
- }).pipe(D.mapError(() => new w({
1421
- capability: "media:image",
1422
- message: "media persistence failed",
1423
- receipt: Q(c.usage, c.providerMetadata, r)
1424
- })));
1425
- l.push({
1426
- url: a.url,
1427
- mediaType: i.mediaType,
1428
- role: t === 0 ? "primary" : "variant",
1429
- ...a.refId === void 0 ? {} : { storageRefId: a.refId },
1430
- ...i.providerMetadata === void 0 ? {} : { providerMetadata: i.providerMetadata }
1431
- });
1432
- }
1433
- return {
1434
- artifacts: l,
1435
- ...X(c.usage, c.providerMetadata, r),
1436
- usage: Z(c.usage)
1437
- };
1438
- }
1439
- if (n.modality === "audio") {
1440
- let t = yield* Ln(n.params).pipe(D.mapError((e) => new w({
1441
- capability: "media:audio",
1442
- message: e
1443
- }))), a = yield* tt({
1444
- ...t,
1445
- text: n.prompt,
1446
- ...r ? { provider: i(r) } : {}
1447
- }), o = yield* e.put({
1448
- data: a.audio.data,
1449
- mediaType: a.audio.mediaType,
1450
- run: n.run
1451
- }).pipe(D.mapError(() => new w({
1452
- capability: "media:audio",
1453
- message: "media persistence failed",
1454
- receipt: Q(a.usage, a.providerMetadata, r)
1455
- })));
1456
- return {
1457
- artifacts: [{
1458
- url: o.url,
1459
- mediaType: a.audio.mediaType,
1460
- role: "primary",
1461
- ...o.refId === void 0 ? {} : { storageRefId: o.refId }
1462
- }],
1463
- ...X(a.usage, a.providerMetadata, r),
1464
- usage: Z(a.usage)
1465
- };
1466
- }
1467
- let { maxInlineBytes: a, providerOptions: o, ...s } = yield* Rn(n.params).pipe(D.mapError((e) => new w({
1468
- capability: "media:video",
1469
- message: e
1470
- }))), c = yield* rt({
1471
- prompt: n.prompt,
1472
- inputs: {
1473
- ...t.referenceImageUrl === void 0 ? {} : { image: t.referenceImageUrl },
1474
- ...t.referenceVideoUrl === void 0 ? {} : { references: [t.referenceVideoUrl] },
1475
- frameImages: [...t.firstFrameImageUrl === void 0 ? [] : [{
1476
- frameType: "first_frame",
1477
- image: t.firstFrameImageUrl
1478
- }], ...t.lastFrameImageUrl === void 0 ? [] : [{
1479
- frameType: "last_frame",
1480
- image: t.lastFrameImageUrl
1481
- }]]
1482
- },
1483
- ...r ? { provider: i(r) } : {},
1484
- params: s,
1485
- ...o === void 0 ? {} : { providerOptions: o },
1486
- ...a === void 0 ? {} : { maxInlineBytes: a }
1487
- }), l;
1488
- if (c.video.url) l = e.ingestUrl ? yield* e.ingestUrl(c.video.url, n.run).pipe(D.mapError(() => new w({
1489
- capability: "media:video",
1490
- message: "media persistence failed",
1491
- receipt: Q(c.usage, c.providerMetadata, r)
1492
- }))) : { url: c.video.url };
1493
- else if (c.video.data) l = yield* e.put({
1494
- data: c.video.data,
1495
- mediaType: c.video.mediaType,
1496
- run: n.run
1497
- }).pipe(D.mapError(() => new w({
1498
- capability: "media:video",
1499
- message: "media persistence failed",
1500
- receipt: Q(c.usage, c.providerMetadata, r)
1501
- })));
1502
- else return yield* D.fail(new w({
1503
- capability: "media:video",
1504
- message: "no video produced"
1505
- }));
1506
- return {
1507
- artifacts: [{
1508
- url: l.url,
1509
- mediaType: c.video.mediaType,
1510
- role: "primary",
1511
- ...l.refId === void 0 ? {} : { storageRefId: l.refId }
1512
- }],
1513
- ...X(c.usage, c.providerMetadata, r),
1514
- usage: Z(c.usage)
1515
- };
1516
- }).pipe(D.catch((e) => e instanceof w ? D.fail(e) : D.fail(new w({
1517
- capability: `media:${n.modality}`,
1518
- message: String(e.message ?? e)
1519
- }))));
1520
- }, Hn = () => globalThis.crypto?.randomUUID?.() ?? `req-${Date.now().toString(36)}`, Un = (e) => e.request?.subject?.id ?? null, $ = (e, t) => D.promise(() => e.store.query(N(R).where(A("id", t)).descriptor)).pipe(D.map((e) => e[0])), Wn = (e) => D.sync(() => {
1521
- let t = e.workflows;
1522
- if (!t) throw Error("workflow runtime unavailable; no flow start was submitted");
1523
- return t;
1524
- }), Gn = (t, n) => D.gen(function* () {
1525
- yield* Wn(t);
1526
- let r = yield* rn(t, n.flowRef), i = n.input ?? {}, a = r.brief.filter((e) => e.required && e.type !== "boolean" && (i[e.key] === void 0 || i[e.key] === null || i[e.key] === "")).map((e) => e.key);
1527
- if (a.length > 0) return yield* D.fail(new Se({
1528
- missing: a,
1529
- message: `missing required brief field(s): ${a.join(", ")}`
1530
- }));
1531
- let o = Hn(), s = `run-${o}`, c = n.source ?? "manual";
1532
- return yield* D.promise(() => t.transaction(async (t) => {
1533
- let a = t.workflows;
1534
- if (!a) throw Error("workflow runtime unavailable in transaction; no flow start was submitted");
1535
- await t.store.insert(R.tableName, {
1536
- id: s,
1537
- flowRef: n.flowRef,
1538
- flowName: r.name,
1539
- mode: r.mode,
1540
- status: "pending",
1541
- source: c,
1542
- requestId: o,
1543
- input: i,
1544
- ownerId: Un(t)
1545
- });
1546
- let l = await Tn(t, s, await a.start(e, {
1547
- runId: s,
1548
- flowRef: n.flowRef,
1549
- input: i,
1550
- source: c,
1551
- requestId: o
1552
- }));
1553
- return b.make({
1554
- runId: s,
1555
- requestId: o,
1556
- admission: l
1557
- });
1558
- }));
1559
- }), Kn = (t, r) => D.gen(function* () {
1560
- return yield* Wn(t), yield* D.tryPromise({
1561
- try: () => t.transaction(async (t) => {
1562
- let i = t.workflows;
1563
- if (!i) throw Error("workflow runtime unavailable in transaction; no flow start was submitted");
1564
- let a = (await t.store.query(N(R).where(A("id", r.runId)).descriptor))[0];
1565
- if (!a) throw new T({
1566
- runId: r.runId,
1567
- message: "run not found"
1568
- });
1569
- let o = a.requestId;
1570
- if (typeof o != "string" || o.length === 0) throw Error("stored flow run has no valid requestId; retry refused without changing the run");
1571
- let s = k.decodeUnknownResult(n.payloadSchema.pipe(k.check(k.makeFilter((e) => e.runId === r.runId && e.flowRef.length > 0))))({
1572
- ...a,
1573
- runId: a.id
1574
- });
1575
- if (O.isFailure(s)) throw Error("stored workflow payload is incomplete or invalid; retry refused without changing the run");
1576
- let c = await Tn(t, r.runId, await i.start(e, s.success));
1577
- return b.make({
1578
- runId: r.runId,
1579
- requestId: o,
1580
- admission: c
1581
- });
1582
- }),
1583
- catch: (e) => e
1584
- }).pipe(D.catch((e) => e instanceof T ? D.fail(e) : D.die(e)));
1585
- }), qn = (t, r) => D.gen(function* () {
1586
- let i = yield* $(t, r.runId);
1587
- if (!i) return yield* D.fail(new T({
1588
- runId: r.runId,
1589
- message: "run not found"
1590
- }));
1591
- if (Jn(i.status)) return C.make({
1592
- runId: r.runId,
1593
- status: i.status,
1594
- engine: "not-requested",
1595
- control: null
1596
- });
1597
- let a = (/* @__PURE__ */ new Date()).toISOString();
1598
- yield* D.promise(() => t.store.updateMany(R.tableName, {
1599
- status: "cancelling",
1600
- cancelledAt: a
1601
- }, { where: Fe(A("id", r.runId), Re("status", [
1602
- "pending",
1603
- "running",
1604
- "waiting"
1605
- ])) }));
1606
- let o = yield* $(t, r.runId);
1607
- if (!o) return yield* D.fail(new T({
1608
- runId: r.runId,
1609
- message: "run not found"
1610
- }));
1611
- if (Jn(o.status)) return C.make({
1612
- runId: r.runId,
1613
- status: o.status,
1614
- engine: "not-requested",
1615
- control: null
1616
- });
1617
- let s = t.workflows, c = k.decodeUnknownOption(k.Struct({
1618
- runId: k.Literal(r.runId),
1619
- flowRef: k.NonEmptyString,
1620
- requestId: k.NonEmptyString,
1621
- input: k.Record(k.String, k.Unknown),
1622
- source: k.Literals(["manual", "cron"])
1623
- }))({
1624
- ...i,
1625
- runId: i.id
1626
- }), l = s === void 0 || c._tag === "None" ? null : yield* D.flatMap(n.executionId(c.value), (t) => D.tryPromise(async () => {
1627
- let n = k.decodeUnknownSync(je)(await s.cancel(e, t));
1628
- if (n.operation !== "cancel" || n.snapshot.workflowName !== "flow.run" || n.snapshot.executionId !== t) throw Error("workflow cancellation receipt does not match the flow execution");
1629
- return n;
1630
- })).pipe(D.catch(() => D.succeed(null))), u = l === null ? s === void 0 || c._tag === "None" ? "unreachable" : "unknown" : l.snapshot.status === "cancelled" && (l.kind === "confirmed" || l.kind === "already-terminal") ? "cancelled" : l.kind === "accepted" ? "accepted" : l.kind === "already-terminal" ? "already-terminal" : "unknown", d = Fe(A("id", r.runId), A("status", "cancelling"), A("cancelledAt", o.cancelledAt));
1631
- if (u === "cancelled") yield* D.promise(() => t.store.updateMany(R.tableName, {
1632
- status: "cancelled",
1633
- completedAt: o.completedAt ?? (/* @__PURE__ */ new Date()).toISOString()
1634
- }, { where: d }));
1635
- else if (l?.kind === "already-terminal") {
1636
- let e = k.decodeUnknownOption(n.successSchema)(l.snapshot.output), i = l.snapshot.status === "failed" ? "failed" : e._tag === "Some" && e.value.runId === r.runId && e.value.status !== "waiting" ? e.value.status : void 0;
1637
- i !== void 0 && (yield* D.promise(() => t.store.updateMany(R.tableName, {
1638
- status: i,
1639
- completedAt: o.completedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1640
- ...i === "cancelled" ? {} : { cancelledAt: null }
1641
- }, { where: d })));
1642
- }
1643
- let f = yield* $(t, r.runId);
1644
- return f ? yield* k.decodeUnknownEffect(C)({
1645
- runId: r.runId,
1646
- status: f.status,
1647
- engine: u,
1648
- control: l
1649
- }).pipe(D.orDie) : yield* D.fail(new T({
1650
- runId: r.runId,
1651
- message: "run not found"
1652
- }));
1653
- }), Jn = (e) => e === "succeeded" || e === "failed" || e === "cancelled", Yn = (e) => {
1654
- let t = e.steps?.filter((e) => e.status === "waiting"), n = t?.[0];
1655
- if (t?.length !== 1 || n?.type !== "human" || !Number.isSafeInteger(n.id) || n.id < 0) throw Error("expected exactly one waiting human step with a nonnegative integer index");
1656
- return n.id;
1657
- }, Xn = (t, i) => D.gen(function* () {
1658
- let a = (e, t) => new Ee({
1659
- runId: i.runId,
1660
- reason: e,
1661
- message: t
1662
- }), o = yield* k.decodeUnknownEffect(le, { onExcessProperty: "error" })(i).pipe(D.mapError(() => a("invalid-response", "review response requires runId, displayed stepIndex and a valid response")));
1663
- if (o.response.decision === void 0 && o.response.text === void 0 && o.response.value === void 0) return yield* D.fail(a("invalid-response", "review response must contain a decision, text or value"));
1664
- let s = t.workflows;
1665
- if (!s) return yield* D.fail(a("runtime-unavailable", "workflow runtime unavailable; review was not sent"));
1666
- let c = yield* $(t, i.runId);
1667
- if (!c) return yield* D.fail(new T({
1668
- runId: i.runId,
1669
- message: "run not found"
1670
- }));
1671
- let l = c.status;
1672
- if (l !== "waiting") return yield* D.fail(new we({
1673
- runId: i.runId,
1674
- status: l ?? "unknown",
1675
- message: `run is "${l}", not awaiting a response`
1676
- }));
1677
- let u = yield* D.try({
1678
- try: () => Yn(c),
1679
- catch: () => a("invalid-run", "stored run has no unambiguous waiting review")
1680
- });
1681
- if (u !== o.stepIndex) return yield* D.fail(new we({
1682
- runId: i.runId,
1683
- status: l,
1684
- message: "this review is no longer waiting; reload the run before answering"
1685
- }));
1686
- let d = yield* k.decodeUnknownEffect(k.Struct({
1687
- runId: k.Literal(i.runId),
1688
- flowRef: k.NonEmptyString,
1689
- requestId: k.NonEmptyString,
1690
- input: k.Record(k.String, k.Unknown),
1691
- source: k.Literals(["manual", "cron"])
1692
- }))({
1693
- ...c,
1694
- runId: c.id
1695
- }).pipe(D.mapError(() => a("invalid-run", "stored workflow payload is incomplete; review was not sent"))), f = yield* n.executionId(d), p = {
1696
- ...o.response,
1697
- respondedAt: (/* @__PURE__ */ new Date()).toISOString()
1698
- }, m = yield* D.tryPromise({
1699
- try: () => s.signal({
1700
- workflowName: e,
1701
- executionId: f
1702
- }, r(u), p),
1703
- catch: () => a("delivery-unknown", "review delivery was not confirmed; observe the run before retrying")
1704
- }), h = yield* k.decodeUnknownEffect(k.Struct({ eventId: k.NonEmptyString }))(m).pipe(D.mapError(() => a("delivery-unknown", "workflow runtime returned no valid review delivery receipt")));
1705
- return yield* k.decodeUnknownEffect(ge)({
1706
- runId: i.runId,
1707
- stepIndex: u,
1708
- executionId: f,
1709
- eventId: h.eventId,
1710
- status: "accepted"
1711
- }).pipe(D.mapError(() => a("delivery-unknown", "workflow runtime returned no valid review delivery receipt")));
1712
- }), Zn = (e, t) => D.promise(() => e.store.query(N(L).where(A("id", t.id)).descriptor)).pipe(D.map((e) => e[0])), Qn = (e) => D.promise(() => e.store.query(N(L).descriptor)), $n = (e, t) => D.promise(() => e.store.insert(L.tableName, {
1713
- id: t.id ?? `flow-${Hn()}`,
1714
- ...t
1715
- })), er = (e, t) => D.promise(() => e.store.update(L.tableName, t.id, t.patch)), tr = (e, t) => D.promise(() => e.store.delete(L.tableName, t.id)), nr = "aiFlows", rr = (e = {}) => {
1716
- let t = Pe({
1717
- base: nr,
1
+ import { clearRegistry as e, getRegisteredFlow as t, listRegisteredFlows as n, registerFlow as r } from "./registry.js";
2
+ import { aiFlowRunsTable as i, aiFlowsTable as a, aiFlowsTables as o } from "./table.js";
3
+ import { FLOW_RUN_WORKFLOW as s, HUMAN_RESPONSE_SIGNAL_PREFIX as c, humanResponseSignalName as l } from "./workflow.js";
4
+ import { admittedStartHandle as u, reconcileFlowStarts as d } from "./startReconcile.js";
5
+ import { FLOW_RUNS_TTL_ENV as f, FLOW_RUNS_TTL_HOURS_DEFAULT as p, HUMAN_REVIEW_TIMEOUT_ENV as m, HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT as h, MAX_CHAIN_DEPTH_DEFAULT as ee, MAX_CHAIN_DEPTH_ENV as te, getAiFlowsDefaults as ne, msFromHoursEnv as re, resetAiFlowsDefaults as ie, resolveHumanReviewTimeoutMs as g, resolveMaxChainDepth as _, setAiFlowsDefaults as v } from "./defaults.js";
6
+ import { ConditionOp as y, StepCondition as b, describeCondition as x, evaluateCondition as S, isTruthy as C } from "./condition.js";
7
+ import { BriefField as w, ChainPending as T, CostCompleteness as E, CostSource as D, FlowCadence as O, FlowCancelReceipt as k, FlowChain as A, FlowMode as j, FlowReviewInput as M, FlowReviewReceipt as N, FlowStartReceipt as P, FlowStatus as F, FlowStep as I, HumanResponse as L, Json as R, MAX_STEPS_DEFAULT as z, MAX_STEPS_MAX as B, MAX_STEPS_MIN as V, MediaArtifact as H, MediaArtifacts as U, MediaInputSlot as W, MediaInputs as G, MediaReceipt as K, Modality as q, ReviewMode as J, ReviewOption as Y, RunReview as ae, RunSource as oe, RunStatus as se, RunStep as ce, RunStepStatus as le, StepType as ue, StepUsage as de, Visibility as fe, clampMaxSteps as pe, normalizeFlow as me, sanitizeOutputKey as he } from "./ir.js";
8
+ import { collectRefs as ge, interpolate as _e, unresolvedRefs as ve } from "./interpolate.js";
9
+ import { flowSegments as ye, nonContiguousGroups as be } from "./segments.js";
10
+ import { buildFlowRunExecute as xe, resolveIr as Se } from "./engine.js";
11
+ import { defineFlow as Ce, flowStep as we, validateFlow as Te } from "./define.js";
12
+ import { cadenceMatches as Ee, nextRuns as De } from "./cadence.js";
13
+ import { cronRequestId as Oe, runCadenceTick as ke } from "./cadenceTick.js";
14
+ import { makeMediaGenerator as Ae } from "./mediaAdapter.js";
15
+ import { cancelFlow as je, createFlow as Me, deleteFlow as Ne, getFlow as Pe, launchFlow as Fe, listFlows as Ie, respondToFlow as Le, retryFlow as X, updateFlow as Re, waitingStepIndex as ze } from "./procedures.js";
16
+ import { Effect as Z } from "effect";
17
+ import { definePlugin as Be, pluginInstanceName as Ve } from "@voltro/protocol";
18
+ import { eq as Q, inSet as He, notInSet as Ue, queryFor as We, registerRetention as Ge } from "@voltro/database";
19
+ //#region src/index.ts
20
+ var $ = "aiFlows", Ke = (e = {}) => {
21
+ let t = Ve({
22
+ base: $,
1718
23
  alias: e.alias
1719
24
  });
1720
- St(e.humanReviewTimeoutMs === void 0 ? {} : { humanReviewTimeoutMs: e.humanReviewTimeoutMs }), Be({
25
+ v(e.humanReviewTimeoutMs === void 0 ? {} : { humanReviewTimeoutMs: e.humanReviewTimeoutMs }), Ge({
1721
26
  source: "plugin",
1722
- table: R.tableName,
27
+ table: i.tableName,
1723
28
  timeColumn: "createdAt",
1724
- ttlMs: e.runsTtlMs ?? Tt(process.env.VOLTRO_AI_FLOW_RUNS_TTL_HOURS, 2160),
1725
- envVar: vt,
29
+ ttlMs: e.runsTtlMs ?? re(process.env.VOLTRO_AI_FLOW_RUNS_TTL_HOURS, 2160),
30
+ envVar: f,
1726
31
  label: "ai flow runs",
1727
- where: Re("status", [
32
+ where: He("status", [
1728
33
  "succeeded",
1729
34
  "failed",
1730
35
  "cancelled"
1731
36
  ])
1732
37
  });
1733
- let n = Math.max(1, e.inspectPageMax ?? 200), r = { current: void 0 }, i = (e) => ({
38
+ let r = Math.max(1, e.inspectPageMax ?? 200), a = { current: void 0 }, s = (e) => ({
1734
39
  kind: "json",
1735
40
  data: e
1736
- }), a = (e, t) => ({
41
+ }), c = (e, t) => ({
1737
42
  kind: "json",
1738
43
  status: e,
1739
44
  data: { error: t }
1740
- }), o = (e, t, n) => D.promise(async () => {
1741
- let o = r.current;
1742
- if (!o) return a(503, "store not bound yet");
1743
- let s = await o.query({
45
+ }), l = (e, t, n) => Z.promise(async () => {
46
+ let r = a.current;
47
+ if (!r) return c(503, "store not bound yet");
48
+ let i = await r.query({
1744
49
  table: e,
1745
- predicate: n === void 0 ? void 0 : A("id", n),
50
+ predicate: n === void 0 ? void 0 : Q("id", n),
1746
51
  order: [{
1747
52
  column: "createdAt",
1748
53
  direction: "desc"
@@ -1767,30 +72,30 @@ var Ut = (e, t = {}) => {
1767
72
  "createdAt"
1768
73
  ] : void 0
1769
74
  });
1770
- return i({
1771
- count: s.length,
1772
- rows: s,
75
+ return s({
76
+ count: i.length,
77
+ rows: i,
1773
78
  take: t
1774
79
  });
1775
- }).pipe(D.catchCause(() => D.succeed(a(500, "query failed")))), s = (e, t) => {
1776
- let r = /[?&]take=(\d+)/.exec(e)?.[1], i = r === void 0 ? t : Number(r);
1777
- return Math.min(n, Math.max(1, Number.isFinite(i) ? i : t));
1778
- }, c = [{
80
+ }).pipe(Z.catchCause(() => Z.succeed(c(500, "query failed")))), d = (e, t) => {
81
+ let n = /[?&]take=(\d+)/.exec(e)?.[1], i = n === void 0 ? t : Number(n);
82
+ return Math.min(r, Math.max(1, Number.isFinite(i) ? i : t));
83
+ }, p = [{
1779
84
  method: "GET",
1780
85
  path: "/flows",
1781
86
  scope: "process",
1782
87
  description: "List flow definitions (`?take=` up to the configured max).",
1783
- handler: (e) => D.promise(async () => {
1784
- let t = r.current;
1785
- if (!t) return a(503, "store not bound yet");
1786
- let o = s(e.url, Math.min(200, n)), c = [...ct()].sort((e, t) => e.name < t.name ? -1 : +(e.name > t.name)), l = c.slice(0, o).map((e) => ({
88
+ handler: (e) => Z.promise(async () => {
89
+ let t = a.current;
90
+ if (!t) return c(503, "store not bound yet");
91
+ let i = d(e.url, Math.min(200, r)), o = [...n()].sort((e, t) => e.name < t.name ? -1 : +(e.name > t.name)), l = o.slice(0, i).map((e) => ({
1787
92
  id: e.name,
1788
93
  name: e.name,
1789
94
  mode: e.mode,
1790
95
  definitionSource: "code"
1791
- })), u = l.length === o ? [] : await t.query({
96
+ })), u = l.length === i ? [] : await t.query({
1792
97
  table: "_voltro_ai_flows",
1793
- predicate: c.length === 0 ? void 0 : ze("id", c.map((e) => e.name)),
98
+ predicate: o.length === 0 ? void 0 : Ue("id", o.map((e) => e.name)),
1794
99
  order: [{
1795
100
  column: "createdAt",
1796
101
  direction: "desc"
@@ -1798,62 +103,62 @@ var Ut = (e, t = {}) => {
1798
103
  column: "id",
1799
104
  direction: "desc"
1800
105
  }],
1801
- take: o - l.length,
106
+ take: i - l.length,
1802
107
  skip: void 0,
1803
108
  projection: void 0
1804
- }), d = [...l, ...u.map((e) => ({
109
+ }), f = [...l, ...u.map((e) => ({
1805
110
  ...e,
1806
111
  definitionSource: "stored"
1807
112
  }))];
1808
- return i({
1809
- count: d.length,
1810
- rows: d,
1811
- take: o
113
+ return s({
114
+ count: f.length,
115
+ rows: f,
116
+ take: i
1812
117
  });
1813
- }).pipe(D.catchCause(() => D.succeed(a(500, "query failed"))))
118
+ }).pipe(Z.catchCause(() => Z.succeed(c(500, "query failed"))))
1814
119
  }, {
1815
120
  method: "GET",
1816
121
  path: "/runs",
1817
122
  scope: "process",
1818
123
  description: "List recent run summaries (`?take=` bounded); `?runId=` reads one run with payloads and steps.",
1819
- handler: (e) => o("_voltro_ai_flow_runs", s(e.url, Math.min(100, n)), new URL(e.url, "http://inspect.local").searchParams.get("runId") ?? void 0)
124
+ handler: (e) => l("_voltro_ai_flow_runs", d(e.url, Math.min(100, r)), new URL(e.url, "http://inspect.local").searchParams.get("runId") ?? void 0)
1820
125
  }];
1821
- return Ne({
126
+ return Be({
1822
127
  name: t,
1823
- baseName: nr,
128
+ baseName: $,
1824
129
  description: "AI Flows — durable multi-step AI pipelines (deterministic + agentic) with human-in-the-loop, chaining, and cadence. Code-first (defineFlow) or data-driven.",
1825
130
  permissions: [
1826
131
  "store:write",
1827
132
  "inspect:read",
1828
133
  "store:changes:read"
1829
134
  ],
1830
- ...e.tables === !1 ? {} : { extendSchema: { tables: ut } },
1831
- inspectEndpoints: c,
135
+ ...e.tables === !1 ? {} : { extendSchema: { tables: o } },
136
+ inspectEndpoints: p,
1832
137
  bindDataStore: (e) => {
1833
- r.current = e;
138
+ a.current = e;
1834
139
  },
1835
- onChangeEvent: (e) => D.gen(function* () {
140
+ onChangeEvent: (e) => Z.gen(function* () {
1836
141
  if (e.table !== "_voltro_workflow_runs" || e.new === null || e.op !== "update" && e.op !== "insert") return;
1837
142
  let t = e.new;
1838
143
  if (t.tag !== "flow.run") return;
1839
- let n = r.current;
144
+ let n = a.current;
1840
145
  if (n === void 0) return;
1841
- let i = t.payload, a = (typeof i == "string" ? JSON.parse(i) : i)?.runId;
1842
- if (typeof a != "string") return;
1843
- let o = (yield* D.promise(() => n.query(N(R).where(A("id", a)).descriptor)))[0];
1844
- if (o === void 0) return;
1845
- let s = o.status, c = t.executionId, l = o.workflowStart;
1846
- s === "pending" && l?.status === "queued" && typeof c == "string" && c.length > 0 && (yield* D.promise(() => n.update(R.tableName, a, { workflowStart: ft(c) })));
1847
- let u = e.old?.status === "cancelled";
1848
- if (e.op !== "update" || t.status !== "cancelled" || u || s === "cancelled" || s === "succeeded" || s === "failed") return;
1849
- let d = (/* @__PURE__ */ new Date()).toISOString(), f = typeof o.cancelledAt == "string" ? o.cancelledAt : d;
1850
- yield* D.promise(() => n.update(R.tableName, a, {
146
+ let r = t.payload, o = (typeof r == "string" ? JSON.parse(r) : r)?.runId;
147
+ if (typeof o != "string") return;
148
+ let s = (yield* Z.promise(() => n.query(We(i).where(Q("id", o)).descriptor)))[0];
149
+ if (s === void 0) return;
150
+ let c = s.status, l = t.executionId, d = s.workflowStart;
151
+ c === "pending" && d?.status === "queued" && typeof l == "string" && l.length > 0 && (yield* Z.promise(() => n.update(i.tableName, o, { workflowStart: u(l) })));
152
+ let f = e.old?.status === "cancelled";
153
+ if (e.op !== "update" || t.status !== "cancelled" || f || c === "cancelled" || c === "succeeded" || c === "failed") return;
154
+ let p = (/* @__PURE__ */ new Date()).toISOString(), m = typeof s.cancelledAt == "string" ? s.cancelledAt : p;
155
+ yield* Z.promise(() => n.update(i.tableName, o, {
1851
156
  status: "cancelled",
1852
- cancelledAt: f,
1853
- completedAt: d
157
+ cancelledAt: m,
158
+ completedAt: p
1854
159
  }));
1855
- }).pipe(D.catchCause(() => D.void))
160
+ }).pipe(Z.catchCause(() => Z.void))
1856
161
  });
1857
162
  };
1858
163
  //#endregion
1859
- export { he as BriefField, de as ChainPending, ee as ConditionOp, pe as CostCompleteness, S as CostSource, vt as FLOW_RUNS_TTL_ENV, _t as FLOW_RUNS_TTL_HOURS_DEFAULT, e as FLOW_RUN_WORKFLOW, re as FlowCadence, C as FlowCancelReceipt, me as FlowChain, ie as FlowMode, le as FlowReviewInput, ge as FlowReviewReceipt, b as FlowStartReceipt, x as FlowStatus, fe as FlowStep, t as HUMAN_RESPONSE_SIGNAL_PREFIX, gt as HUMAN_REVIEW_TIMEOUT_ENV, ht as HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT, ue as HumanResponse, oe as Json, yt as MAX_CHAIN_DEPTH_DEFAULT, bt as MAX_CHAIN_DEPTH_ENV, ae as MAX_STEPS_DEFAULT, ne as MAX_STEPS_MAX, _e as MAX_STEPS_MIN, be as MediaArtifact, y as MediaArtifacts, ye as MediaInputSlot, _ as MediaInputs, o as MediaReceipt, ve as Modality, te as ReviewMode, c as ReviewOption, s as RunReview, h as RunSource, ce as RunStatus, i as RunStep, se as RunStepStatus, xe as StepCondition, p as StepType, m as StepUsage, g as Visibility, ft as admittedStartHandle, R as aiFlowRunsTable, rr as aiFlowsPlugin, L as aiFlowsTable, ut as aiFlowsTables, bn as buildFlowRunExecute, ke as cadenceMatches, qn as cancelFlow, l as clampMaxSteps, lt as clearRegistry, At as collectRefs, $n as createFlow, En as cronRequestId, wn as defineFlow, tr as deleteFlow, a as describeCondition, v as evaluateCondition, Nt as flowSegments, xn as flowStep, Ct as getAiFlowsDefaults, Zn as getFlow, st as getRegisteredFlow, r as humanResponseSignalName, jt as interpolate, u as isTruthy, Gn as launchFlow, Qn as listFlows, ct as listRegisteredFlows, Vn as makeMediaGenerator, Oe as nextRuns, Pt as nonContiguousGroups, d as normalizeFlow, mt as reconcileFlowStarts, ot as registerFlow, wt as resetAiFlowsDefaults, Dt as resolveHumanReviewTimeoutMs, rn as resolveIr, Ot as resolveMaxChainDepth, Xn as respondToFlow, Kn as retryFlow, On as runCadenceTick, f as sanitizeOutputKey, St as setAiFlowsDefaults, Mt as unresolvedRefs, er as updateFlow, Cn as validateFlow, Yn as waitingStepIndex };
164
+ export { w as BriefField, T as ChainPending, y as ConditionOp, E as CostCompleteness, D as CostSource, f as FLOW_RUNS_TTL_ENV, p as FLOW_RUNS_TTL_HOURS_DEFAULT, s as FLOW_RUN_WORKFLOW, O as FlowCadence, k as FlowCancelReceipt, A as FlowChain, j as FlowMode, M as FlowReviewInput, N as FlowReviewReceipt, P as FlowStartReceipt, F as FlowStatus, I as FlowStep, c as HUMAN_RESPONSE_SIGNAL_PREFIX, m as HUMAN_REVIEW_TIMEOUT_ENV, h as HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT, L as HumanResponse, R as Json, ee as MAX_CHAIN_DEPTH_DEFAULT, te as MAX_CHAIN_DEPTH_ENV, z as MAX_STEPS_DEFAULT, B as MAX_STEPS_MAX, V as MAX_STEPS_MIN, H as MediaArtifact, U as MediaArtifacts, W as MediaInputSlot, G as MediaInputs, K as MediaReceipt, q as Modality, J as ReviewMode, Y as ReviewOption, ae as RunReview, oe as RunSource, se as RunStatus, ce as RunStep, le as RunStepStatus, b as StepCondition, ue as StepType, de as StepUsage, fe as Visibility, u as admittedStartHandle, i as aiFlowRunsTable, Ke as aiFlowsPlugin, a as aiFlowsTable, o as aiFlowsTables, xe as buildFlowRunExecute, Ee as cadenceMatches, je as cancelFlow, pe as clampMaxSteps, e as clearRegistry, ge as collectRefs, Me as createFlow, Oe as cronRequestId, Ce as defineFlow, Ne as deleteFlow, x as describeCondition, S as evaluateCondition, ye as flowSegments, we as flowStep, ne as getAiFlowsDefaults, Pe as getFlow, t as getRegisteredFlow, l as humanResponseSignalName, _e as interpolate, C as isTruthy, Fe as launchFlow, Ie as listFlows, n as listRegisteredFlows, Ae as makeMediaGenerator, De as nextRuns, be as nonContiguousGroups, me as normalizeFlow, d as reconcileFlowStarts, r as registerFlow, ie as resetAiFlowsDefaults, g as resolveHumanReviewTimeoutMs, Se as resolveIr, _ as resolveMaxChainDepth, Le as respondToFlow, X as retryFlow, ke as runCadenceTick, he as sanitizeOutputKey, v as setAiFlowsDefaults, ve as unresolvedRefs, Re as updateFlow, Te as validateFlow, ze as waitingStepIndex };