@voltro/plugin-ai-flows 0.85.0 → 0.86.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/engine.js ADDED
@@ -0,0 +1,906 @@
1
+ import { getRegisteredFlow as e } from "./registry.js";
2
+ import { aiFlowRunsTable as t, aiFlowsTable as n } from "./table.js";
3
+ import { humanResponseSignalName as r } from "./workflow.js";
4
+ import { resolveHumanReviewTimeoutMs as i, resolveMaxChainDepth as a } from "./defaults.js";
5
+ import { describeCondition as o, evaluateCondition as s } from "./condition.js";
6
+ import { CostSource as c, HumanResponse as l, MediaArtifacts as u, RunStep as d, StepUsage as f, normalizeFlow as p } from "./ir.js";
7
+ import { interpolate as m, unresolvedRefs as h } from "./interpolate.js";
8
+ import { flowSegments as g } from "./segments.js";
9
+ import { decodeTextParams as _ } from "./textParams.js";
10
+ import { ResolvedMediaInputs as v, resolveMediaInputRefs as y, resolveMediaInputs as b } from "./mediaInputs.js";
11
+ import { decodeMediaResult as x } from "./mediaResult.js";
12
+ import { FlowCapabilityMissing as S, FlowDependencyError as C, FlowNotFound as w } from "./errors.js";
13
+ import { Cause as T, Effect as E, Exit as D, Result as O, Schema as k } from "effect";
14
+ import { and as A, eq as j, queryFor as M } from "@voltro/database";
15
+ import { SuspensionUnavailable as ee, awaitSignalSuspending as te, step as N } from "@voltro/workflow";
16
+ import { defineTool as P, estimateCostUsd as ne, gatewayCostUsd as re, generateObject as ie, generateObjectJson as ae, generateObjectWithTools as oe, generateText as F } from "@voltro/ai";
17
+ //#region src/engine.ts
18
+ var I = (e) => e, se = (e) => e._tag === "FlowAgentUnavailable" ? e.publicMessage ?? "agent unavailable" : "agent not found", L = k.Struct({
19
+ value: k.optional(k.Unknown),
20
+ text: k.optional(k.String),
21
+ url: k.optional(k.String),
22
+ artifacts: k.optional(u),
23
+ costMicroUsd: k.optional(k.Number),
24
+ costSource: k.optional(c),
25
+ requestId: k.optional(k.String),
26
+ usage: k.optional(f),
27
+ error: k.optional(k.String)
28
+ }), R = (e) => x(e).pipe(E.map((e) => {
29
+ let t = e.artifacts.find((e) => e.role === "primary");
30
+ return {
31
+ value: t.url,
32
+ url: t.url,
33
+ artifacts: e.artifacts,
34
+ ...e.requestId === void 0 ? {} : { requestId: e.requestId },
35
+ ...e.costMicroUsd === void 0 ? {} : { costMicroUsd: e.costMicroUsd },
36
+ ...e.costSource === void 0 ? {} : { costSource: e.costSource },
37
+ ...e.usage === void 0 ? {} : { usage: e.usage }
38
+ };
39
+ }), E.catch((e) => E.succeed({ error: e }))), z = (e) => ({
40
+ ...e.requestId ? { requestId: e.requestId } : {},
41
+ ...e.costMicroUsd ? { costMicroUsd: e.costMicroUsd } : {},
42
+ ...e.costSource === void 0 ? {} : { costSource: e.costSource },
43
+ ...e.usage === void 0 ? {} : { usage: e.usage }
44
+ }), B = () => (/* @__PURE__ */ new Date()).toISOString(), ce = (e) => Math.round(e * 1e6), le = (e) => ({
45
+ name: "gateway",
46
+ model: e
47
+ }), V = (e, t) => e.resolveModel?.(t) ?? le(t), H = (e, t, n, r) => E.gen(function* () {
48
+ return t.maxSteps !== void 0 && (!Number.isSafeInteger(t.maxSteps) || t.maxSteps < 1) ? yield* E.fail(new S({
49
+ capability: "resolveAgent",
50
+ message: "agent maxSteps must be a positive safe integer"
51
+ })) : yield* F({
52
+ ...r,
53
+ system: t.system,
54
+ prompt: n,
55
+ provider: V(e, t.model),
56
+ ...t.tools === void 0 ? {} : { tools: t.tools },
57
+ ...t.maxSteps === void 0 ? {} : { maxSteps: t.maxSteps }
58
+ });
59
+ }), U = (e, t, n) => W(e, t, n).costMicroUsd, W = (e, t, n) => {
60
+ let r = re(t);
61
+ if (typeof r == "number") return {
62
+ costMicroUsd: ce(r),
63
+ costSource: "gateway"
64
+ };
65
+ let i = ne(e, { model: n ?? "unknown" });
66
+ return {
67
+ costMicroUsd: i.costMicroUsd ?? 0,
68
+ costSource: i.costSource ?? "unpriced"
69
+ };
70
+ }, G = (e) => {
71
+ let t = e.filter((e) => (e.status === "succeeded" || e.status === "failed") && (e.costSource !== void 0 || e.costMicroUsd !== void 0));
72
+ if (t.length === 0) return "unknown";
73
+ let n = t.map((e) => e.costSource ?? "unpriced");
74
+ return n.every((e) => e === "gateway") ? "actual" : n.some((e) => e === "unpriced") ? "incomplete" : "estimated";
75
+ }, K = (e, n, r) => E.promise(() => e.store.update(t.tableName, n, r).then(() => void 0)).pipe(E.catchCause(() => E.void)), q = (e, n, r, i) => E.promise(async () => {
76
+ let a = await e.store.query(M(t).where(j("id", n)).descriptor), o = a[0]?.[i];
77
+ a[0] !== void 0 && o == null && await e.store.update(t.tableName, n, r);
78
+ }).pipe(E.catchCause(() => E.void)), ue = (e, n) => E.promise(async () => {
79
+ let r = (await e.store.query(M(t).where(j("id", n)).descriptor))[0]?.status;
80
+ return r === "cancelling" || r === "cancelled";
81
+ }).pipe(E.catchCause(() => E.succeed(!1))), de = (e, n) => E.promise(() => e.store.updateMany(t.tableName, {
82
+ status: "cancelled",
83
+ completedAt: B()
84
+ }, { where: A(j("id", n), j("status", "cancelling")) }).then(() => void 0)).pipe(E.catchCause(() => E.void)), J = (t, r) => E.gen(function* () {
85
+ let i = e(r);
86
+ if (i) return i;
87
+ let a = (yield* E.promise(() => t.store.query(M(n).where(j("id", r)).descriptor)))[0];
88
+ return a ? p({
89
+ name: a.name ?? r,
90
+ mode: a.mode,
91
+ steps: a.steps ?? [],
92
+ maxSteps: a.maxSteps ?? null,
93
+ brief: a.inputSchema ?? [],
94
+ orchestratorModel: a.orchestratorModel ?? null,
95
+ orchestratorInstructions: a.orchestratorInstructions ?? null,
96
+ chain: a.chainTo ?? null,
97
+ cadence: a.cadence ?? null,
98
+ humanTimeoutMs: a.humanTimeoutMs ?? null
99
+ }) : yield* E.fail(new w({
100
+ flowRef: r,
101
+ message: `no flow registered or stored for "${r}"`
102
+ }));
103
+ }), Y = (e, t, n, r, i, a) => E.gen(function* () {
104
+ let e = m(n.prompt ?? "", r), o = n.type === "agent" || n.type === "structured" || n.type === "generate" && (n.modality ?? "text") === "text", s = yield* _(o ? n.params : void 0).pipe(E.result);
105
+ if (O.isFailure(s)) return { error: `step "${n.id}": ${s.failure}` };
106
+ 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` };
107
+ let c = h(n.prompt ?? "", r);
108
+ if (c.length > 0) return { error: new C({
109
+ stepId: n.id,
110
+ unresolvedRef: c[0],
111
+ message: `step "${n.id}" references unresolved {{${c[0]}}}`
112
+ }).message };
113
+ switch (n.type) {
114
+ case "note": return {
115
+ value: e,
116
+ text: e,
117
+ costMicroUsd: 0,
118
+ costSource: "gateway"
119
+ };
120
+ case "agent": {
121
+ if (!n.agentRef) return { error: "agent step missing agentRef" };
122
+ if (!t.resolveAgent) return { error: new S({
123
+ capability: "resolveAgent",
124
+ message: "no agent resolver configured"
125
+ }).message };
126
+ let r = yield* I(t.resolveAgent(n.agentRef, i)).pipe(E.map((e) => ({
127
+ ok: !0,
128
+ a: e
129
+ })), E.catch((e) => E.succeed({
130
+ ok: !1,
131
+ e
132
+ })));
133
+ if (!r.ok) return { error: r.e.message };
134
+ let a = yield* H(t, r.a, e, s.success).pipe(E.map((e) => ({
135
+ ok: !0,
136
+ r: e
137
+ })), E.catch((e) => E.succeed({
138
+ ok: !1,
139
+ e
140
+ })));
141
+ return a.ok ? {
142
+ value: a.r.text,
143
+ text: a.r.text,
144
+ ...W(a.r.usage, a.r.providerMetadata, r.a.model)
145
+ } : { error: String(a.e.message ?? a.e) };
146
+ }
147
+ case "structured": {
148
+ if (n.schema === void 0) return { error: `step "${n.id}": structured step requires a JSON Schema` };
149
+ let r = n.model ?? t.defaultModels?.text, i = yield* ae({
150
+ ...s.success,
151
+ prompt: e,
152
+ jsonSchema: n.schema,
153
+ ...r ? { provider: V(t, r) } : {}
154
+ }).pipe(E.map((e) => ({
155
+ ok: !0,
156
+ r: e
157
+ })), E.catch((e) => E.succeed({
158
+ ok: !1,
159
+ e
160
+ })));
161
+ return i.ok ? {
162
+ value: i.r.object,
163
+ text: JSON.stringify(i.r.object, null, 2),
164
+ ...W(i.r.usage, i.r.providerMetadata, r)
165
+ } : { error: String(i.e.message ?? i.e) };
166
+ }
167
+ case "generate": {
168
+ let o = n.modality ?? "text";
169
+ if (o === "text") {
170
+ let r = n.model ?? t.defaultModels?.text, i = yield* F({
171
+ ...s.success,
172
+ prompt: e,
173
+ ...r ? { provider: V(t, r) } : {}
174
+ }).pipe(E.map((e) => ({
175
+ ok: !0,
176
+ r: e
177
+ })), E.catch((e) => E.succeed({
178
+ ok: !1,
179
+ e
180
+ })));
181
+ return i.ok ? {
182
+ value: i.r.text,
183
+ text: i.r.text,
184
+ ...W(i.r.usage, i.r.providerMetadata, r)
185
+ } : { error: String(i.e.message ?? i.e) };
186
+ }
187
+ if (!t.generateMedia) return { error: new S({
188
+ capability: `media:${o}`,
189
+ message: `no media generator configured for ${o}`
190
+ }).message };
191
+ let c = yield* b(n.mediaInputs, r, a).pipe(E.result);
192
+ if (O.isFailure(c)) return { error: `step "${n.id}": ${c.failure}` };
193
+ let l = y(n.mediaInputs, a), u = n.model ?? t.defaultModels?.[o], d = yield* I(t.generateMedia({
194
+ modality: o,
195
+ ...u ? { model: u } : {},
196
+ prompt: e,
197
+ ...n.params ? { params: n.params } : {},
198
+ ...n.mediaInputs === void 0 ? {} : { inputs: c.success },
199
+ ...Object.keys(l).length > 0 ? { inputRefs: l } : {},
200
+ run: i
201
+ })).pipe(E.map((e) => ({
202
+ ok: !0,
203
+ m: e
204
+ })), E.catch((e) => E.succeed({
205
+ ok: !1,
206
+ e
207
+ })));
208
+ if (!d.ok) {
209
+ let e = d.e.receipt;
210
+ return {
211
+ error: d.e.message,
212
+ ...e === void 0 ? {} : e
213
+ };
214
+ }
215
+ return yield* R(d.m);
216
+ }
217
+ case "human": return { error: new S({
218
+ capability: "human",
219
+ message: "human step reached the step interpreter — it should have been parked by the deterministic executor (routing bug)"
220
+ }).message };
221
+ default: return { error: `unknown step type: ${String(n.type)}` };
222
+ }
223
+ }), fe = (e, t, n, a, c, u) => E.gen(function* () {
224
+ let d = Object.assign(Object.create(null), c), f = Object.create(null), p = a.steps.map((e, t) => ({
225
+ id: t,
226
+ title: e.title ?? `Step ${t + 1}`,
227
+ type: e.type,
228
+ status: "pending",
229
+ ...e.description ? { description: e.description } : {}
230
+ })), h = 0;
231
+ yield* q(e, n, {
232
+ status: "running",
233
+ steps: p,
234
+ totalSteps: a.steps.length,
235
+ currentStep: 0,
236
+ startedAt: B()
237
+ }, "startedAt");
238
+ for (let c of g(a.steps)) {
239
+ if (yield* ue(e, n)) return yield* de(e, n), {
240
+ runId: n,
241
+ status: "cancelled"
242
+ };
243
+ if (c.steps.length > 1) {
244
+ let r = [];
245
+ for (let { index: e, step: t } of c.steps) t.when !== void 0 && !s(t.when, d) ? p[e] = {
246
+ ...p[e],
247
+ status: "skipped",
248
+ completedAt: B(),
249
+ skipReason: o(t.when)
250
+ } : (r.push({
251
+ index: e,
252
+ step: t
253
+ }), p[e] = {
254
+ ...p[e],
255
+ status: "running",
256
+ startedAt: B()
257
+ });
258
+ yield* K(e, n, {
259
+ steps: p,
260
+ currentStep: c.steps[0].index
261
+ });
262
+ let i = yield* E.all(r.map(({ index: r, step: i }) => N({
263
+ name: `flow-${r}-${i.id}`,
264
+ input: { index: r },
265
+ success: L,
266
+ execute: Y(e, t, i, d, {
267
+ runId: n,
268
+ tenantId: u.tenantId,
269
+ ownerId: u.ownerId
270
+ }, f)
271
+ }).pipe(E.map((e) => ({
272
+ index: r,
273
+ step: i,
274
+ result: e
275
+ })))), { concurrency: "unbounded" }), a = i.find((e) => e.result.error);
276
+ for (let { index: e, step: t, result: n } of i) n.error ? (h += n.costMicroUsd ?? 0, p[e] = {
277
+ ...p[e],
278
+ status: "failed",
279
+ completedAt: B(),
280
+ errorMessage: n.error,
281
+ ...z(n)
282
+ }) : (t.outputKey && n.value !== void 0 && (d[t.outputKey] = n.value), t.outputKey && n.artifacts !== void 0 && (f[t.outputKey] = n.artifacts), h += n.costMicroUsd ?? 0, p[e] = {
283
+ ...p[e],
284
+ status: "succeeded",
285
+ completedAt: B(),
286
+ ...n.text ? { output: { text: n.text } } : {},
287
+ ...n.url ? { url: n.url } : {},
288
+ ...n.artifacts === void 0 ? {} : { artifacts: n.artifacts },
289
+ ...z(n)
290
+ });
291
+ if (a !== void 0) return yield* K(e, n, {
292
+ steps: p,
293
+ status: "failed",
294
+ errorMessage: a.result.error,
295
+ completedAt: B(),
296
+ costMicroUsd: h,
297
+ costCompleteness: G(p)
298
+ }), {
299
+ runId: n,
300
+ status: "failed"
301
+ };
302
+ yield* K(e, n, {
303
+ steps: p,
304
+ currentStep: c.steps[c.steps.length - 1].index + 1,
305
+ costMicroUsd: h,
306
+ costCompleteness: G(p)
307
+ });
308
+ continue;
309
+ }
310
+ let { index: g, step: _ } = c.steps[0];
311
+ if (_.when !== void 0 && !s(_.when, d)) {
312
+ p[g] = {
313
+ ...p[g],
314
+ status: "skipped",
315
+ completedAt: B(),
316
+ skipReason: o(_.when)
317
+ }, yield* K(e, n, {
318
+ steps: p,
319
+ currentStep: g + 1
320
+ });
321
+ continue;
322
+ }
323
+ if (_.type === "human") {
324
+ let o = {
325
+ mode: _.reviewMode ?? "approve",
326
+ ..._.options ? { options: _.options } : {},
327
+ prompt: m(_.prompt ?? "", d)
328
+ };
329
+ p[g] = {
330
+ ...p[g],
331
+ status: "waiting",
332
+ startedAt: B(),
333
+ review: o
334
+ }, yield* K(e, n, {
335
+ steps: p,
336
+ status: "waiting",
337
+ currentStep: g
338
+ }), t.onEvent && (yield* I(t.onEvent({
339
+ kind: "review-needed",
340
+ runId: n,
341
+ flowName: a.name,
342
+ ownerId: u.ownerId,
343
+ source: u.source
344
+ })).pipe(E.catchCause(() => E.void)));
345
+ let s = i({
346
+ step: _,
347
+ flow: a,
348
+ deps: t
349
+ }), c = yield* te(e, {
350
+ name: r(g),
351
+ schema: l,
352
+ timeoutMs: s
353
+ }).pipe(E.map((e) => ({
354
+ ok: !0,
355
+ a: e
356
+ })), E.catchCause((e) => T.hasInterruptsOnly(e) ? E.failCause(e) : E.succeed({
357
+ ok: !1,
358
+ cause: e
359
+ })));
360
+ if (!c.ok) {
361
+ let t = Number.isFinite(s) ? `human review timed out after ${s}ms` : "human review failed";
362
+ return p[g] = {
363
+ ...p[g],
364
+ status: "failed",
365
+ completedAt: B(),
366
+ errorMessage: t
367
+ }, yield* K(e, n, {
368
+ steps: p,
369
+ status: "failed",
370
+ errorMessage: t,
371
+ completedAt: B(),
372
+ costMicroUsd: h,
373
+ costCompleteness: G(p)
374
+ }), {
375
+ runId: n,
376
+ status: "failed"
377
+ };
378
+ }
379
+ let f = c.a;
380
+ if (f.decision === "reject") return p[g] = {
381
+ ...p[g],
382
+ status: "failed",
383
+ completedAt: B(),
384
+ errorMessage: "rejected by reviewer"
385
+ }, yield* K(e, n, {
386
+ steps: p,
387
+ status: "cancelled",
388
+ humanResponse: f,
389
+ completedAt: B(),
390
+ costMicroUsd: h,
391
+ costCompleteness: G(p)
392
+ }), {
393
+ runId: n,
394
+ status: "cancelled"
395
+ };
396
+ _.outputKey && (d[_.outputKey] = f.value ?? f.text ?? f.decision ?? !0), p[g] = {
397
+ ...p[g],
398
+ status: "succeeded",
399
+ completedAt: B(),
400
+ output: { text: String(f.text ?? f.value ?? f.decision ?? "approved") }
401
+ }, yield* K(e, n, {
402
+ steps: p,
403
+ status: "running",
404
+ humanResponse: f,
405
+ currentStep: g + 1
406
+ });
407
+ continue;
408
+ }
409
+ p[g] = {
410
+ ...p[g],
411
+ status: "running",
412
+ startedAt: B()
413
+ }, yield* K(e, n, {
414
+ steps: p,
415
+ currentStep: g
416
+ });
417
+ let v = yield* N({
418
+ name: `flow-${g}-${_.id}`,
419
+ input: { index: g },
420
+ success: L,
421
+ execute: Y(e, t, _, d, {
422
+ runId: n,
423
+ tenantId: u.tenantId,
424
+ ownerId: u.ownerId
425
+ }, f)
426
+ });
427
+ if (v.error) return h += v.costMicroUsd ?? 0, p[g] = {
428
+ ...p[g],
429
+ status: "failed",
430
+ completedAt: B(),
431
+ errorMessage: v.error,
432
+ ...z(v)
433
+ }, yield* K(e, n, {
434
+ steps: p,
435
+ status: "failed",
436
+ errorMessage: v.error,
437
+ completedAt: B(),
438
+ costMicroUsd: h,
439
+ costCompleteness: G(p)
440
+ }), {
441
+ runId: n,
442
+ status: "failed"
443
+ };
444
+ _.outputKey && v.value !== void 0 && (d[_.outputKey] = v.value), _.outputKey && v.artifacts !== void 0 && (f[_.outputKey] = v.artifacts), h += v.costMicroUsd ?? 0, p[g] = {
445
+ ...p[g],
446
+ status: "succeeded",
447
+ completedAt: B(),
448
+ ...v.text ? { output: { text: v.text } } : {},
449
+ ...v.url ? { url: v.url } : {},
450
+ ...v.artifacts === void 0 ? {} : { artifacts: v.artifacts },
451
+ ...z(v)
452
+ }, yield* K(e, n, {
453
+ steps: p,
454
+ currentStep: g + 1,
455
+ costMicroUsd: h,
456
+ costCompleteness: G(p)
457
+ });
458
+ }
459
+ let _ = Object.create(null);
460
+ for (let e of a.steps) e.outputKey && d[e.outputKey] !== void 0 && (_[e.outputKey] = d[e.outputKey]);
461
+ return yield* K(e, n, {
462
+ status: "succeeded",
463
+ output: _,
464
+ completedAt: B(),
465
+ costMicroUsd: h
466
+ }), {
467
+ runId: n,
468
+ status: "succeeded",
469
+ output: _
470
+ };
471
+ }), pe = (e, n, r, i, o, s, c) => E.gen(function* () {
472
+ let l = r.chain;
473
+ if (!l) return;
474
+ let u = [...s.chainPath ?? [], s.flowRef];
475
+ if (l.flowRef === r.name || l.flowRef === s.flowRef) return;
476
+ if (u.includes(l.flowRef)) {
477
+ yield* K(e, n, { chainRefusal: `chain to "${l.flowRef}" refused — it is already in this run's chain (${u.join(" → ")}), which would loop` });
478
+ return;
479
+ }
480
+ let d = a(c);
481
+ if (u.length >= d) {
482
+ yield* K(e, n, { chainRefusal: `chain to "${l.flowRef}" refused — depth ${u.length} reached the limit of ${d} (${u.join(" → ")})` });
483
+ return;
484
+ }
485
+ let f = {
486
+ ...i,
487
+ ...o
488
+ }, p = {};
489
+ for (let e of l.mappings) e.sourceKey in f && (p[e.targetKey] = f[e.sourceKey]);
490
+ if (l.requireConfirmation) {
491
+ yield* K(e, n, { chainPending: {
492
+ flowRef: l.flowRef,
493
+ input: p,
494
+ status: "pending"
495
+ } });
496
+ return;
497
+ }
498
+ let m = e.workflows;
499
+ if (!m) return;
500
+ let h = `${n}--chain`, g = `${s.requestId}--chain`;
501
+ yield* E.promise(async () => {
502
+ try {
503
+ await e.store.insert(t.tableName, {
504
+ id: h,
505
+ flowRef: l.flowRef,
506
+ flowName: l.flowRef,
507
+ status: "pending",
508
+ source: s.source,
509
+ requestId: g,
510
+ input: p
511
+ });
512
+ } catch {}
513
+ await m.child("flow.run", {
514
+ runId: h,
515
+ flowRef: l.flowRef,
516
+ input: p,
517
+ source: s.source,
518
+ requestId: g,
519
+ chainPath: u
520
+ });
521
+ }).pipe(E.catchCause(() => E.void));
522
+ }), me = (e) => e.type === "agent" ? e.agentRef ? `agent step, agent "${e.agentRef}"` : "agent step" : e.type === "generate" ? `${e.modality ?? "media"} generation step` : `${e.type} step`, he = (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}` : ""} (${me(e)})`).join("\n"), ge = "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", X = k.optional(k.String.annotate({ description: "One short sentence: what this call is for. Shown to the user in the run timeline." })), Z = (e) => e === void 0 || e.trim() === "" ? {} : { description: e.trim().slice(0, 200) }, Q = k.Struct({ json: k.String.annotate({ description: "The requested JSON object, serialized as a JSON string." }) }), _e = (e) => {
523
+ try {
524
+ let t = JSON.parse(e);
525
+ return typeof t == "object" && t && !Array.isArray(t) ? t : void 0;
526
+ } catch {
527
+ return;
528
+ }
529
+ }, ve = (e) => {
530
+ if (D.isSuccess(e)) return "the tool returned without recording a result";
531
+ if (T.hasInterruptsOnly(e.cause)) return "interrupted before it finished — nothing waited for its result";
532
+ let t = T.squash(e.cause);
533
+ return t instanceof Error ? t.message : String(t);
534
+ }, ye = (e) => {
535
+ let t = Object.entries(e);
536
+ 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");
537
+ }, $ = (e) => [
538
+ e.orchestrator?.instructions ?? "You are an orchestrator that uses the available tools to produce a bundled result.",
539
+ he(e),
540
+ "When finished, emit a JSON object mapping each deliverable name (outputKey) to its value, serialized as a string in the json field."
541
+ ].filter(Boolean).join("\n\n"), be = k.Struct({
542
+ object: k.Record(k.String, k.Unknown),
543
+ planCostMicroUsd: k.Number,
544
+ planCostSource: k.optional(c),
545
+ toolCostMicroUsd: k.Number,
546
+ steps: k.Array(d),
547
+ error: k.optional(k.String)
548
+ }), xe = (e, t, n, r, i, a, o, s) => E.gen(function* () {
549
+ yield* q(e, n, {
550
+ status: "running",
551
+ startedAt: B(),
552
+ totalSteps: r.steps.length
553
+ }, "startedAt");
554
+ let c = yield* N({
555
+ name: "flow-agentic",
556
+ input: { flowRef: r.name },
557
+ success: be,
558
+ execute: E.gen(function* () {
559
+ let c = [], l = 0, u = (e) => {
560
+ let t = c.length;
561
+ return c.push({
562
+ id: t,
563
+ status: "running",
564
+ startedAt: B(),
565
+ ...e
566
+ }), t;
567
+ }, d = (e, t) => {
568
+ c[e] = {
569
+ ...c[e],
570
+ completedAt: B(),
571
+ ...t
572
+ };
573
+ }, f = () => K(e, n, {
574
+ steps: c,
575
+ currentStep: c.length,
576
+ costMicroUsd: l
577
+ }), p = (e, t) => E.suspend(() => {
578
+ let n = u(e);
579
+ return E.andThen(f(), t(n)).pipe(E.onExit((e) => c[n]?.status === "running" ? (d(n, {
580
+ status: "failed",
581
+ errorMessage: ve(e)
582
+ }), E.ignore(f())) : E.void));
583
+ }), m = yield* (t.listAgents ? I(t.listAgents({
584
+ runId: n,
585
+ tenantId: o,
586
+ ownerId: a
587
+ })) : E.succeed(void 0)).pipe(E.result);
588
+ if (O.isFailure(m)) return yield* E.logWarning(`flow agent listing failed for run ${n}: ${m.failure.message}`).pipe(E.annotateLogs({ scope: "voltro:ai-flows" })), {
589
+ object: {},
590
+ planCostMicroUsd: 0,
591
+ toolCostMicroUsd: 0,
592
+ steps: c,
593
+ error: "flow agent listing failed"
594
+ };
595
+ let h = m.success, g = h ?? [...new Set(r.steps.flatMap((e) => e.type === "agent" && e.agentRef ? [e.agentRef] : []))].map((e) => ({ ref: e })), _ = g.map((e) => e.ref), y = _.length > 0 ? k.Literals(_) : k.String, b = P({
596
+ name: "run_agent",
597
+ 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("; ")}.` : ""),
598
+ input: k.Struct({
599
+ agentRef: y,
600
+ prompt: k.String,
601
+ purpose: X
602
+ }),
603
+ execute: ({ agentRef: e, prompt: r, purpose: i }) => p({
604
+ title: `agent:${e}`,
605
+ type: "agent",
606
+ agentRef: e,
607
+ ...Z(i)
608
+ }, (i) => E.gen(function* () {
609
+ if (!t.resolveAgent) return d(i, {
610
+ status: "failed",
611
+ errorMessage: "no agent resolver configured"
612
+ }), yield* f(), "ERROR: no agent resolver configured";
613
+ let s = yield* I(t.resolveAgent(e, {
614
+ runId: n,
615
+ tenantId: o,
616
+ ownerId: a
617
+ })).pipe(E.map((e) => ({
618
+ ok: !0,
619
+ a: e
620
+ })), E.catch((e) => E.succeed({
621
+ ok: !1,
622
+ e
623
+ })));
624
+ if (!s.ok) return d(i, {
625
+ status: "failed",
626
+ errorMessage: s.e.message
627
+ }), yield* f(), `ERROR: ${se(s.e)}`;
628
+ let c = yield* H(t, s.a, r, {}).pipe(E.map((e) => ({
629
+ ok: !0,
630
+ r: e
631
+ })), E.catch((e) => E.succeed({
632
+ ok: !1,
633
+ e
634
+ })));
635
+ if (!c.ok) {
636
+ let e = String(c.e.message ?? c.e);
637
+ return d(i, {
638
+ status: "failed",
639
+ errorMessage: e
640
+ }), yield* f(), `ERROR: ${e}`;
641
+ }
642
+ let u = U(c.r.usage, c.r.providerMetadata, s.a.model);
643
+ return l += u, d(i, {
644
+ status: "succeeded",
645
+ output: { text: c.r.text },
646
+ costMicroUsd: u
647
+ }), yield* f(), c.r.text;
648
+ }))
649
+ }), x = P({
650
+ name: "generate_media",
651
+ description: "Generate image, video, or audio artifacts. Returns every artifact with its URL, role, media type and optional storage reference.",
652
+ input: k.Struct({
653
+ modality: k.Literals([
654
+ "image",
655
+ "video",
656
+ "audio"
657
+ ]),
658
+ prompt: k.String,
659
+ purpose: X,
660
+ model: k.optional(k.String),
661
+ inputs: k.optional(v),
662
+ params: k.optional(k.Record(k.String, k.Unknown))
663
+ }),
664
+ execute: ({ modality: e, prompt: r, purpose: i, model: s, inputs: c, params: u }) => p({
665
+ title: `media:${e}`,
666
+ type: "generate",
667
+ modality: e,
668
+ ...Z(i)
669
+ }, (i) => E.gen(function* () {
670
+ if (!t.generateMedia) return d(i, {
671
+ status: "failed",
672
+ errorMessage: `no media generator for ${e}`
673
+ }), yield* f(), `ERROR: no media generator configured for ${e}`;
674
+ let p = yield* I(t.generateMedia({
675
+ modality: e,
676
+ prompt: r,
677
+ ...s ? { model: s } : {},
678
+ ...c === void 0 ? {} : { inputs: c },
679
+ ...u === void 0 ? {} : { params: u },
680
+ run: {
681
+ runId: n,
682
+ tenantId: o,
683
+ ownerId: a
684
+ }
685
+ })).pipe(E.map((e) => ({
686
+ ok: !0,
687
+ r: e
688
+ })), E.catch((e) => E.succeed({
689
+ ok: !1,
690
+ e
691
+ })));
692
+ if (!p.ok) return d(i, {
693
+ status: "failed",
694
+ errorMessage: p.e.message
695
+ }), yield* f(), `ERROR: ${p.e.message}`;
696
+ let m = yield* R(p.r);
697
+ return m.error ? (d(i, {
698
+ status: "failed",
699
+ errorMessage: m.error
700
+ }), yield* f(), { error: m.error }) : (l += m.costMicroUsd ?? 0, d(i, {
701
+ status: "succeeded",
702
+ url: m.url,
703
+ artifacts: m.artifacts,
704
+ ...m.requestId ? { requestId: m.requestId } : {},
705
+ costMicroUsd: m.costMicroUsd ?? 0,
706
+ costSource: m.costSource ?? "unpriced"
707
+ }), yield* f(), { artifacts: m.artifacts });
708
+ }))
709
+ }), S = P({
710
+ name: "pick_structured",
711
+ description: "Produce a JSON object for a task. Returns the object.",
712
+ input: k.Struct({
713
+ prompt: k.String,
714
+ purpose: X,
715
+ model: k.optional(k.String)
716
+ }),
717
+ execute: ({ prompt: e, purpose: n, model: r }) => p({
718
+ title: "structured",
719
+ type: "structured",
720
+ ...Z(n)
721
+ }, (n) => E.gen(function* () {
722
+ let i = yield* ie({
723
+ prompt: `${e}\n\nReturn the JSON object serialized as a string in the \`json\` field.`,
724
+ schema: Q,
725
+ ...r ? { provider: V(t, r) } : {}
726
+ }).pipe(E.map((e) => ({
727
+ ok: !0,
728
+ r: e
729
+ })), E.catch((e) => E.succeed({
730
+ ok: !1,
731
+ e
732
+ })));
733
+ if (!i.ok) {
734
+ let e = String(i.e.message ?? i.e);
735
+ return d(n, {
736
+ status: "failed",
737
+ errorMessage: e
738
+ }), yield* f(), { error: e };
739
+ }
740
+ let a = U(i.r.usage, i.r.providerMetadata, r);
741
+ l += a;
742
+ let o = _e(i.r.object.json);
743
+ if (o === void 0) {
744
+ let e = "the model's `json` field is not a JSON object";
745
+ return d(n, {
746
+ status: "failed",
747
+ errorMessage: e,
748
+ costMicroUsd: a
749
+ }), yield* f(), { error: e };
750
+ }
751
+ return d(n, {
752
+ status: "succeeded",
753
+ output: { text: JSON.stringify(o) },
754
+ costMicroUsd: a
755
+ }), yield* f(), o;
756
+ }))
757
+ }), C = {
758
+ run_agent: b,
759
+ generate_media: x,
760
+ pick_structured: S
761
+ }, w = yield* (t.resolveTools ? I(t.resolveTools(s, {
762
+ runId: n,
763
+ tenantId: o,
764
+ ownerId: a
765
+ }, { provider: () => r.orchestrator?.model ? V(t, r.orchestrator.model) : void 0 })) : E.succeed({})).pipe(E.result);
766
+ if (O.isFailure(w)) return yield* E.logWarning(`flow tool resolution failed for run ${n}: ${w.failure.message}`).pipe(E.annotateLogs({ scope: "voltro:ai-flows" })), {
767
+ object: {},
768
+ planCostMicroUsd: 0,
769
+ toolCostMicroUsd: 0,
770
+ steps: c,
771
+ error: "flow tool resolution failed"
772
+ };
773
+ if (Object.keys(w.success).some((e) => Object.hasOwn(C, e))) return {
774
+ object: {},
775
+ planCostMicroUsd: 0,
776
+ toolCostMicroUsd: 0,
777
+ steps: c,
778
+ error: "flow tools cannot replace reserved planner tools"
779
+ };
780
+ let T = t.memoryPrefix ? yield* I(t.memoryPrefix(a)).pipe(E.catch(() => E.succeed(""))) : "", D = T ? `${T}\n\n${$(r)}` : $(r), A = yield* oe({
781
+ system: D,
782
+ prompt: ye(i),
783
+ schema: Q,
784
+ tools: {
785
+ ...w.success,
786
+ ...h?.length === 0 ? {
787
+ generate_media: x,
788
+ pick_structured: S
789
+ } : C
790
+ },
791
+ maxSteps: r.maxSteps,
792
+ ...r.orchestrator?.model ? { provider: V(t, r.orchestrator.model) } : {}
793
+ }).pipe(E.provideService(ee, ge), E.map((e) => ({
794
+ ok: !0,
795
+ r: e
796
+ })), E.catch((e) => E.succeed({
797
+ ok: !1,
798
+ e
799
+ })));
800
+ for (let e of c) e.status === "running" && d(e.id, {
801
+ status: "failed",
802
+ errorMessage: "not finished — the run ended first"
803
+ });
804
+ if (!A.ok) return {
805
+ object: {},
806
+ planCostMicroUsd: 0,
807
+ toolCostMicroUsd: l,
808
+ steps: c,
809
+ error: String(A.e.message ?? A.e)
810
+ };
811
+ let j = _e(A.r.object.json);
812
+ return {
813
+ object: j ?? {},
814
+ ...j === void 0 ? { error: "the planner's `json` field is not a JSON object" } : {},
815
+ planCostMicroUsd: U(A.r.usage, A.r.providerMetadata, r.orchestrator?.model),
816
+ planCostSource: W(A.r.usage, A.r.providerMetadata, r.orchestrator?.model).costSource,
817
+ toolCostMicroUsd: l,
818
+ steps: c
819
+ };
820
+ })
821
+ }), l = c.planCostMicroUsd + c.toolCostMicroUsd, u = G([...c.steps, {
822
+ status: "succeeded",
823
+ costMicroUsd: c.planCostMicroUsd,
824
+ costSource: c.planCostSource ?? "unpriced"
825
+ }]);
826
+ return c.error ? (yield* K(e, n, {
827
+ status: "failed",
828
+ steps: c.steps,
829
+ errorMessage: c.error,
830
+ completedAt: B(),
831
+ costMicroUsd: l,
832
+ costCompleteness: u
833
+ }), {
834
+ runId: n,
835
+ status: "failed"
836
+ }) : (yield* K(e, n, {
837
+ status: "succeeded",
838
+ steps: c.steps,
839
+ output: c.object,
840
+ completedAt: B(),
841
+ costMicroUsd: l,
842
+ costCompleteness: u
843
+ }), {
844
+ runId: n,
845
+ status: "succeeded",
846
+ output: c.object
847
+ });
848
+ }), Se = (e, n = {}) => (r, i) => E.gen(function* () {
849
+ let { runId: i, flowRef: a, input: o } = r, s = yield* E.tryPromise(() => e.store.query(M(t).where(j("id", i)).descriptor)).pipe(E.flatMap(k.decodeUnknownEffect(k.Tuple([k.Struct({
850
+ id: k.Literal(i),
851
+ tenantId: k.NullOr(k.NonEmptyString),
852
+ ownerId: k.optional(k.NullOr(k.String))
853
+ })]))), E.result);
854
+ if (O.isFailure(s)) return yield* K(e, i, {
855
+ status: "failed",
856
+ errorMessage: "flow run context unavailable: expected one matching run row with an explicit tenantId (string or null)",
857
+ completedAt: B()
858
+ }), {
859
+ runId: i,
860
+ status: "failed"
861
+ };
862
+ let { tenantId: c, ownerId: l = null } = s.success[0], u = yield* N({
863
+ name: "flow-0-resolve",
864
+ input: { flowRef: a },
865
+ success: k.Struct({
866
+ ir: k.Unknown,
867
+ error: k.optional(k.String)
868
+ }),
869
+ execute: J(e, a).pipe(E.flatMap((e) => {
870
+ for (let t of e.steps) {
871
+ if (!(t.type === "agent" || t.type === "structured" || t.type === "generate" && (t.modality ?? "text") === "text") || t.params === void 0) continue;
872
+ let e = E.runSyncExit(_(t.params));
873
+ if (D.isFailure(e)) return E.succeed({
874
+ ir: null,
875
+ error: `step "${t.id}": ${T.squash(e.cause)}`
876
+ });
877
+ }
878
+ return E.succeed({ ir: JSON.parse(JSON.stringify(e)) });
879
+ }), E.catch((e) => E.succeed({
880
+ ir: null,
881
+ error: e.message
882
+ })))
883
+ });
884
+ if (u.error || !u.ir) return yield* K(e, i, {
885
+ status: "failed",
886
+ errorMessage: u.error ?? "flow not found",
887
+ completedAt: B()
888
+ }), {
889
+ runId: i,
890
+ status: "failed"
891
+ };
892
+ let d = u.ir, f = d.mode === "agentic" ? yield* xe(e, n, i, d, o, l, c, a) : yield* fe(e, n, i, d, o, {
893
+ ownerId: l,
894
+ tenantId: c,
895
+ source: r.source
896
+ });
897
+ return f.status === "succeeded" && d.chain && (yield* pe(e, i, d, o, f.output ?? {}, r, n)), n.onEvent && (f.status === "succeeded" || f.status === "failed") && (yield* I(n.onEvent({
898
+ kind: f.status,
899
+ runId: i,
900
+ flowName: d.name,
901
+ ownerId: l,
902
+ source: r.source
903
+ })).pipe(E.catchCause(() => E.void))), f;
904
+ });
905
+ //#endregion
906
+ export { Se as buildFlowRunExecute, J as resolveIr };