@voltro/plugin-ai-flows 0.1.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 ADDED
@@ -0,0 +1,965 @@
1
+ import { BriefField as e, ChainPending as t, FlowCadence as n, FlowChain as r, FlowMode as i, FlowStatus as a, FlowStep as o, HumanResponse as s, Json as c, MAX_STEPS_DEFAULT as l, MAX_STEPS_MAX as u, MAX_STEPS_MIN as d, MediaInputSlot as f, MediaInputs as p, Modality as m, ReviewMode as h, ReviewOption as ee, RunReview as te, RunSource as ne, RunStatus as re, RunStep as ie, RunStepStatus as ae, StepType as oe, Visibility as se, clampMaxSteps as ce, normalizeFlow as g, sanitizeOutputKey as le } from "./ir.js";
2
+ import { FLOW_RUN_WORKFLOW as _, HUMAN_RESPONSE_SIGNAL as v } from "./workflow.js";
3
+ import { FlowBriefIncomplete as ue, FlowCapabilityMissing as y, FlowDependencyError as de, FlowNotAwaitingResponse as fe, FlowNotFound as pe, FlowRunNotFound as b, FlowValidationError as me } from "./errors.js";
4
+ import { n as he, t as ge } from "./cadence-Bt6dPelT.js";
5
+ import { Effect as x, Schema as S } from "effect";
6
+ import { definePlugin as _e } from "@voltro/protocol";
7
+ import { boolean as ve, eq as C, id as ye, integer as w, json as T, queryFor as E, table as D, text as O, timestamp as k } from "@voltro/database";
8
+ import { tenant as A } from "@voltro/plugin-multitenancy/mixin";
9
+ import { audit as j } from "@voltro/plugin-audit/mixin";
10
+ import { softDelete as be } from "@voltro/plugin-soft-delete/mixin";
11
+ import { awaitSignalSuspending as xe, step as M } from "@voltro/workflow";
12
+ import { defineTool as N, estimateCostUsd as P, gatewayCostUsd as F, generateImage as Se, generateObject as I, generateObjectWithTools as Ce, generateSpeech as we, generateText as L, generateVideo as Te } from "@voltro/ai";
13
+ //#region src/table.ts
14
+ var R = D("ai_flows", {
15
+ id: ye({ prefix: "aifl" }),
16
+ name: O(),
17
+ description: O().nullable(),
18
+ mode: O().default("deterministic"),
19
+ status: O().default("draft"),
20
+ visibility: O().default("private"),
21
+ orchestratorModel: O().nullable(),
22
+ orchestratorInstructions: O().nullable(),
23
+ maxSteps: w().default(30),
24
+ steps: T().nullable(),
25
+ inputSchema: T().nullable(),
26
+ chainTo: T().nullable(),
27
+ cadence: T().nullable(),
28
+ isEnabled: ve().default(!0),
29
+ metadata: T().nullable(),
30
+ icon: O().nullable(),
31
+ color: O().nullable(),
32
+ avatarUrl: O().nullable(),
33
+ usageCount: w().default(0),
34
+ ownerId: O().nullable()
35
+ }).with(A(), j(), be()).index(["status"]).index(["visibility"]).reactive(), z = D("ai_flow_runs", {
36
+ id: ye({ prefix: "aifr" }),
37
+ flowRef: O(),
38
+ flowName: O().nullable(),
39
+ mode: O().default("deterministic"),
40
+ status: O().default("pending"),
41
+ source: O().nullable(),
42
+ requestId: O(),
43
+ input: T().nullable(),
44
+ output: T().nullable(),
45
+ steps: T().nullable(),
46
+ currentStep: w().default(0),
47
+ totalSteps: w().default(0),
48
+ humanResponse: T().nullable(),
49
+ chainPending: T().nullable(),
50
+ costMicroUsd: w().default(0),
51
+ durationMs: w().nullable(),
52
+ error: O().nullable(),
53
+ errorMessage: O().nullable(),
54
+ startedAt: k().nullable(),
55
+ completedAt: k().nullable(),
56
+ cancelledAt: k().nullable(),
57
+ sessionId: O().nullable(),
58
+ sessionName: O().nullable(),
59
+ ownerId: O().nullable(),
60
+ metadata: T().nullable()
61
+ }).with(A(), j()).index(["flowRef"]).index(["status"]).index(["requestId"]).reactive(), B = [R, z], Ee = /\{\{\s*([\w.-]+)\s*\}\}/g, V = (e) => {
62
+ let t = [];
63
+ for (let n of e.matchAll(Ee)) t.push(n[1]);
64
+ return t;
65
+ }, H = (e, t) => e.replace(Ee, (e, n) => {
66
+ let r = t[n];
67
+ return r == null ? "" : typeof r == "string" ? r : JSON.stringify(r);
68
+ }), De = (e, t) => {
69
+ let n = /* @__PURE__ */ new Set();
70
+ for (let r of V(e)) t[r] == null && !n.has(r) && n.add(r);
71
+ return [...n];
72
+ }, U = /* @__PURE__ */ new Map(), Oe = (e) => {
73
+ U.set(e.name, e);
74
+ }, ke = (e) => U.get(e), Ae = () => [...U.values()], je = () => U.clear(), Me = S.Struct({
75
+ value: S.optional(S.Unknown),
76
+ text: S.optional(S.String),
77
+ url: S.optional(S.String),
78
+ costMicroUsd: S.optional(S.Number),
79
+ requestId: S.optional(S.String),
80
+ error: S.optional(S.String)
81
+ }), W = () => (/* @__PURE__ */ new Date()).toISOString(), Ne = (e) => Math.round(e * 1e6), G = (e, t) => e.resolveModel?.(t) ?? G(e, t), K = (e, t, n) => {
82
+ let r = F(t);
83
+ return typeof r == "number" ? Ne(r) : P(e, { model: n ?? "unknown" }).costMicroUsd ?? 0;
84
+ }, q = (e, t, n) => x.promise(() => e.store.update(z.tableName, t, n).then(() => void 0)).pipe(x.catchAllCause(() => x.void)), Pe = (e, t) => x.promise(async () => (await e.store.query(E(z).where(C("id", t)).descriptor))[0]?.status === "cancelled").pipe(x.catchAllCause(() => x.succeed(!1))), J = (e, t) => x.gen(function* () {
85
+ let n = ke(t);
86
+ if (n) return n;
87
+ let r = (yield* x.promise(() => e.store.query(E(R).where(C("id", t)).descriptor)))[0];
88
+ return r ? g({
89
+ name: r.name ?? t,
90
+ mode: r.mode,
91
+ steps: r.steps ?? [],
92
+ maxSteps: r.maxSteps ?? null,
93
+ brief: r.inputSchema ?? [],
94
+ orchestratorModel: r.orchestratorModel ?? null,
95
+ orchestratorInstructions: r.orchestratorInstructions ?? null,
96
+ chain: r.chainTo ?? null,
97
+ cadence: r.cadence ?? null
98
+ }) : yield* x.fail(new pe({
99
+ flowRef: t,
100
+ message: `no flow registered or stored for "${t}"`
101
+ }));
102
+ }), Fe = (e, t, n, r) => x.gen(function* () {
103
+ let e = H(n.prompt ?? "", r), i = De(n.prompt ?? "", r);
104
+ if (i.length > 0) return { error: new de({
105
+ stepId: n.id,
106
+ unresolvedRef: i[0],
107
+ message: `step "${n.id}" references unresolved {{${i[0]}}}`
108
+ }).message };
109
+ switch (n.type) {
110
+ case "note": return {
111
+ value: e,
112
+ text: e,
113
+ costMicroUsd: 0
114
+ };
115
+ case "agent": {
116
+ if (!n.agentRef) return { error: "agent step missing agentRef" };
117
+ if (!t.resolveAgent) return { error: new y({
118
+ capability: "resolveAgent",
119
+ message: "no agent resolver configured"
120
+ }).message };
121
+ let r = yield* t.resolveAgent(n.agentRef).pipe(x.map((e) => ({
122
+ ok: !0,
123
+ a: e
124
+ })), x.catchAll((e) => x.succeed({
125
+ ok: !1,
126
+ e
127
+ })));
128
+ if (!r.ok) return { error: r.e.message };
129
+ let i = yield* L({
130
+ system: r.a.system,
131
+ prompt: e,
132
+ provider: G(t, r.a.model)
133
+ }).pipe(x.map((e) => ({
134
+ ok: !0,
135
+ r: e
136
+ })), x.catchAll((e) => x.succeed({
137
+ ok: !1,
138
+ e
139
+ })));
140
+ return i.ok ? {
141
+ value: i.r.text,
142
+ text: i.r.text,
143
+ costMicroUsd: K(i.r.usage, i.r.providerMetadata, r.a.model)
144
+ } : { error: String(i.e.message ?? i.e) };
145
+ }
146
+ case "structured": {
147
+ let r = n.model ?? t.defaultModels?.text, i = yield* I({
148
+ prompt: e,
149
+ schema: S.Record({
150
+ key: S.String,
151
+ value: S.Unknown
152
+ }),
153
+ ...r ? { provider: G(t, r) } : {}
154
+ }).pipe(x.map((e) => ({
155
+ ok: !0,
156
+ r: e
157
+ })), x.catchAll((e) => x.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
+ costMicroUsd: K(i.r.usage, i.r.providerMetadata, r)
165
+ } : { error: String(i.e.message ?? i.e) };
166
+ }
167
+ case "generate": {
168
+ let r = n.modality ?? "text";
169
+ if (r === "text") {
170
+ let r = n.model ?? t.defaultModels?.text, i = yield* L({
171
+ prompt: e,
172
+ ...r ? { provider: G(t, r) } : {}
173
+ }).pipe(x.map((e) => ({
174
+ ok: !0,
175
+ r: e
176
+ })), x.catchAll((e) => x.succeed({
177
+ ok: !1,
178
+ e
179
+ })));
180
+ return i.ok ? {
181
+ value: i.r.text,
182
+ text: i.r.text,
183
+ costMicroUsd: K(i.r.usage, i.r.providerMetadata, r)
184
+ } : { error: String(i.e.message ?? i.e) };
185
+ }
186
+ if (!t.generateMedia) return { error: new y({
187
+ capability: `media:${r}`,
188
+ message: `no media generator configured for ${r}`
189
+ }).message };
190
+ let i = n.model ?? t.defaultModels?.[r], a = yield* t.generateMedia({
191
+ modality: r,
192
+ ...i ? { model: i } : {},
193
+ prompt: e,
194
+ ...n.params ? { params: n.params } : {}
195
+ }).pipe(x.map((e) => ({
196
+ ok: !0,
197
+ m: e
198
+ })), x.catchAll((e) => x.succeed({
199
+ ok: !1,
200
+ e
201
+ })));
202
+ return a.ok ? {
203
+ value: a.m.url,
204
+ url: a.m.url,
205
+ ...a.m.requestId ? { requestId: a.m.requestId } : {},
206
+ costMicroUsd: a.m.costMicroUsd ?? 0
207
+ } : { error: a.e.message };
208
+ }
209
+ case "human": return { error: new y({
210
+ capability: "human",
211
+ message: "human-in-the-loop steps are not yet wired (task #35)"
212
+ }).message };
213
+ default: return { error: `unknown step type: ${String(n.type)}` };
214
+ }
215
+ }), Ie = (e, t, n, r, i, a) => x.gen(function* () {
216
+ let o = { ...i }, c = r.steps.map((e, t) => ({
217
+ id: t,
218
+ title: e.title ?? `Step ${t + 1}`,
219
+ type: e.type,
220
+ status: "pending",
221
+ ...e.description ? { description: e.description } : {}
222
+ })), l = 0;
223
+ yield* q(e, n, {
224
+ status: "running",
225
+ steps: c,
226
+ totalSteps: r.steps.length,
227
+ currentStep: 0,
228
+ startedAt: W()
229
+ });
230
+ for (let [i, u] of r.steps.entries()) {
231
+ if (yield* Pe(e, n)) return {
232
+ runId: n,
233
+ status: "cancelled"
234
+ };
235
+ if (u.type === "human") {
236
+ let d = {
237
+ mode: u.reviewMode ?? "approve",
238
+ ...u.options ? { options: u.options } : {},
239
+ prompt: H(u.prompt ?? "", o)
240
+ };
241
+ c[i] = {
242
+ ...c[i],
243
+ status: "waiting",
244
+ startedAt: W(),
245
+ review: d
246
+ }, yield* q(e, n, {
247
+ steps: c,
248
+ status: "waiting",
249
+ currentStep: i
250
+ }), t.onEvent && (yield* t.onEvent({
251
+ kind: "review-needed",
252
+ runId: n,
253
+ flowName: r.name,
254
+ ownerId: a.ownerId,
255
+ source: a.source
256
+ }).pipe(x.catchAllCause(() => x.void)));
257
+ let f = yield* xe(e, {
258
+ name: v,
259
+ schema: s
260
+ }).pipe(x.map((e) => ({
261
+ ok: !0,
262
+ a: e
263
+ })), x.catchAll((e) => x.succeed({
264
+ ok: !1,
265
+ e
266
+ })));
267
+ if (!f.ok) return c[i] = {
268
+ ...c[i],
269
+ status: "failed",
270
+ completedAt: W(),
271
+ errorMessage: "human review timed out or failed to decode"
272
+ }, yield* q(e, n, {
273
+ steps: c,
274
+ status: "failed",
275
+ errorMessage: "human review timed out",
276
+ completedAt: W(),
277
+ costMicroUsd: l
278
+ }), {
279
+ runId: n,
280
+ status: "failed"
281
+ };
282
+ let p = f.a;
283
+ if (p.decision === "reject") return c[i] = {
284
+ ...c[i],
285
+ status: "failed",
286
+ completedAt: W(),
287
+ errorMessage: "rejected by reviewer"
288
+ }, yield* q(e, n, {
289
+ steps: c,
290
+ status: "cancelled",
291
+ completedAt: W(),
292
+ costMicroUsd: l
293
+ }), {
294
+ runId: n,
295
+ status: "cancelled"
296
+ };
297
+ u.outputKey && (o[u.outputKey] = p.value ?? p.text ?? p.decision ?? !0), c[i] = {
298
+ ...c[i],
299
+ status: "succeeded",
300
+ completedAt: W(),
301
+ output: { text: String(p.text ?? p.value ?? p.decision ?? "approved") }
302
+ }, yield* q(e, n, {
303
+ steps: c,
304
+ status: "running",
305
+ currentStep: i + 1
306
+ });
307
+ continue;
308
+ }
309
+ c[i] = {
310
+ ...c[i],
311
+ status: "running",
312
+ startedAt: W()
313
+ }, yield* q(e, n, {
314
+ steps: c,
315
+ currentStep: i
316
+ });
317
+ let d = yield* M({
318
+ name: `flow-${i}-${u.id}`,
319
+ input: { index: i },
320
+ success: Me,
321
+ execute: Fe(e, t, u, o)
322
+ });
323
+ if (d.error) return c[i] = {
324
+ ...c[i],
325
+ status: "failed",
326
+ completedAt: W(),
327
+ errorMessage: d.error
328
+ }, yield* q(e, n, {
329
+ steps: c,
330
+ status: "failed",
331
+ errorMessage: d.error,
332
+ completedAt: W(),
333
+ costMicroUsd: l
334
+ }), {
335
+ runId: n,
336
+ status: "failed"
337
+ };
338
+ u.outputKey && d.value !== void 0 && (o[u.outputKey] = d.value), l += d.costMicroUsd ?? 0, c[i] = {
339
+ ...c[i],
340
+ status: "succeeded",
341
+ completedAt: W(),
342
+ ...d.text ? { output: { text: d.text } } : {},
343
+ ...d.url ? { url: d.url } : {},
344
+ ...d.requestId ? { requestId: d.requestId } : {},
345
+ ...d.costMicroUsd ? { costMicroUsd: d.costMicroUsd } : {}
346
+ }, yield* q(e, n, {
347
+ steps: c,
348
+ currentStep: i + 1,
349
+ costMicroUsd: l
350
+ });
351
+ }
352
+ let u = {};
353
+ for (let e of r.steps) e.outputKey && o[e.outputKey] !== void 0 && (u[e.outputKey] = o[e.outputKey]);
354
+ return yield* q(e, n, {
355
+ status: "succeeded",
356
+ output: u,
357
+ completedAt: W(),
358
+ costMicroUsd: l
359
+ }), {
360
+ runId: n,
361
+ status: "succeeded",
362
+ output: u
363
+ };
364
+ }), Le = (e, t, n, r, i, a) => x.gen(function* () {
365
+ let o = n.chain;
366
+ if (!o || o.flowRef === n.name || o.flowRef === a.flowRef) return;
367
+ let s = {
368
+ ...r,
369
+ ...i
370
+ }, c = {};
371
+ for (let e of o.mappings) e.sourceKey in s && (c[e.targetKey] = s[e.sourceKey]);
372
+ if (o.requireConfirmation) {
373
+ yield* q(e, t, { chainPending: {
374
+ flowRef: o.flowRef,
375
+ input: c,
376
+ status: "pending"
377
+ } });
378
+ return;
379
+ }
380
+ let l = e.workflows;
381
+ if (!l) return;
382
+ let u = `${t}--chain`, d = `${a.requestId}--chain`;
383
+ yield* x.promise(async () => {
384
+ try {
385
+ await e.store.insert(z.tableName, {
386
+ id: u,
387
+ flowRef: o.flowRef,
388
+ flowName: o.flowRef,
389
+ status: "pending",
390
+ source: a.source,
391
+ requestId: d,
392
+ input: c
393
+ });
394
+ } catch {}
395
+ await l.child("flow.run", {
396
+ runId: u,
397
+ flowRef: o.flowRef,
398
+ input: c,
399
+ source: a.source,
400
+ requestId: d
401
+ });
402
+ }).pipe(x.catchAllCause(() => x.void));
403
+ }), Re = (e) => e.steps.length === 0 ? "" : "Suggested plan (you MAY reorder, insert, or skip steps):\n" + e.steps.map((e, t) => `${t + 1}. [${e.type}${e.modality ? `/${e.modality}` : ""}] ${e.title ?? e.id}${e.prompt ? `: ${e.prompt}` : ""}`).join("\n"), ze = (e) => {
404
+ let t = Object.entries(e);
405
+ 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");
406
+ }, Be = (e) => [
407
+ e.orchestrator?.instructions ?? "You are an orchestrator that uses the available tools to produce a bundled result.",
408
+ Re(e),
409
+ "When finished, emit a JSON object mapping each deliverable name (outputKey) to its value."
410
+ ].filter(Boolean).join("\n\n"), Ve = S.Struct({
411
+ object: S.Record({
412
+ key: S.String,
413
+ value: S.Unknown
414
+ }),
415
+ planCostMicroUsd: S.Number,
416
+ toolCostMicroUsd: S.Number,
417
+ steps: S.Array(ie),
418
+ error: S.optional(S.String)
419
+ }), He = (e, t, n, r, i, a) => x.gen(function* () {
420
+ yield* q(e, n, {
421
+ status: "running",
422
+ startedAt: W(),
423
+ totalSteps: r.steps.length
424
+ });
425
+ let o = yield* M({
426
+ name: "flow-agentic",
427
+ input: { flowRef: r.name },
428
+ success: Ve,
429
+ execute: x.gen(function* () {
430
+ let o = [], s = 0, c = (e) => {
431
+ let t = o.length;
432
+ return o.push({
433
+ id: t,
434
+ status: "running",
435
+ startedAt: W(),
436
+ ...e
437
+ }), t;
438
+ }, l = (e, t) => {
439
+ o[e] = {
440
+ ...o[e],
441
+ completedAt: W(),
442
+ ...t
443
+ };
444
+ }, u = () => q(e, n, {
445
+ steps: o,
446
+ currentStep: o.length,
447
+ costMicroUsd: s
448
+ }), d = N({
449
+ name: "run_agent",
450
+ description: "Delegate a text task to an allowed sub-agent. Returns the agent's text.",
451
+ input: S.Struct({
452
+ agentRef: S.String,
453
+ prompt: S.String
454
+ }),
455
+ execute: ({ agentRef: e, prompt: n }) => x.gen(function* () {
456
+ let r = c({
457
+ title: `agent:${e}`,
458
+ type: "agent"
459
+ });
460
+ if (yield* u(), !t.resolveAgent) return l(r, {
461
+ status: "failed",
462
+ errorMessage: "no agent resolver configured"
463
+ }), yield* u(), "ERROR: no agent resolver configured";
464
+ let i = yield* t.resolveAgent(e).pipe(x.map((e) => ({
465
+ ok: !0,
466
+ a: e
467
+ })), x.catchAll((e) => x.succeed({
468
+ ok: !1,
469
+ e
470
+ })));
471
+ if (!i.ok) return l(r, {
472
+ status: "failed",
473
+ errorMessage: i.e.message
474
+ }), yield* u(), `ERROR: ${i.e.message}`;
475
+ let a = yield* L({
476
+ system: i.a.system,
477
+ prompt: n,
478
+ provider: G(t, i.a.model)
479
+ }).pipe(x.map((e) => ({
480
+ ok: !0,
481
+ r: e
482
+ })), x.catchAll((e) => x.succeed({
483
+ ok: !1,
484
+ e
485
+ })));
486
+ if (!a.ok) {
487
+ let e = String(a.e.message ?? a.e);
488
+ return l(r, {
489
+ status: "failed",
490
+ errorMessage: e
491
+ }), yield* u(), `ERROR: ${e}`;
492
+ }
493
+ let o = K(a.r.usage, a.r.providerMetadata, i.a.model);
494
+ return s += o, l(r, {
495
+ status: "succeeded",
496
+ output: { text: a.r.text },
497
+ costMicroUsd: o
498
+ }), yield* u(), a.r.text;
499
+ })
500
+ }), f = N({
501
+ name: "generate_media",
502
+ description: "Generate an image, video, or audio artifact. Returns the hosted URL.",
503
+ input: S.Struct({
504
+ modality: S.Literal("image", "video", "audio"),
505
+ prompt: S.String,
506
+ model: S.optional(S.String)
507
+ }),
508
+ execute: ({ modality: e, prompt: n, model: r }) => x.gen(function* () {
509
+ let i = c({
510
+ title: `media:${e}`,
511
+ type: "generate"
512
+ });
513
+ if (yield* u(), !t.generateMedia) return l(i, {
514
+ status: "failed",
515
+ errorMessage: `no media generator for ${e}`
516
+ }), yield* u(), `ERROR: no media generator configured for ${e}`;
517
+ let a = yield* t.generateMedia({
518
+ modality: e,
519
+ prompt: n,
520
+ ...r ? { model: r } : {}
521
+ }).pipe(x.map((e) => ({
522
+ ok: !0,
523
+ r: e
524
+ })), x.catchAll((e) => x.succeed({
525
+ ok: !1,
526
+ e
527
+ })));
528
+ return a.ok ? (s += a.r.costMicroUsd ?? 0, l(i, {
529
+ status: "succeeded",
530
+ url: a.r.url,
531
+ ...a.r.requestId ? { requestId: a.r.requestId } : {},
532
+ costMicroUsd: a.r.costMicroUsd ?? 0
533
+ }), yield* u(), a.r.url) : (l(i, {
534
+ status: "failed",
535
+ errorMessage: a.e.message
536
+ }), yield* u(), `ERROR: ${a.e.message}`);
537
+ })
538
+ }), p = N({
539
+ name: "pick_structured",
540
+ description: "Produce a JSON object for a task. Returns the object.",
541
+ input: S.Struct({
542
+ prompt: S.String,
543
+ model: S.optional(S.String)
544
+ }),
545
+ execute: ({ prompt: e, model: n }) => x.gen(function* () {
546
+ let r = c({
547
+ title: "structured",
548
+ type: "structured"
549
+ });
550
+ yield* u();
551
+ let i = yield* I({
552
+ prompt: e,
553
+ schema: S.Record({
554
+ key: S.String,
555
+ value: S.Unknown
556
+ }),
557
+ ...n ? { provider: G(t, n) } : {}
558
+ }).pipe(x.map((e) => ({
559
+ ok: !0,
560
+ r: e
561
+ })), x.catchAll((e) => x.succeed({
562
+ ok: !1,
563
+ e
564
+ })));
565
+ if (!i.ok) {
566
+ let e = String(i.e.message ?? i.e);
567
+ return l(r, {
568
+ status: "failed",
569
+ errorMessage: e
570
+ }), yield* u(), { error: e };
571
+ }
572
+ let a = K(i.r.usage, i.r.providerMetadata, n);
573
+ return s += a, l(r, {
574
+ status: "succeeded",
575
+ output: { text: JSON.stringify(i.r.object) },
576
+ costMicroUsd: a
577
+ }), yield* u(), i.r.object;
578
+ })
579
+ }), m = t.memoryPrefix ? yield* t.memoryPrefix(a).pipe(x.catchAll(() => x.succeed(""))) : "", h = yield* Ce({
580
+ system: m ? `${m}\n\n${Be(r)}` : Be(r),
581
+ prompt: ze(i),
582
+ schema: S.Record({
583
+ key: S.String,
584
+ value: S.Unknown
585
+ }),
586
+ tools: {
587
+ run_agent: d,
588
+ generate_media: f,
589
+ pick_structured: p
590
+ },
591
+ maxSteps: r.maxSteps,
592
+ ...r.orchestrator?.model ? { provider: G(t, r.orchestrator.model) } : {}
593
+ }).pipe(x.map((e) => ({
594
+ ok: !0,
595
+ r: e
596
+ })), x.catchAll((e) => x.succeed({
597
+ ok: !1,
598
+ e
599
+ })));
600
+ return h.ok ? {
601
+ object: h.r.object,
602
+ planCostMicroUsd: K(h.r.usage, h.r.providerMetadata, r.orchestrator?.model),
603
+ toolCostMicroUsd: s,
604
+ steps: o
605
+ } : {
606
+ object: {},
607
+ planCostMicroUsd: 0,
608
+ toolCostMicroUsd: s,
609
+ steps: o,
610
+ error: String(h.e.message ?? h.e)
611
+ };
612
+ })
613
+ }), s = o.planCostMicroUsd + o.toolCostMicroUsd;
614
+ return o.error ? (yield* q(e, n, {
615
+ status: "failed",
616
+ steps: o.steps,
617
+ errorMessage: o.error,
618
+ completedAt: W(),
619
+ costMicroUsd: s
620
+ }), {
621
+ runId: n,
622
+ status: "failed"
623
+ }) : (yield* q(e, n, {
624
+ status: "succeeded",
625
+ steps: o.steps,
626
+ output: o.object,
627
+ completedAt: W(),
628
+ costMicroUsd: s
629
+ }), {
630
+ runId: n,
631
+ status: "succeeded",
632
+ output: o.object
633
+ });
634
+ }), Ue = (e, t = {}) => (n, r) => x.gen(function* () {
635
+ let { runId: r, flowRef: i, input: a } = n, o = yield* M({
636
+ name: "flow-0-resolve",
637
+ input: { flowRef: i },
638
+ success: S.Struct({
639
+ ir: S.Unknown,
640
+ error: S.optional(S.String)
641
+ }),
642
+ execute: J(e, i).pipe(x.map((e) => ({ ir: e })), x.catchAll((e) => x.succeed({
643
+ ir: void 0,
644
+ error: e.message
645
+ })))
646
+ });
647
+ if (o.error || !o.ir) return yield* q(e, r, {
648
+ status: "failed",
649
+ errorMessage: o.error ?? "flow not found",
650
+ completedAt: W()
651
+ }), {
652
+ runId: r,
653
+ status: "failed"
654
+ };
655
+ let s = o.ir, c = (yield* x.promise(() => e.store.query(E(z).where(C("id", r)).descriptor)).pipe(x.catchAllCause(() => x.succeed([]))))[0]?.ownerId ?? null, l = s.mode === "agentic" ? yield* He(e, t, r, s, a, c) : yield* Ie(e, t, r, s, a, {
656
+ ownerId: c,
657
+ source: n.source
658
+ });
659
+ return l.status === "succeeded" && s.chain && (yield* Le(e, r, s, a, l.output ?? {}, n)), t.onEvent && (l.status === "succeeded" || l.status === "failed") && (yield* t.onEvent({
660
+ kind: l.status,
661
+ runId: r,
662
+ flowName: s.name,
663
+ ownerId: c,
664
+ source: n.source
665
+ }).pipe(x.catchAllCause(() => x.void))), l;
666
+ }), We = {
667
+ text: (e) => ({
668
+ type: "generate",
669
+ modality: "text",
670
+ ...e
671
+ }),
672
+ media: (e, t) => ({
673
+ type: "generate",
674
+ modality: e,
675
+ ...t
676
+ }),
677
+ agent: (e) => ({
678
+ type: "agent",
679
+ ...e
680
+ }),
681
+ structured: (e) => ({
682
+ type: "structured",
683
+ ...e
684
+ }),
685
+ note: (e) => ({
686
+ type: "note",
687
+ ...e
688
+ }),
689
+ human: (e) => ({
690
+ type: "human",
691
+ ...e
692
+ })
693
+ }, Ge = (e) => e.map((e, t) => "id" in e && e.id ? e : {
694
+ id: `step-${t}`,
695
+ ...e
696
+ }), Ke = (e) => {
697
+ let t = new Set(e.brief.map((e) => e.key)), n = [];
698
+ for (let r of e.steps) {
699
+ for (let e of V(r.prompt ?? "")) t.has(e) || n.push(`step "${r.id}" references {{${e}}} which is not a brief field or a prior step outputKey`);
700
+ r.outputKey && t.add(le(r.outputKey));
701
+ }
702
+ if (n.length > 0) throw new me({
703
+ flowRef: e.name,
704
+ message: `flow "${e.name}" has ${n.length} unresolved reference(s)`,
705
+ issues: n
706
+ });
707
+ }, qe = (e) => {
708
+ let t = g({
709
+ name: e.name,
710
+ mode: e.mode,
711
+ steps: Ge(e.steps),
712
+ maxSteps: e.maxSteps,
713
+ brief: e.brief,
714
+ orchestratorModel: e.orchestrator?.model,
715
+ orchestratorInstructions: e.orchestrator?.instructions,
716
+ chain: e.chain,
717
+ cadence: e.cadence
718
+ });
719
+ return Ke(t), Oe(t), t;
720
+ }, Y = (e) => String(e).padStart(2, "0"), X = (e, t) => `cron-${e}-${t.getFullYear()}${Y(t.getMonth() + 1)}${Y(t.getDate())}-${Y(t.getHours())}${Y(t.getMinutes())}`, Je = async (e) => {
721
+ let t = [];
722
+ for (let e of Ae()) e.cadence && (e.cadence.repeats?.length ?? 0) > 0 && t.push({
723
+ flowRef: e.name,
724
+ cadence: e.cadence,
725
+ defaultInput: e.cadence.defaultInput ?? {}
726
+ });
727
+ let n = await e.store.select("ai_flows").where("isEnabled", !0).all();
728
+ for (let e of n) e.id && e.cadence && (e.cadence.repeats?.length ?? 0) > 0 && t.push({
729
+ flowRef: e.id,
730
+ cadence: e.cadence,
731
+ defaultInput: e.cadence.defaultInput ?? {}
732
+ });
733
+ return t;
734
+ }, Ye = async (e, t = /* @__PURE__ */ new Date()) => {
735
+ let n = e.workflows, r = [], i = 0, a = await Je(e).catch(() => []);
736
+ for (let o of a) {
737
+ if (!ge(o.cadence, t) || (i += 1, !n)) continue;
738
+ let a = X(o.flowRef, t), s = `run-${a}`;
739
+ try {
740
+ try {
741
+ await e.store.insert("ai_flow_runs", {
742
+ id: s,
743
+ flowRef: o.flowRef,
744
+ flowName: o.flowRef,
745
+ status: "pending",
746
+ source: "cron",
747
+ requestId: a,
748
+ input: o.defaultInput
749
+ });
750
+ } catch {}
751
+ await n.start("flow.run", {
752
+ runId: s,
753
+ flowRef: o.flowRef,
754
+ input: o.defaultInput,
755
+ source: "cron",
756
+ requestId: a
757
+ }), r.push(a);
758
+ } catch {}
759
+ }
760
+ return {
761
+ matched: i,
762
+ started: r
763
+ };
764
+ }, Xe = (e) => ({
765
+ name: "gateway",
766
+ model: e
767
+ }), Ze = (e) => Math.round(e * 1e6), Z = (e, t, n) => {
768
+ let r = F(t);
769
+ return typeof r == "number" ? Ze(r) : e ? P(e, { model: n ?? "unknown" }).costMicroUsd ?? 0 : 0;
770
+ }, Qe = (e, t) => (n) => {
771
+ let r = n.model, i = (e) => t?.resolveModel?.(e) ?? Xe(e);
772
+ return x.gen(function* () {
773
+ if (n.modality === "image") {
774
+ let t = yield* Se({
775
+ prompt: n.prompt,
776
+ ...r ? { provider: i(r) } : {}
777
+ }), a = t.images[0];
778
+ if (!a) return yield* x.fail(new y({
779
+ capability: "media:image",
780
+ message: "no image produced"
781
+ }));
782
+ let o = yield* x.promise(() => e.put({
783
+ data: a.data,
784
+ mediaType: a.mediaType
785
+ }));
786
+ return {
787
+ url: o.url,
788
+ ...o.refId ? { requestId: o.refId } : {},
789
+ costMicroUsd: Z(t.usage, t.providerMetadata, r)
790
+ };
791
+ }
792
+ if (n.modality === "audio") {
793
+ let t = yield* we({
794
+ text: n.prompt,
795
+ ...r ? { provider: i(r) } : {}
796
+ }), a = yield* x.promise(() => e.put({
797
+ data: t.audio.data,
798
+ mediaType: t.audio.mediaType
799
+ }));
800
+ return {
801
+ url: a.url,
802
+ ...a.refId ? { requestId: a.refId } : {},
803
+ costMicroUsd: Z(t.usage, t.providerMetadata, r)
804
+ };
805
+ }
806
+ let t = yield* Te({
807
+ prompt: n.prompt,
808
+ ...r ? { provider: i(r) } : {},
809
+ ...n.params ? { params: n.params } : {}
810
+ }), a;
811
+ if (t.video.url) a = e.ingestUrl ? yield* x.promise(() => e.ingestUrl(t.video.url)) : { url: t.video.url };
812
+ else if (t.video.data) a = yield* x.promise(() => e.put({
813
+ data: t.video.data,
814
+ mediaType: t.video.mediaType
815
+ }));
816
+ else return yield* x.fail(new y({
817
+ capability: "media:video",
818
+ message: "no video produced"
819
+ }));
820
+ return {
821
+ url: a.url,
822
+ ...a.refId ? { requestId: a.refId } : {},
823
+ costMicroUsd: Z(t.usage, t.providerMetadata, r)
824
+ };
825
+ }).pipe(x.catchAll((e) => e instanceof y ? x.fail(e) : x.fail(new y({
826
+ capability: `media:${n.modality}`,
827
+ message: String(e.message ?? e)
828
+ }))));
829
+ }, Q = () => globalThis.crypto?.randomUUID?.() ?? `req-${Date.now().toString(36)}`, $e = (e) => e.request?.subject?.id ?? null, $ = (e, t) => x.promise(() => e.store.query(E(z).where(C("id", t)).descriptor)).pipe(x.map((e) => e[0])), et = (e, t) => x.gen(function* () {
830
+ let n = yield* J(e, t.flowRef), r = t.input ?? {}, i = n.brief.filter((e) => e.required && e.type !== "boolean" && (r[e.key] === void 0 || r[e.key] === null || r[e.key] === "")).map((e) => e.key);
831
+ if (i.length > 0) return yield* x.fail(new ue({
832
+ missing: i,
833
+ message: `missing required brief field(s): ${i.join(", ")}`
834
+ }));
835
+ let a = Q(), o = `run-${a}`, s = t.source ?? "manual";
836
+ yield* x.promise(() => e.store.insert(z.tableName, {
837
+ id: o,
838
+ flowRef: t.flowRef,
839
+ flowName: n.name,
840
+ mode: n.mode,
841
+ status: "pending",
842
+ source: s,
843
+ requestId: a,
844
+ input: r,
845
+ ownerId: $e(e)
846
+ }));
847
+ let c = e.workflows;
848
+ return c && (yield* x.promise(() => c.start(_, {
849
+ runId: o,
850
+ flowRef: t.flowRef,
851
+ input: r,
852
+ source: s,
853
+ requestId: a
854
+ }))), {
855
+ runId: o,
856
+ requestId: a,
857
+ status: "pending"
858
+ };
859
+ }), tt = (e, t) => x.gen(function* () {
860
+ let n = yield* $(e, t.runId);
861
+ if (!n) return yield* x.fail(new b({
862
+ runId: t.runId,
863
+ message: "run not found"
864
+ }));
865
+ let r = n.requestId ?? Q(), i = n.flowRef, a = n.input ?? {}, o = n.source ?? "manual";
866
+ yield* x.promise(() => e.store.update(z.tableName, t.runId, {
867
+ status: "pending",
868
+ error: null,
869
+ errorMessage: null
870
+ }));
871
+ let s = e.workflows;
872
+ return s && (yield* x.promise(() => s.start(_, {
873
+ runId: t.runId,
874
+ flowRef: i,
875
+ input: a,
876
+ source: o,
877
+ requestId: r
878
+ }))), {
879
+ runId: t.runId,
880
+ requestId: r,
881
+ status: "pending"
882
+ };
883
+ }), nt = (e, t) => x.gen(function* () {
884
+ return (yield* $(e, t.runId)) ? (yield* x.promise(() => e.store.update(z.tableName, t.runId, {
885
+ status: "cancelled",
886
+ cancelledAt: (/* @__PURE__ */ new Date()).toISOString()
887
+ })), {
888
+ runId: t.runId,
889
+ status: "cancelled"
890
+ }) : yield* x.fail(new b({
891
+ runId: t.runId,
892
+ message: "run not found"
893
+ }));
894
+ }), rt = (e, t) => x.gen(function* () {
895
+ let n = yield* $(e, t.runId);
896
+ if (!n) return yield* x.fail(new b({
897
+ runId: t.runId,
898
+ message: "run not found"
899
+ }));
900
+ let r = n.status;
901
+ if (r !== "waiting") return yield* x.fail(new fe({
902
+ runId: t.runId,
903
+ status: r ?? "unknown",
904
+ message: `run is "${r}", not awaiting a response`
905
+ }));
906
+ let i = {
907
+ ...t.response,
908
+ respondedAt: (/* @__PURE__ */ new Date()).toISOString()
909
+ };
910
+ yield* x.promise(() => e.store.update(z.tableName, t.runId, { humanResponse: i }));
911
+ let a = e.workflows, o = n.requestId;
912
+ return a && o && (yield* x.promise(() => a.signal({
913
+ workflowName: _,
914
+ executionId: `flow-run:${o}`
915
+ }, v, i)).pipe(x.catchAllCause(() => x.void))), { runId: t.runId };
916
+ }), it = (e, t) => x.promise(() => e.store.query(E(R).where(C("id", t.id)).descriptor)).pipe(x.map((e) => e[0])), at = (e) => x.promise(() => e.store.query(E(R).descriptor)), ot = (e, t) => x.promise(() => e.store.insert(R.tableName, {
917
+ id: t.id ?? `flow-${Q()}`,
918
+ ...t
919
+ })), st = (e, t) => x.promise(() => e.store.update(R.tableName, t.id, t.patch)), ct = (e, t) => x.promise(() => e.store.delete(R.tableName, t.id)), lt = (e = {}) => {
920
+ let t = e.alias ?? "aiFlows", n = { current: void 0 }, r = (e) => ({
921
+ kind: "json",
922
+ data: e
923
+ }), i = (e, t) => ({
924
+ kind: "json",
925
+ status: e,
926
+ data: { error: t }
927
+ }), a = (e, t) => x.promise(async () => {
928
+ let a = n.current;
929
+ if (!a) return i(503, "store not bound yet");
930
+ let o = await a.query({
931
+ table: e,
932
+ predicate: void 0,
933
+ order: [],
934
+ take: t,
935
+ skip: void 0,
936
+ projection: void 0
937
+ });
938
+ return r({
939
+ count: o.length,
940
+ rows: o
941
+ });
942
+ }).pipe(x.catchAllCause(() => x.succeed(i(500, "query failed"))));
943
+ return _e({
944
+ name: t,
945
+ description: "AI Flows — durable multi-step AI pipelines (deterministic + agentic) with human-in-the-loop, chaining, and cadence. Code-first (defineFlow) or data-driven.",
946
+ permissions: ["store:write", "inspect:read"],
947
+ extendSchema: { tables: B },
948
+ inspectEndpoints: [{
949
+ method: "GET",
950
+ path: "/flows",
951
+ description: "List flow definitions.",
952
+ handler: () => a("ai_flows", 200)
953
+ }, {
954
+ method: "GET",
955
+ path: "/runs",
956
+ description: "List recent flow runs.",
957
+ handler: () => a("ai_flow_runs", 100)
958
+ }],
959
+ bindDataStore: (e) => {
960
+ n.current = e;
961
+ }
962
+ });
963
+ };
964
+ //#endregion
965
+ export { e as BriefField, t as ChainPending, _ as FLOW_RUN_WORKFLOW, n as FlowCadence, r as FlowChain, i as FlowMode, a as FlowStatus, o as FlowStep, v as HUMAN_RESPONSE_SIGNAL, s as HumanResponse, c as Json, l as MAX_STEPS_DEFAULT, u as MAX_STEPS_MAX, d as MAX_STEPS_MIN, f as MediaInputSlot, p as MediaInputs, m as Modality, h as ReviewMode, ee as ReviewOption, te as RunReview, ne as RunSource, re as RunStatus, ie as RunStep, ae as RunStepStatus, oe as StepType, se as Visibility, z as aiFlowRunsTable, lt as aiFlowsPlugin, R as aiFlowsTable, B as aiFlowsTables, Ue as buildFlowRunExecute, ge as cadenceMatches, nt as cancelFlow, ce as clampMaxSteps, je as clearRegistry, V as collectRefs, ot as createFlow, X as cronRequestId, qe as defineFlow, ct as deleteFlow, We as flowStep, it as getFlow, ke as getRegisteredFlow, H as interpolate, et as launchFlow, at as listFlows, Ae as listRegisteredFlows, Qe as makeMediaGenerator, he as nextRuns, g as normalizeFlow, Oe as registerFlow, J as resolveIr, rt as respondToFlow, tt as retryFlow, Ye as runCadenceTick, le as sanitizeOutputKey, De as unresolvedRefs, st as updateFlow, Ke as validateFlow };