@voltro/plugin-ai-flows 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
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 ee, ReviewMode as m, ReviewOption as h, 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 _ } from "./ir.js";
2
- import { FLOW_RUN_WORKFLOW as v, HUMAN_RESPONSE_SIGNAL as y } from "./workflow.js";
3
- import { FlowBriefIncomplete as le, FlowCapabilityMissing as b, FlowDependencyError as ue, FlowNotAwaitingResponse as de, FlowNotFound as fe, FlowRunNotFound as x, FlowValidationError as pe } from "./errors.js";
4
- import { n as me, t as he } from "./cadence-Bt6dPelT.js";
5
- import { Effect as S, Schema as C } from "effect";
6
- import { definePlugin as ge } from "@voltro/protocol";
7
- import { boolean as _e, eq as w, id as ve, integer as T, json as E, queryFor as D, table as ye, 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 Se, generateImage as Ce, generateObject as we, generateObjectWithTools as Te, generateSpeech as Ee, generateText as F, generateVideo as De } from "@voltro/ai";
1
+ import { A as e, C as t, D as n, E as r, M as i, O as a, S as o, T as s, _ as c, a as l, b as u, c as d, d as f, f as p, g as m, h, i as g, j as _, k as ee, l as te, m as ne, n as re, o as ie, p as ae, r as oe, s as se, t as ce, u as le, v as ue, w as de, x as fe, y as pe } from "./ir-BOv5uwYI.js";
2
+ import { FLOW_RUN_WORKFLOW as v, HUMAN_RESPONSE_SIGNAL_PREFIX as me, humanResponseSignalName as y } from "./workflow.js";
3
+ import { FlowBriefIncomplete as he, FlowCapabilityMissing as b, FlowDependencyError as ge, FlowNotAwaitingResponse as _e, FlowNotFound as ve, FlowRunNotFound as x, FlowValidationError as ye } from "./errors.js";
4
+ import { n as be, t as xe } from "./cadence-Bt6dPelT.js";
5
+ import { Cause as Se, Effect as S, Schema as C } from "effect";
6
+ import { definePlugin as Ce, pluginInstanceName as we } from "@voltro/protocol";
7
+ import { boolean as Te, eq as w, id as Ee, inSet as De, integer as T, json as E, queryFor as D, registerRetention as Oe, table as ke, text as O, timestamp as k } from "@voltro/database";
8
+ import { tenant as Ae } from "@voltro/plugin-multitenancy/mixin";
9
+ import { audit as je } from "@voltro/plugin-audit/mixin";
10
+ import { softDelete as Me } from "@voltro/plugin-soft-delete/mixin";
11
+ import { awaitSignalSuspending as Ne, step as A } from "@voltro/workflow";
12
+ import { defineTool as j, estimateCostUsd as Pe, gatewayCostUsd as Fe, generateImage as Ie, generateObject as Le, generateObjectWithTools as Re, generateSpeech as ze, generateText as M, generateVideo as Be } from "@voltro/ai";
13
13
  //#region src/table.ts
14
- var I = ye("_voltro_ai_flows", {
15
- id: ve({ prefix: "aifl" }),
14
+ var N = ke("_voltro_ai_flows", {
15
+ id: Ee({ prefix: "aifl" }),
16
16
  name: O(),
17
17
  description: O().nullable(),
18
18
  mode: O().default("deterministic"),
@@ -25,15 +25,16 @@ var I = ye("_voltro_ai_flows", {
25
25
  inputSchema: E().nullable(),
26
26
  chainTo: E().nullable(),
27
27
  cadence: E().nullable(),
28
- isEnabled: _e().default(!0),
28
+ humanTimeoutMs: T().nullable(),
29
+ isEnabled: Te().default(!0),
29
30
  metadata: E().nullable(),
30
31
  icon: O().nullable(),
31
32
  color: O().nullable(),
32
33
  avatarUrl: O().nullable(),
33
34
  usageCount: T().default(0),
34
35
  ownerId: O().nullable()
35
- }).renamedFrom("ai_flows").with(A(), j(), be()).index(["status"]).index(["visibility"]), L = ye("_voltro_ai_flow_runs", {
36
- id: ve({ prefix: "aifr" }),
36
+ }).renamedFrom("ai_flows").with(Ae(), je(), Me()).index(["status"]).index(["visibility"]), P = ke("_voltro_ai_flow_runs", {
37
+ id: Ee({ prefix: "aifr" }),
37
38
  flowRef: O(),
38
39
  flowName: O().nullable(),
39
40
  mode: O().default("deterministic"),
@@ -47,6 +48,7 @@ var I = ye("_voltro_ai_flows", {
47
48
  totalSteps: T().default(0),
48
49
  humanResponse: E().nullable(),
49
50
  chainPending: E().nullable(),
51
+ chainRefusal: O().nullable(),
50
52
  costMicroUsd: T().default(0),
51
53
  durationMs: T().nullable(),
52
54
  error: O().nullable(),
@@ -58,50 +60,138 @@ var I = ye("_voltro_ai_flows", {
58
60
  sessionName: O().nullable(),
59
61
  ownerId: O().nullable(),
60
62
  metadata: E().nullable()
61
- }).renamedFrom("ai_flow_runs").with(A(), j()).index(["flowRef"]).index(["status"]).index(["requestId"]), Oe = [I, L], ke = /\{\{\s*([\w.-]+)\s*\}\}/g, R = (e) => {
63
+ }).renamedFrom("ai_flow_runs").with(Ae(), je()).index(["flowRef"]).index(["status"]).index(["requestId"]), Ve = [N, P], He = 168, Ue = "VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS", We = 2160, Ge = "VOLTRO_AI_FLOW_RUNS_TTL_HOURS", Ke = 5, qe = "VOLTRO_AI_FLOW_MAX_CHAIN_DEPTH", F = { current: {} }, Je = (e) => {
64
+ F.current = e;
65
+ }, I = () => F.current, Ye = () => {
66
+ F.current = {};
67
+ }, Xe = (e, t) => {
68
+ if (e === void 0 || e.trim() === "") return t * 36e5;
69
+ let n = Number(e);
70
+ return !Number.isFinite(n) || n < 0 ? t * 36e5 : n * 36e5;
71
+ }, Ze = (e) => Number.isFinite(e) && e > 0 ? e : Infinity, Qe = (e) => {
72
+ let t = e.env ?? process.env;
73
+ return Ze(e.step?.timeoutMs ?? e.flow?.humanTimeoutMs ?? e.deps?.humanReviewTimeoutMs ?? I().humanReviewTimeoutMs ?? Xe(t.VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS, 168));
74
+ }, $e = (e) => {
75
+ let t = e?.env ?? process.env, n = Number(t[qe]), r = e?.maxChainDepth ?? I().maxChainDepth ?? (Number.isFinite(n) && n >= 1 ? n : 5);
76
+ return Number.isFinite(r) && r >= 1 ? r : 5;
77
+ }, et = /\{\{\s*([\w.-]+)\s*\}\}/g, L = (e) => {
62
78
  let t = [];
63
- for (let n of e.matchAll(ke)) t.push(n[1]);
79
+ for (let n of e.matchAll(et)) t.push(n[1]);
64
80
  return t;
65
- }, z = (e, t) => e.replace(ke, (e, n) => {
81
+ }, R = (e, t) => e.replace(et, (e, n) => {
66
82
  let r = t[n];
67
83
  return r == null ? "" : typeof r == "string" ? r : JSON.stringify(r);
68
- }), Ae = (e, t) => {
84
+ }), tt = (e, t) => {
69
85
  let n = /* @__PURE__ */ new Set();
70
- for (let r of R(e)) t[r] == null && !n.has(r) && n.add(r);
86
+ for (let r of L(e)) t[r] == null && !n.has(r) && n.add(r);
71
87
  return [...n];
72
- }, B = /* @__PURE__ */ new Map(), V = (e) => {
88
+ }, z = (e) => {
89
+ let t = [], n;
90
+ if (e.forEach((e, r) => {
91
+ let i = e.group;
92
+ if (i !== void 0 && n !== void 0 && n.group === i) {
93
+ n.steps.push({
94
+ index: r,
95
+ step: e
96
+ });
97
+ return;
98
+ }
99
+ n !== void 0 && t.push({
100
+ ...n.group === void 0 ? {} : { group: n.group },
101
+ steps: n.steps
102
+ }), n = {
103
+ ...i === void 0 ? {} : { group: i },
104
+ steps: [{
105
+ index: r,
106
+ step: e
107
+ }]
108
+ };
109
+ }), n !== void 0) {
110
+ let e = n;
111
+ t.push({
112
+ ...e.group === void 0 ? {} : { group: e.group },
113
+ steps: e.steps
114
+ });
115
+ }
116
+ return t;
117
+ }, nt = (e) => {
118
+ let t = /* @__PURE__ */ new Map();
119
+ for (let n of e) n.group !== void 0 && t.set(n.group, (t.get(n.group) ?? 0) + 1);
120
+ return [...t.entries()].filter(([, e]) => e > 1).map(([e]) => e).sort();
121
+ }, B = /* @__PURE__ */ new Map(), rt = (e) => {
73
122
  B.set(e.name, e);
74
- }, H = (e) => B.get(e), U = () => [...B.values()], je = () => B.clear(), W = (e) => e, Me = C.Struct({
123
+ }, it = (e) => B.get(e), at = () => [...B.values()], ot = () => B.clear(), V = (e) => typeof e == "object" && e && !Array.isArray(e) ? e : void 0, H = (e) => Array.isArray(e) ? e : void 0, st = (e) => {
124
+ switch (e) {
125
+ case "string": return C.String;
126
+ case "number": return C.Number;
127
+ case "integer": return C.Int;
128
+ case "boolean": return C.Boolean;
129
+ case "null": return C.Null;
130
+ default: return C.Unknown;
131
+ }
132
+ }, U = (e, t) => {
133
+ let n = typeof t.description == "string" ? t.description : void 0, r = typeof t.title == "string" ? t.title : void 0;
134
+ return n === void 0 && r === void 0 ? e : e.annotations({
135
+ ...n === void 0 ? {} : { description: n },
136
+ ...r === void 0 ? {} : { title: r }
137
+ });
138
+ }, ct = (e) => e.length === 0 ? C.Unknown : e.length === 1 ? e[0] : C.Union(...e), lt = () => C.Record({
139
+ key: C.String,
140
+ value: C.Unknown
141
+ }), W = (e) => {
142
+ let t = V(e);
143
+ if (t === void 0) return C.Unknown;
144
+ if ("const" in t) return U(C.Literal(t.const), t);
145
+ let n = H(t.enum);
146
+ if (n !== void 0 && n.length > 0) return U(C.Literal(...n), t);
147
+ let r = H(t.anyOf) ?? H(t.oneOf);
148
+ if (r !== void 0) return U(ct(r.map(W)), t);
149
+ let i = t.type, a = typeof i == "string" ? [i] : H(i)?.filter((e) => typeof e == "string") ?? [], o = t.nullable === !0 || a.includes("null"), s = a.find((e) => e !== "null"), c = s === "object" || s === void 0 && t.properties !== void 0 ? ut(t) : s === "array" || s === void 0 && t.items !== void 0 ? C.Array(W(t.items)) : s === void 0 ? C.Unknown : st(s);
150
+ return U(o ? C.NullOr(c) : c, t);
151
+ }, ut = (e) => {
152
+ let t = V(e.properties);
153
+ if (t === void 0) return lt();
154
+ let n = new Set((H(e.required) ?? []).filter((e) => typeof e == "string")), r = {};
155
+ for (let [e, i] of Object.entries(t)) {
156
+ let t = W(i);
157
+ r[e] = n.has(e) ? t : C.optional(t);
158
+ }
159
+ return C.Struct(r);
160
+ }, dt = (e) => {
161
+ let t = V(e);
162
+ return t === void 0 || Object.keys(t).length === 0 ? lt() : W(t);
163
+ }, G = (e) => e, ft = C.Struct({
75
164
  value: C.optional(C.Unknown),
76
165
  text: C.optional(C.String),
77
166
  url: C.optional(C.String),
78
167
  costMicroUsd: C.optional(C.Number),
79
168
  requestId: C.optional(C.String),
80
169
  error: C.optional(C.String)
81
- }), G = () => (/* @__PURE__ */ new Date()).toISOString(), Ne = (e) => Math.round(e * 1e6), K = (e, t) => e.resolveModel?.(t) ?? K(e, t), q = (e, t, n) => {
82
- let r = Se(t);
83
- return typeof r == "number" ? Ne(r) : P(e, { model: n ?? "unknown" }).costMicroUsd ?? 0;
84
- }, J = (e, t, n) => S.promise(() => e.store.update(L.tableName, t, n).then(() => void 0)).pipe(S.catchAllCause(() => S.void)), Pe = (e, t) => S.promise(async () => (await e.store.query(D(L).where(w("id", t)).descriptor))[0]?.status === "cancelled").pipe(S.catchAllCause(() => S.succeed(!1))), Y = (e, t) => S.gen(function* () {
85
- let n = H(t);
170
+ }), K = () => (/* @__PURE__ */ new Date()).toISOString(), pt = (e) => Math.round(e * 1e6), q = (e, t) => e.resolveModel?.(t) ?? q(e, t), J = (e, t, n) => {
171
+ let r = Fe(t);
172
+ return typeof r == "number" ? pt(r) : Pe(e, { model: n ?? "unknown" }).costMicroUsd ?? 0;
173
+ }, Y = (e, t, n) => S.promise(() => e.store.update(P.tableName, t, n).then(() => void 0)).pipe(S.catchAllCause(() => S.void)), mt = (e, t) => S.promise(async () => (await e.store.query(D(P).where(w("id", t)).descriptor))[0]?.status === "cancelled").pipe(S.catchAllCause(() => S.succeed(!1))), X = (e, t) => S.gen(function* () {
174
+ let n = it(t);
86
175
  if (n) return n;
87
- let r = (yield* S.promise(() => e.store.query(D(I).where(w("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* S.fail(new fe({
176
+ let i = (yield* S.promise(() => e.store.query(D(N).where(w("id", t)).descriptor)))[0];
177
+ return i ? r({
178
+ name: i.name ?? t,
179
+ mode: i.mode,
180
+ steps: i.steps ?? [],
181
+ maxSteps: i.maxSteps ?? null,
182
+ brief: i.inputSchema ?? [],
183
+ orchestratorModel: i.orchestratorModel ?? null,
184
+ orchestratorInstructions: i.orchestratorInstructions ?? null,
185
+ chain: i.chainTo ?? null,
186
+ cadence: i.cadence ?? null,
187
+ humanTimeoutMs: i.humanTimeoutMs ?? null
188
+ }) : yield* S.fail(new ve({
99
189
  flowRef: t,
100
190
  message: `no flow registered or stored for "${t}"`
101
191
  }));
102
- }), Fe = (e, t, n, r, i) => S.gen(function* () {
103
- let e = z(n.prompt ?? "", r), a = Ae(n.prompt ?? "", r);
104
- if (a.length > 0) return { error: new ue({
192
+ }), ht = (e, t, n, r, i) => S.gen(function* () {
193
+ let e = R(n.prompt ?? "", r), a = tt(n.prompt ?? "", r);
194
+ if (a.length > 0) return { error: new ge({
105
195
  stepId: n.id,
106
196
  unresolvedRef: a[0],
107
197
  message: `step "${n.id}" references unresolved {{${a[0]}}}`
@@ -118,7 +208,7 @@ var I = ye("_voltro_ai_flows", {
118
208
  capability: "resolveAgent",
119
209
  message: "no agent resolver configured"
120
210
  }).message };
121
- let r = yield* W(t.resolveAgent(n.agentRef)).pipe(S.map((e) => ({
211
+ let r = yield* G(t.resolveAgent(n.agentRef)).pipe(S.map((e) => ({
122
212
  ok: !0,
123
213
  a: e
124
214
  })), S.catchAll((e) => S.succeed({
@@ -126,10 +216,10 @@ var I = ye("_voltro_ai_flows", {
126
216
  e
127
217
  })));
128
218
  if (!r.ok) return { error: r.e.message };
129
- let i = yield* F({
219
+ let i = yield* M({
130
220
  system: r.a.system,
131
221
  prompt: e,
132
- provider: K(t, r.a.model)
222
+ provider: q(t, r.a.model)
133
223
  }).pipe(S.map((e) => ({
134
224
  ok: !0,
135
225
  r: e
@@ -140,17 +230,14 @@ var I = ye("_voltro_ai_flows", {
140
230
  return i.ok ? {
141
231
  value: i.r.text,
142
232
  text: i.r.text,
143
- costMicroUsd: q(i.r.usage, i.r.providerMetadata, r.a.model)
233
+ costMicroUsd: J(i.r.usage, i.r.providerMetadata, r.a.model)
144
234
  } : { error: String(i.e.message ?? i.e) };
145
235
  }
146
236
  case "structured": {
147
- let r = n.model ?? t.defaultModels?.text, i = yield* we({
237
+ let r = n.model ?? t.defaultModels?.text, i = yield* Le({
148
238
  prompt: e,
149
- schema: C.Record({
150
- key: C.String,
151
- value: C.Unknown
152
- }),
153
- ...r ? { provider: K(t, r) } : {}
239
+ schema: dt(n.schema),
240
+ ...r ? { provider: q(t, r) } : {}
154
241
  }).pipe(S.map((e) => ({
155
242
  ok: !0,
156
243
  r: e
@@ -161,15 +248,15 @@ var I = ye("_voltro_ai_flows", {
161
248
  return i.ok ? {
162
249
  value: i.r.object,
163
250
  text: JSON.stringify(i.r.object, null, 2),
164
- costMicroUsd: q(i.r.usage, i.r.providerMetadata, r)
251
+ costMicroUsd: J(i.r.usage, i.r.providerMetadata, r)
165
252
  } : { error: String(i.e.message ?? i.e) };
166
253
  }
167
254
  case "generate": {
168
255
  let r = n.modality ?? "text";
169
256
  if (r === "text") {
170
- let r = n.model ?? t.defaultModels?.text, i = yield* F({
257
+ let r = n.model ?? t.defaultModels?.text, i = yield* M({
171
258
  prompt: e,
172
- ...r ? { provider: K(t, r) } : {}
259
+ ...r ? { provider: q(t, r) } : {}
173
260
  }).pipe(S.map((e) => ({
174
261
  ok: !0,
175
262
  r: e
@@ -180,14 +267,14 @@ var I = ye("_voltro_ai_flows", {
180
267
  return i.ok ? {
181
268
  value: i.r.text,
182
269
  text: i.r.text,
183
- costMicroUsd: q(i.r.usage, i.r.providerMetadata, r)
270
+ costMicroUsd: J(i.r.usage, i.r.providerMetadata, r)
184
271
  } : { error: String(i.e.message ?? i.e) };
185
272
  }
186
273
  if (!t.generateMedia) return { error: new b({
187
274
  capability: `media:${r}`,
188
275
  message: `no media generator configured for ${r}`
189
276
  }).message };
190
- let a = n.model ?? t.defaultModels?.[r], o = yield* W(t.generateMedia({
277
+ let a = n.model ?? t.defaultModels?.[r], o = yield* G(t.generateMedia({
191
278
  modality: r,
192
279
  ...a ? { model: a } : {},
193
280
  prompt: e,
@@ -209,247 +296,355 @@ var I = ye("_voltro_ai_flows", {
209
296
  }
210
297
  case "human": return { error: new b({
211
298
  capability: "human",
212
- message: "human-in-the-loop steps are not yet wired (task #35)"
299
+ message: "human step reached the step interpreter it should have been parked by the deterministic executor (routing bug)"
213
300
  }).message };
214
301
  default: return { error: `unknown step type: ${String(n.type)}` };
215
302
  }
216
- }), Ie = (e, t, n, r, i, a) => S.gen(function* () {
217
- let o = { ...i }, c = r.steps.map((e, t) => ({
303
+ }), gt = (t, n, r, i, a, o) => S.gen(function* () {
304
+ let s = { ...a }, c = i.steps.map((e, t) => ({
218
305
  id: t,
219
306
  title: e.title ?? `Step ${t + 1}`,
220
307
  type: e.type,
221
308
  status: "pending",
222
309
  ...e.description ? { description: e.description } : {}
223
310
  })), l = 0;
224
- yield* J(e, n, {
311
+ yield* Y(t, r, {
225
312
  status: "running",
226
313
  steps: c,
227
- totalSteps: r.steps.length,
314
+ totalSteps: i.steps.length,
228
315
  currentStep: 0,
229
- startedAt: G()
316
+ startedAt: K()
230
317
  });
231
- for (let [i, u] of r.steps.entries()) {
232
- if (yield* Pe(e, n)) return {
233
- runId: n,
318
+ for (let a of z(i.steps)) {
319
+ if (yield* mt(t, r)) return {
320
+ runId: r,
234
321
  status: "cancelled"
235
322
  };
236
- if (u.type === "human") {
237
- let d = {
238
- mode: u.reviewMode ?? "approve",
239
- ...u.options ? { options: u.options } : {},
240
- prompt: z(u.prompt ?? "", o)
323
+ if (a.steps.length > 1) {
324
+ let i = [];
325
+ for (let { index: t, step: n } of a.steps) {
326
+ if (n.when !== void 0 && !_(n.when, s)) {
327
+ c[t] = {
328
+ ...c[t],
329
+ status: "skipped",
330
+ completedAt: K(),
331
+ skipReason: e(n.when)
332
+ };
333
+ continue;
334
+ }
335
+ i.push({
336
+ index: t,
337
+ step: n
338
+ }), c[t] = {
339
+ ...c[t],
340
+ status: "running",
341
+ startedAt: K()
342
+ };
343
+ }
344
+ yield* Y(t, r, {
345
+ steps: c,
346
+ currentStep: a.steps[0].index
347
+ });
348
+ let u = yield* S.all(i.map(({ index: e, step: i }) => A({
349
+ name: `flow-${e}-${i.id}`,
350
+ input: { index: e },
351
+ success: ft,
352
+ execute: ht(t, n, i, s, {
353
+ runId: r,
354
+ tenantId: o.tenantId
355
+ })
356
+ }).pipe(S.map((t) => ({
357
+ index: e,
358
+ step: i,
359
+ result: t
360
+ })))), { concurrency: "unbounded" }), d = u.find((e) => e.result.error);
361
+ for (let { index: e, step: t, result: n } of u) {
362
+ if (n.error) {
363
+ c[e] = {
364
+ ...c[e],
365
+ status: "failed",
366
+ completedAt: K(),
367
+ errorMessage: n.error
368
+ };
369
+ continue;
370
+ }
371
+ t.outputKey && n.value !== void 0 && (s[t.outputKey] = n.value), l += n.costMicroUsd ?? 0, c[e] = {
372
+ ...c[e],
373
+ status: "succeeded",
374
+ completedAt: K(),
375
+ ...n.text ? { output: { text: n.text } } : {},
376
+ ...n.url ? { url: n.url } : {},
377
+ ...n.requestId ? { requestId: n.requestId } : {},
378
+ ...n.costMicroUsd ? { costMicroUsd: n.costMicroUsd } : {}
379
+ };
380
+ }
381
+ if (d !== void 0) return yield* Y(t, r, {
382
+ steps: c,
383
+ status: "failed",
384
+ errorMessage: d.result.error,
385
+ completedAt: K(),
386
+ costMicroUsd: l
387
+ }), {
388
+ runId: r,
389
+ status: "failed"
241
390
  };
242
- c[i] = {
243
- ...c[i],
391
+ yield* Y(t, r, {
392
+ steps: c,
393
+ currentStep: a.steps[a.steps.length - 1].index + 1,
394
+ costMicroUsd: l
395
+ });
396
+ continue;
397
+ }
398
+ let { index: u, step: f } = a.steps[0];
399
+ if (f.when !== void 0 && !_(f.when, s)) {
400
+ c[u] = {
401
+ ...c[u],
402
+ status: "skipped",
403
+ completedAt: K(),
404
+ skipReason: e(f.when)
405
+ }, yield* Y(t, r, {
406
+ steps: c,
407
+ currentStep: u + 1
408
+ });
409
+ continue;
410
+ }
411
+ if (f.type === "human") {
412
+ let e = {
413
+ mode: f.reviewMode ?? "approve",
414
+ ...f.options ? { options: f.options } : {},
415
+ prompt: R(f.prompt ?? "", s)
416
+ };
417
+ c[u] = {
418
+ ...c[u],
244
419
  status: "waiting",
245
- startedAt: G(),
246
- review: d
247
- }, yield* J(e, n, {
420
+ startedAt: K(),
421
+ review: e
422
+ }, yield* Y(t, r, {
248
423
  steps: c,
249
424
  status: "waiting",
250
- currentStep: i
251
- }), t.onEvent && (yield* W(t.onEvent({
425
+ currentStep: u
426
+ }), n.onEvent && (yield* G(n.onEvent({
252
427
  kind: "review-needed",
253
- runId: n,
254
- flowName: r.name,
255
- ownerId: a.ownerId,
256
- source: a.source
428
+ runId: r,
429
+ flowName: i.name,
430
+ ownerId: o.ownerId,
431
+ source: o.source
257
432
  })).pipe(S.catchAllCause(() => S.void)));
258
- let f = yield* xe(e, {
259
- name: y,
260
- schema: s
433
+ let a = Qe({
434
+ step: f,
435
+ flow: i,
436
+ deps: n
437
+ }), p = yield* Ne(t, {
438
+ name: y(u),
439
+ schema: d,
440
+ timeoutMs: a
261
441
  }).pipe(S.map((e) => ({
262
442
  ok: !0,
263
443
  a: e
264
- })), S.catchAll((e) => S.succeed({
444
+ })), S.catchAllCause((e) => Se.isInterruptedOnly(e) ? S.failCause(e) : S.succeed({
265
445
  ok: !1,
266
- e
446
+ cause: e
267
447
  })));
268
- if (!f.ok) return c[i] = {
269
- ...c[i],
270
- status: "failed",
271
- completedAt: G(),
272
- errorMessage: "human review timed out or failed to decode"
273
- }, yield* J(e, n, {
274
- steps: c,
275
- status: "failed",
276
- errorMessage: "human review timed out",
277
- completedAt: G(),
278
- costMicroUsd: l
279
- }), {
280
- runId: n,
281
- status: "failed"
282
- };
283
- let p = f.a;
284
- if (p.decision === "reject") return c[i] = {
285
- ...c[i],
448
+ if (!p.ok) {
449
+ let e = Number.isFinite(a) ? `human review timed out after ${a}ms` : "human review failed";
450
+ return c[u] = {
451
+ ...c[u],
452
+ status: "failed",
453
+ completedAt: K(),
454
+ errorMessage: e
455
+ }, yield* Y(t, r, {
456
+ steps: c,
457
+ status: "failed",
458
+ errorMessage: e,
459
+ completedAt: K(),
460
+ costMicroUsd: l
461
+ }), {
462
+ runId: r,
463
+ status: "failed"
464
+ };
465
+ }
466
+ let m = p.a;
467
+ if (m.decision === "reject") return c[u] = {
468
+ ...c[u],
286
469
  status: "failed",
287
- completedAt: G(),
470
+ completedAt: K(),
288
471
  errorMessage: "rejected by reviewer"
289
- }, yield* J(e, n, {
472
+ }, yield* Y(t, r, {
290
473
  steps: c,
291
474
  status: "cancelled",
292
- completedAt: G(),
475
+ completedAt: K(),
293
476
  costMicroUsd: l
294
477
  }), {
295
- runId: n,
478
+ runId: r,
296
479
  status: "cancelled"
297
480
  };
298
- u.outputKey && (o[u.outputKey] = p.value ?? p.text ?? p.decision ?? !0), c[i] = {
299
- ...c[i],
481
+ f.outputKey && (s[f.outputKey] = m.value ?? m.text ?? m.decision ?? !0), c[u] = {
482
+ ...c[u],
300
483
  status: "succeeded",
301
- completedAt: G(),
302
- output: { text: String(p.text ?? p.value ?? p.decision ?? "approved") }
303
- }, yield* J(e, n, {
484
+ completedAt: K(),
485
+ output: { text: String(m.text ?? m.value ?? m.decision ?? "approved") }
486
+ }, yield* Y(t, r, {
304
487
  steps: c,
305
488
  status: "running",
306
- currentStep: i + 1
489
+ currentStep: u + 1
307
490
  });
308
491
  continue;
309
492
  }
310
- c[i] = {
311
- ...c[i],
493
+ c[u] = {
494
+ ...c[u],
312
495
  status: "running",
313
- startedAt: G()
314
- }, yield* J(e, n, {
496
+ startedAt: K()
497
+ }, yield* Y(t, r, {
315
498
  steps: c,
316
- currentStep: i
499
+ currentStep: u
317
500
  });
318
- let d = yield* M({
319
- name: `flow-${i}-${u.id}`,
320
- input: { index: i },
321
- success: Me,
322
- execute: Fe(e, t, u, o, {
323
- runId: n,
324
- tenantId: a.tenantId
501
+ let p = yield* A({
502
+ name: `flow-${u}-${f.id}`,
503
+ input: { index: u },
504
+ success: ft,
505
+ execute: ht(t, n, f, s, {
506
+ runId: r,
507
+ tenantId: o.tenantId
325
508
  })
326
509
  });
327
- if (d.error) return c[i] = {
328
- ...c[i],
510
+ if (p.error) return c[u] = {
511
+ ...c[u],
329
512
  status: "failed",
330
- completedAt: G(),
331
- errorMessage: d.error
332
- }, yield* J(e, n, {
513
+ completedAt: K(),
514
+ errorMessage: p.error
515
+ }, yield* Y(t, r, {
333
516
  steps: c,
334
517
  status: "failed",
335
- errorMessage: d.error,
336
- completedAt: G(),
518
+ errorMessage: p.error,
519
+ completedAt: K(),
337
520
  costMicroUsd: l
338
521
  }), {
339
- runId: n,
522
+ runId: r,
340
523
  status: "failed"
341
524
  };
342
- u.outputKey && d.value !== void 0 && (o[u.outputKey] = d.value), l += d.costMicroUsd ?? 0, c[i] = {
343
- ...c[i],
525
+ f.outputKey && p.value !== void 0 && (s[f.outputKey] = p.value), l += p.costMicroUsd ?? 0, c[u] = {
526
+ ...c[u],
344
527
  status: "succeeded",
345
- completedAt: G(),
346
- ...d.text ? { output: { text: d.text } } : {},
347
- ...d.url ? { url: d.url } : {},
348
- ...d.requestId ? { requestId: d.requestId } : {},
349
- ...d.costMicroUsd ? { costMicroUsd: d.costMicroUsd } : {}
350
- }, yield* J(e, n, {
528
+ completedAt: K(),
529
+ ...p.text ? { output: { text: p.text } } : {},
530
+ ...p.url ? { url: p.url } : {},
531
+ ...p.requestId ? { requestId: p.requestId } : {},
532
+ ...p.costMicroUsd ? { costMicroUsd: p.costMicroUsd } : {}
533
+ }, yield* Y(t, r, {
351
534
  steps: c,
352
- currentStep: i + 1,
535
+ currentStep: u + 1,
353
536
  costMicroUsd: l
354
537
  });
355
538
  }
356
539
  let u = {};
357
- for (let e of r.steps) e.outputKey && o[e.outputKey] !== void 0 && (u[e.outputKey] = o[e.outputKey]);
358
- return yield* J(e, n, {
540
+ for (let e of i.steps) e.outputKey && s[e.outputKey] !== void 0 && (u[e.outputKey] = s[e.outputKey]);
541
+ return yield* Y(t, r, {
359
542
  status: "succeeded",
360
543
  output: u,
361
- completedAt: G(),
544
+ completedAt: K(),
362
545
  costMicroUsd: l
363
546
  }), {
364
- runId: n,
547
+ runId: r,
365
548
  status: "succeeded",
366
549
  output: u
367
550
  };
368
- }), Le = (e, t, n, r, i, a) => S.gen(function* () {
369
- let o = n.chain;
370
- if (!o || o.flowRef === n.name || o.flowRef === a.flowRef) return;
371
- let s = {
551
+ }), _t = (e, t, n, r, i, a, o) => S.gen(function* () {
552
+ let s = n.chain;
553
+ if (!s) return;
554
+ let c = [...a.chainPath ?? [], a.flowRef];
555
+ if (s.flowRef === n.name || s.flowRef === a.flowRef) return;
556
+ if (c.includes(s.flowRef)) {
557
+ yield* Y(e, t, { chainRefusal: `chain to "${s.flowRef}" refused — it is already in this run's chain (${c.join(" → ")}), which would loop` });
558
+ return;
559
+ }
560
+ let l = $e(o);
561
+ if (c.length >= l) {
562
+ yield* Y(e, t, { chainRefusal: `chain to "${s.flowRef}" refused — depth ${c.length} reached the limit of ${l} (${c.join(" → ")})` });
563
+ return;
564
+ }
565
+ let u = {
372
566
  ...r,
373
567
  ...i
374
- }, c = {};
375
- for (let e of o.mappings) e.sourceKey in s && (c[e.targetKey] = s[e.sourceKey]);
376
- if (o.requireConfirmation) {
377
- yield* J(e, t, { chainPending: {
378
- flowRef: o.flowRef,
379
- input: c,
568
+ }, d = {};
569
+ for (let e of s.mappings) e.sourceKey in u && (d[e.targetKey] = u[e.sourceKey]);
570
+ if (s.requireConfirmation) {
571
+ yield* Y(e, t, { chainPending: {
572
+ flowRef: s.flowRef,
573
+ input: d,
380
574
  status: "pending"
381
575
  } });
382
576
  return;
383
577
  }
384
- let l = e.workflows;
385
- if (!l) return;
386
- let u = `${t}--chain`, d = `${a.requestId}--chain`;
578
+ let f = e.workflows;
579
+ if (!f) return;
580
+ let p = `${t}--chain`, m = `${a.requestId}--chain`;
387
581
  yield* S.promise(async () => {
388
582
  try {
389
- await e.store.insert(L.tableName, {
390
- id: u,
391
- flowRef: o.flowRef,
392
- flowName: o.flowRef,
583
+ await e.store.insert(P.tableName, {
584
+ id: p,
585
+ flowRef: s.flowRef,
586
+ flowName: s.flowRef,
393
587
  status: "pending",
394
588
  source: a.source,
395
- requestId: d,
396
- input: c
589
+ requestId: m,
590
+ input: d
397
591
  });
398
592
  } catch {}
399
- await l.child("flow.run", {
400
- runId: u,
401
- flowRef: o.flowRef,
402
- input: c,
593
+ await f.child("flow.run", {
594
+ runId: p,
595
+ flowRef: s.flowRef,
596
+ input: d,
403
597
  source: a.source,
404
- requestId: d
598
+ requestId: m,
599
+ chainPath: c
405
600
  });
406
601
  }).pipe(S.catchAllCause(() => S.void));
407
- }), 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) => {
602
+ }), vt = (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"), yt = (e) => {
408
603
  let t = Object.entries(e);
409
604
  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");
410
- }, Be = (e) => [
605
+ }, bt = (e) => [
411
606
  e.orchestrator?.instructions ?? "You are an orchestrator that uses the available tools to produce a bundled result.",
412
- Re(e),
607
+ vt(e),
413
608
  "When finished, emit a JSON object mapping each deliverable name (outputKey) to its value."
414
- ].filter(Boolean).join("\n\n"), Ve = C.Struct({
609
+ ].filter(Boolean).join("\n\n"), xt = C.Struct({
415
610
  object: C.Record({
416
611
  key: C.String,
417
612
  value: C.Unknown
418
613
  }),
419
614
  planCostMicroUsd: C.Number,
420
615
  toolCostMicroUsd: C.Number,
421
- steps: C.Array(ie),
616
+ steps: C.Array(fe),
422
617
  error: C.optional(C.String)
423
- }), He = (e, t, n, r, i, a, o) => S.gen(function* () {
424
- yield* J(e, n, {
618
+ }), St = (e, t, n, r, i, a, o) => S.gen(function* () {
619
+ yield* Y(e, n, {
425
620
  status: "running",
426
- startedAt: G(),
621
+ startedAt: K(),
427
622
  totalSteps: r.steps.length
428
623
  });
429
- let s = yield* M({
624
+ let s = yield* A({
430
625
  name: "flow-agentic",
431
626
  input: { flowRef: r.name },
432
- success: Ve,
627
+ success: xt,
433
628
  execute: S.gen(function* () {
434
629
  let s = [], c = 0, l = (e) => {
435
630
  let t = s.length;
436
631
  return s.push({
437
632
  id: t,
438
633
  status: "running",
439
- startedAt: G(),
634
+ startedAt: K(),
440
635
  ...e
441
636
  }), t;
442
637
  }, u = (e, t) => {
443
638
  s[e] = {
444
639
  ...s[e],
445
- completedAt: G(),
640
+ completedAt: K(),
446
641
  ...t
447
642
  };
448
- }, d = () => J(e, n, {
643
+ }, d = () => Y(e, n, {
449
644
  steps: s,
450
645
  currentStep: s.length,
451
646
  costMicroUsd: c
452
- }), f = N({
647
+ }), f = j({
453
648
  name: "run_agent",
454
649
  description: "Delegate a text task to an allowed sub-agent. Returns the agent's text.",
455
650
  input: C.Struct({
@@ -465,7 +660,7 @@ var I = ye("_voltro_ai_flows", {
465
660
  status: "failed",
466
661
  errorMessage: "no agent resolver configured"
467
662
  }), yield* d(), "ERROR: no agent resolver configured";
468
- let i = yield* W(t.resolveAgent(e)).pipe(S.map((e) => ({
663
+ let i = yield* G(t.resolveAgent(e)).pipe(S.map((e) => ({
469
664
  ok: !0,
470
665
  a: e
471
666
  })), S.catchAll((e) => S.succeed({
@@ -476,10 +671,10 @@ var I = ye("_voltro_ai_flows", {
476
671
  status: "failed",
477
672
  errorMessage: i.e.message
478
673
  }), yield* d(), `ERROR: ${i.e.message}`;
479
- let a = yield* F({
674
+ let a = yield* M({
480
675
  system: i.a.system,
481
676
  prompt: n,
482
- provider: K(t, i.a.model)
677
+ provider: q(t, i.a.model)
483
678
  }).pipe(S.map((e) => ({
484
679
  ok: !0,
485
680
  r: e
@@ -494,14 +689,14 @@ var I = ye("_voltro_ai_flows", {
494
689
  errorMessage: e
495
690
  }), yield* d(), `ERROR: ${e}`;
496
691
  }
497
- let o = q(a.r.usage, a.r.providerMetadata, i.a.model);
692
+ let o = J(a.r.usage, a.r.providerMetadata, i.a.model);
498
693
  return c += o, u(r, {
499
694
  status: "succeeded",
500
695
  output: { text: a.r.text },
501
696
  costMicroUsd: o
502
697
  }), yield* d(), a.r.text;
503
698
  })
504
- }), p = N({
699
+ }), p = j({
505
700
  name: "generate_media",
506
701
  description: "Generate an image, video, or audio artifact. Returns the hosted URL.",
507
702
  input: C.Struct({
@@ -518,7 +713,7 @@ var I = ye("_voltro_ai_flows", {
518
713
  status: "failed",
519
714
  errorMessage: `no media generator for ${e}`
520
715
  }), yield* d(), `ERROR: no media generator configured for ${e}`;
521
- let s = yield* W(t.generateMedia({
716
+ let s = yield* G(t.generateMedia({
522
717
  modality: e,
523
718
  prompt: r,
524
719
  ...i ? { model: i } : {},
@@ -543,7 +738,7 @@ var I = ye("_voltro_ai_flows", {
543
738
  errorMessage: s.e.message
544
739
  }), yield* d(), `ERROR: ${s.e.message}`);
545
740
  })
546
- }), ee = N({
741
+ }), m = j({
547
742
  name: "pick_structured",
548
743
  description: "Produce a JSON object for a task. Returns the object.",
549
744
  input: C.Struct({
@@ -556,13 +751,13 @@ var I = ye("_voltro_ai_flows", {
556
751
  type: "structured"
557
752
  });
558
753
  yield* d();
559
- let i = yield* we({
754
+ let i = yield* Le({
560
755
  prompt: e,
561
756
  schema: C.Record({
562
757
  key: C.String,
563
758
  value: C.Unknown
564
759
  }),
565
- ...n ? { provider: K(t, n) } : {}
760
+ ...n ? { provider: q(t, n) } : {}
566
761
  }).pipe(S.map((e) => ({
567
762
  ok: !0,
568
763
  r: e
@@ -577,16 +772,16 @@ var I = ye("_voltro_ai_flows", {
577
772
  errorMessage: e
578
773
  }), yield* d(), { error: e };
579
774
  }
580
- let a = q(i.r.usage, i.r.providerMetadata, n);
775
+ let a = J(i.r.usage, i.r.providerMetadata, n);
581
776
  return c += a, u(r, {
582
777
  status: "succeeded",
583
778
  output: { text: JSON.stringify(i.r.object) },
584
779
  costMicroUsd: a
585
780
  }), yield* d(), i.r.object;
586
781
  })
587
- }), m = t.memoryPrefix ? yield* W(t.memoryPrefix(a)).pipe(S.catchAll(() => S.succeed(""))) : "", h = yield* Te({
588
- system: m ? `${m}\n\n${Be(r)}` : Be(r),
589
- prompt: ze(i),
782
+ }), h = t.memoryPrefix ? yield* G(t.memoryPrefix(a)).pipe(S.catchAll(() => S.succeed(""))) : "", g = yield* Re({
783
+ system: h ? `${h}\n\n${bt(r)}` : bt(r),
784
+ prompt: yt(i),
590
785
  schema: C.Record({
591
786
  key: C.String,
592
787
  value: C.Unknown
@@ -594,10 +789,10 @@ var I = ye("_voltro_ai_flows", {
594
789
  tools: {
595
790
  run_agent: f,
596
791
  generate_media: p,
597
- pick_structured: ee
792
+ pick_structured: m
598
793
  },
599
794
  maxSteps: r.maxSteps,
600
- ...r.orchestrator?.model ? { provider: K(t, r.orchestrator.model) } : {}
795
+ ...r.orchestrator?.model ? { provider: q(t, r.orchestrator.model) } : {}
601
796
  }).pipe(S.map((e) => ({
602
797
  ok: !0,
603
798
  r: e
@@ -605,9 +800,9 @@ var I = ye("_voltro_ai_flows", {
605
800
  ok: !1,
606
801
  e
607
802
  })));
608
- return h.ok ? {
609
- object: h.r.object,
610
- planCostMicroUsd: q(h.r.usage, h.r.providerMetadata, r.orchestrator?.model),
803
+ return g.ok ? {
804
+ object: g.r.object,
805
+ planCostMicroUsd: J(g.r.usage, g.r.providerMetadata, r.orchestrator?.model),
611
806
  toolCostMicroUsd: c,
612
807
  steps: s
613
808
  } : {
@@ -615,64 +810,64 @@ var I = ye("_voltro_ai_flows", {
615
810
  planCostMicroUsd: 0,
616
811
  toolCostMicroUsd: c,
617
812
  steps: s,
618
- error: String(h.e.message ?? h.e)
813
+ error: String(g.e.message ?? g.e)
619
814
  };
620
815
  })
621
816
  }), c = s.planCostMicroUsd + s.toolCostMicroUsd;
622
- return s.error ? (yield* J(e, n, {
817
+ return s.error ? (yield* Y(e, n, {
623
818
  status: "failed",
624
819
  steps: s.steps,
625
820
  errorMessage: s.error,
626
- completedAt: G(),
821
+ completedAt: K(),
627
822
  costMicroUsd: c
628
823
  }), {
629
824
  runId: n,
630
825
  status: "failed"
631
- }) : (yield* J(e, n, {
826
+ }) : (yield* Y(e, n, {
632
827
  status: "succeeded",
633
828
  steps: s.steps,
634
829
  output: s.object,
635
- completedAt: G(),
830
+ completedAt: K(),
636
831
  costMicroUsd: c
637
832
  }), {
638
833
  runId: n,
639
834
  status: "succeeded",
640
835
  output: s.object
641
836
  });
642
- }), Ue = (e, t = {}) => (n, r) => S.gen(function* () {
643
- let { runId: r, flowRef: i, input: a } = n, o = yield* M({
837
+ }), Ct = (e, t = {}) => (n, r) => S.gen(function* () {
838
+ let { runId: r, flowRef: i, input: a } = n, o = yield* A({
644
839
  name: "flow-0-resolve",
645
840
  input: { flowRef: i },
646
841
  success: C.Struct({
647
842
  ir: C.Unknown,
648
843
  error: C.optional(C.String)
649
844
  }),
650
- execute: Y(e, i).pipe(S.map((e) => ({ ir: e })), S.catchAll((e) => S.succeed({
845
+ execute: X(e, i).pipe(S.map((e) => ({ ir: e })), S.catchAll((e) => S.succeed({
651
846
  ir: void 0,
652
847
  error: e.message
653
848
  })))
654
849
  });
655
- if (o.error || !o.ir) return yield* J(e, r, {
850
+ if (o.error || !o.ir) return yield* Y(e, r, {
656
851
  status: "failed",
657
852
  errorMessage: o.error ?? "flow not found",
658
- completedAt: G()
853
+ completedAt: K()
659
854
  }), {
660
855
  runId: r,
661
856
  status: "failed"
662
857
  };
663
- let s = o.ir, c = (yield* S.promise(() => e.store.query(D(L).where(w("id", r)).descriptor)).pipe(S.catchAllCause(() => S.succeed([]))))[0], l = c?.ownerId ?? null, u = c?.tenantId ?? null, d = s.mode === "agentic" ? yield* He(e, t, r, s, a, l, u) : yield* Ie(e, t, r, s, a, {
858
+ let s = o.ir, c = (yield* S.promise(() => e.store.query(D(P).where(w("id", r)).descriptor)).pipe(S.catchAllCause(() => S.succeed([]))))[0], l = c?.ownerId ?? null, u = c?.tenantId ?? null, d = s.mode === "agentic" ? yield* St(e, t, r, s, a, l, u) : yield* gt(e, t, r, s, a, {
664
859
  ownerId: l,
665
860
  tenantId: u,
666
861
  source: n.source
667
862
  });
668
- return d.status === "succeeded" && s.chain && (yield* Le(e, r, s, a, d.output ?? {}, n)), t.onEvent && (d.status === "succeeded" || d.status === "failed") && (yield* W(t.onEvent({
863
+ return d.status === "succeeded" && s.chain && (yield* _t(e, r, s, a, d.output ?? {}, n, t)), t.onEvent && (d.status === "succeeded" || d.status === "failed") && (yield* G(t.onEvent({
669
864
  kind: d.status,
670
865
  runId: r,
671
866
  flowName: s.name,
672
867
  ownerId: l,
673
868
  source: n.source
674
869
  })).pipe(S.catchAllCause(() => S.void))), d;
675
- }), We = {
870
+ }), wt = {
676
871
  text: (e) => ({
677
872
  type: "generate",
678
873
  modality: "text",
@@ -699,36 +894,43 @@ var I = ye("_voltro_ai_flows", {
699
894
  type: "human",
700
895
  ...e
701
896
  })
702
- }, Ge = (e) => e.map((e, t) => "id" in e && e.id ? e : {
897
+ }, Tt = (e) => e.map((e, t) => "id" in e && e.id ? e : {
703
898
  id: `step-${t}`,
704
899
  ...e
705
- }), Ke = (e) => {
706
- let t = new Set(e.brief.map((e) => e.key)), n = [];
707
- for (let r of e.steps) {
708
- for (let e of R(r.prompt ?? "")) t.has(e) || n.push(`step "${r.id}" references {{${e}}} which is not a brief field or a prior step outputKey`);
709
- r.outputKey && t.add(_(r.outputKey));
900
+ }), Et = (e) => {
901
+ let t = [], r = z(e.steps);
902
+ for (let e of nt(r)) t.push(`group "${e}" is not contiguous — only CONSECUTIVE steps sharing a group run concurrently, so this would execute as two separate fan-outs`);
903
+ let i = new Set(e.brief.map((e) => e.key));
904
+ for (let e of r) {
905
+ for (let { step: n } of e.steps) {
906
+ 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`);
907
+ for (let r of L(n.prompt ?? "")) i.has(r) || t.push(e.steps.length > 1 ? `step "${n.id}" references {{${r}}} 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 {{${r}}} which is not a brief field or a prior step outputKey`);
908
+ n.when !== void 0 && !i.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`);
909
+ }
910
+ for (let { step: t } of e.steps) t.outputKey && i.add(n(t.outputKey));
710
911
  }
711
- if (n.length > 0) throw new pe({
912
+ if (t.length > 0) throw new ye({
712
913
  flowRef: e.name,
713
- message: `flow "${e.name}" has ${n.length} unresolved reference(s)`,
714
- issues: n
914
+ message: `flow "${e.name}" has ${t.length} problem(s)`,
915
+ issues: t
715
916
  });
716
- }, qe = (e) => {
717
- let t = g({
917
+ }, Dt = (e) => {
918
+ let t = r({
718
919
  name: e.name,
719
920
  mode: e.mode,
720
- steps: Ge(e.steps),
921
+ steps: Tt(e.steps),
721
922
  maxSteps: e.maxSteps,
722
923
  brief: e.brief,
723
924
  orchestratorModel: e.orchestrator?.model,
724
925
  orchestratorInstructions: e.orchestrator?.instructions,
725
926
  chain: e.chain,
726
- cadence: e.cadence
927
+ cadence: e.cadence,
928
+ humanTimeoutMs: e.humanTimeoutMs
727
929
  });
728
- return Ke(t), V(t), t;
729
- }, X = (e) => String(e).padStart(2, "0"), Je = (e, t) => `cron-${e}-${t.getFullYear()}${X(t.getMonth() + 1)}${X(t.getDate())}-${X(t.getHours())}${X(t.getMinutes())}`, Ye = async (e) => {
930
+ return Et(t), rt(t), t;
931
+ }, Z = (e) => String(e).padStart(2, "0"), Ot = (e, t) => `cron-${e}-${t.getFullYear()}${Z(t.getMonth() + 1)}${Z(t.getDate())}-${Z(t.getHours())}${Z(t.getMinutes())}`, kt = async (e) => {
730
932
  let t = [];
731
- for (let e of U()) e.cadence && (e.cadence.repeats?.length ?? 0) > 0 && t.push({
933
+ for (let e of at()) e.cadence && (e.cadence.repeats?.length ?? 0) > 0 && t.push({
732
934
  flowRef: e.name,
733
935
  cadence: e.cadence,
734
936
  defaultInput: e.cadence.defaultInput ?? {}
@@ -740,11 +942,11 @@ var I = ye("_voltro_ai_flows", {
740
942
  defaultInput: e.cadence.defaultInput ?? {}
741
943
  });
742
944
  return t;
743
- }, Xe = async (e, t = /* @__PURE__ */ new Date()) => {
744
- let n = e.workflows, r = [], i = 0, a = await Ye(e).catch(() => []);
945
+ }, At = async (e, t = /* @__PURE__ */ new Date()) => {
946
+ let n = e.workflows, r = [], i = 0, a = await kt(e).catch(() => []);
745
947
  for (let o of a) {
746
- if (!he(o.cadence, t) || (i += 1, !n)) continue;
747
- let a = Je(o.flowRef, t), s = `run-${a}`;
948
+ if (!xe(o.cadence, t) || (i += 1, !n)) continue;
949
+ let a = Ot(o.flowRef, t), s = `run-${a}`;
748
950
  try {
749
951
  try {
750
952
  await e.store.insert("_voltro_ai_flow_runs", {
@@ -770,17 +972,17 @@ var I = ye("_voltro_ai_flows", {
770
972
  matched: i,
771
973
  started: r
772
974
  };
773
- }, Ze = (e) => ({
975
+ }, jt = (e) => ({
774
976
  name: "gateway",
775
977
  model: e
776
- }), Qe = (e) => Math.round(e * 1e6), Z = (e, t, n) => {
777
- let r = Se(t);
778
- return typeof r == "number" ? Qe(r) : e ? P(e, { model: n ?? "unknown" }).costMicroUsd ?? 0 : 0;
779
- }, $e = (e, t) => (n) => {
780
- let r = n.model, i = (e) => t?.resolveModel?.(e) ?? Ze(e);
978
+ }), Mt = (e) => Math.round(e * 1e6), Nt = (e, t, n) => {
979
+ let r = Fe(t);
980
+ return typeof r == "number" ? Mt(r) : e ? Pe(e, { model: n ?? "unknown" }).costMicroUsd ?? 0 : 0;
981
+ }, Pt = (e, t) => (n) => {
982
+ let r = n.model, i = (e) => t?.resolveModel?.(e) ?? jt(e);
781
983
  return S.gen(function* () {
782
984
  if (n.modality === "image") {
783
- let t = yield* Ce({
985
+ let t = yield* Ie({
784
986
  prompt: n.prompt,
785
987
  ...r ? { provider: i(r) } : {}
786
988
  }), a = t.images[0];
@@ -796,11 +998,11 @@ var I = ye("_voltro_ai_flows", {
796
998
  return {
797
999
  url: o.url,
798
1000
  ...o.refId ? { requestId: o.refId } : {},
799
- costMicroUsd: Z(t.usage, t.providerMetadata, r)
1001
+ costMicroUsd: Nt(t.usage, t.providerMetadata, r)
800
1002
  };
801
1003
  }
802
1004
  if (n.modality === "audio") {
803
- let t = yield* Ee({
1005
+ let t = yield* ze({
804
1006
  text: n.prompt,
805
1007
  ...r ? { provider: i(r) } : {}
806
1008
  }), a = yield* S.promise(() => e.put({
@@ -811,10 +1013,10 @@ var I = ye("_voltro_ai_flows", {
811
1013
  return {
812
1014
  url: a.url,
813
1015
  ...a.refId ? { requestId: a.refId } : {},
814
- costMicroUsd: Z(t.usage, t.providerMetadata, r)
1016
+ costMicroUsd: Nt(t.usage, t.providerMetadata, r)
815
1017
  };
816
1018
  }
817
- let t = yield* De({
1019
+ let t = yield* Be({
818
1020
  prompt: n.prompt,
819
1021
  ...r ? { provider: i(r) } : {},
820
1022
  ...n.params ? { params: n.params } : {}
@@ -832,20 +1034,20 @@ var I = ye("_voltro_ai_flows", {
832
1034
  return {
833
1035
  url: a.url,
834
1036
  ...a.refId ? { requestId: a.refId } : {},
835
- costMicroUsd: Z(t.usage, t.providerMetadata, r)
1037
+ costMicroUsd: Nt(t.usage, t.providerMetadata, r)
836
1038
  };
837
1039
  }).pipe(S.catchAll((e) => e instanceof b ? S.fail(e) : S.fail(new b({
838
1040
  capability: `media:${n.modality}`,
839
1041
  message: String(e.message ?? e)
840
1042
  }))));
841
- }, Q = () => globalThis.crypto?.randomUUID?.() ?? `req-${Date.now().toString(36)}`, et = (e) => e.request?.subject?.id ?? null, $ = (e, t) => S.promise(() => e.store.query(D(L).where(w("id", t)).descriptor)).pipe(S.map((e) => e[0])), tt = (e, t) => S.gen(function* () {
842
- let n = yield* Y(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);
843
- if (i.length > 0) return yield* S.fail(new le({
1043
+ }, Q = () => globalThis.crypto?.randomUUID?.() ?? `req-${Date.now().toString(36)}`, Ft = (e) => e.request?.subject?.id ?? null, $ = (e, t) => S.promise(() => e.store.query(D(P).where(w("id", t)).descriptor)).pipe(S.map((e) => e[0])), It = (e, t) => S.gen(function* () {
1044
+ let n = yield* X(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);
1045
+ if (i.length > 0) return yield* S.fail(new he({
844
1046
  missing: i,
845
1047
  message: `missing required brief field(s): ${i.join(", ")}`
846
1048
  }));
847
1049
  let a = Q(), o = `run-${a}`, s = t.source ?? "manual";
848
- yield* S.promise(() => e.store.insert(L.tableName, {
1050
+ yield* S.promise(() => e.store.insert(P.tableName, {
849
1051
  id: o,
850
1052
  flowRef: t.flowRef,
851
1053
  flowName: n.name,
@@ -854,7 +1056,7 @@ var I = ye("_voltro_ai_flows", {
854
1056
  source: s,
855
1057
  requestId: a,
856
1058
  input: r,
857
- ownerId: et(e)
1059
+ ownerId: Ft(e)
858
1060
  }));
859
1061
  let c = e.workflows;
860
1062
  return c && (yield* S.promise(() => c.start(v, {
@@ -868,14 +1070,14 @@ var I = ye("_voltro_ai_flows", {
868
1070
  requestId: a,
869
1071
  status: "pending"
870
1072
  };
871
- }), nt = (e, t) => S.gen(function* () {
1073
+ }), Lt = (e, t) => S.gen(function* () {
872
1074
  let n = yield* $(e, t.runId);
873
1075
  if (!n) return yield* S.fail(new x({
874
1076
  runId: t.runId,
875
1077
  message: "run not found"
876
1078
  }));
877
1079
  let r = n.requestId ?? Q(), i = n.flowRef, a = n.input ?? {}, o = n.source ?? "manual";
878
- yield* S.promise(() => e.store.update(L.tableName, t.runId, {
1080
+ yield* S.promise(() => e.store.update(P.tableName, t.runId, {
879
1081
  status: "pending",
880
1082
  error: null,
881
1083
  errorMessage: null
@@ -892,8 +1094,8 @@ var I = ye("_voltro_ai_flows", {
892
1094
  requestId: r,
893
1095
  status: "pending"
894
1096
  };
895
- }), rt = (e, t) => S.gen(function* () {
896
- return (yield* $(e, t.runId)) ? (yield* S.promise(() => e.store.update(L.tableName, t.runId, {
1097
+ }), Rt = (e, t) => S.gen(function* () {
1098
+ return (yield* $(e, t.runId)) ? (yield* S.promise(() => e.store.update(P.tableName, t.runId, {
897
1099
  status: "cancelled",
898
1100
  cancelledAt: (/* @__PURE__ */ new Date()).toISOString()
899
1101
  })), {
@@ -903,14 +1105,19 @@ var I = ye("_voltro_ai_flows", {
903
1105
  runId: t.runId,
904
1106
  message: "run not found"
905
1107
  }));
906
- }), it = (e, t) => S.gen(function* () {
1108
+ }), zt = (e) => {
1109
+ let t = e.steps?.find((e) => e.status === "waiting");
1110
+ if (t !== void 0) return t.id;
1111
+ let n = e.currentStep;
1112
+ return typeof n == "number" ? n : 0;
1113
+ }, Bt = (e, t) => S.gen(function* () {
907
1114
  let n = yield* $(e, t.runId);
908
1115
  if (!n) return yield* S.fail(new x({
909
1116
  runId: t.runId,
910
1117
  message: "run not found"
911
1118
  }));
912
1119
  let r = n.status;
913
- if (r !== "waiting") return yield* S.fail(new de({
1120
+ if (r !== "waiting") return yield* S.fail(new _e({
914
1121
  runId: t.runId,
915
1122
  status: r ?? "unknown",
916
1123
  message: `run is "${r}", not awaiting a response`
@@ -919,27 +1126,47 @@ var I = ye("_voltro_ai_flows", {
919
1126
  ...t.response,
920
1127
  respondedAt: (/* @__PURE__ */ new Date()).toISOString()
921
1128
  };
922
- yield* S.promise(() => e.store.update(L.tableName, t.runId, { humanResponse: i }));
923
- let a = e.workflows, o = n.requestId;
1129
+ yield* S.promise(() => e.store.update(P.tableName, t.runId, { humanResponse: i }));
1130
+ let a = e.workflows, o = n.requestId, s = zt(n);
924
1131
  return a && o && (yield* S.promise(() => a.signal({
925
1132
  workflowName: v,
926
1133
  executionId: `flow-run:${o}`
927
- }, y, i)).pipe(S.catchAllCause(() => S.void))), { runId: t.runId };
928
- }), at = (e, t) => S.promise(() => e.store.query(D(I).where(w("id", t.id)).descriptor)).pipe(S.map((e) => e[0])), ot = (e) => S.promise(() => e.store.query(D(I).descriptor)), st = (e, t) => S.promise(() => e.store.insert(I.tableName, {
1134
+ }, y(s), i)).pipe(S.catchAllCause(() => S.void))), {
1135
+ runId: t.runId,
1136
+ stepIndex: s
1137
+ };
1138
+ }), Vt = (e, t) => S.promise(() => e.store.query(D(N).where(w("id", t.id)).descriptor)).pipe(S.map((e) => e[0])), Ht = (e) => S.promise(() => e.store.query(D(N).descriptor)), Ut = (e, t) => S.promise(() => e.store.insert(N.tableName, {
929
1139
  id: t.id ?? `flow-${Q()}`,
930
1140
  ...t
931
- })), ct = (e, t) => S.promise(() => e.store.update(I.tableName, t.id, t.patch)), lt = (e, t) => S.promise(() => e.store.delete(I.tableName, t.id)), ut = (e = {}) => {
932
- let t = e.alias ?? "aiFlows", n = { current: void 0 }, r = (e) => ({
1141
+ })), Wt = (e, t) => S.promise(() => e.store.update(N.tableName, t.id, t.patch)), Gt = (e, t) => S.promise(() => e.store.delete(N.tableName, t.id)), Kt = "aiFlows", qt = (e = {}) => {
1142
+ let t = we({
1143
+ base: Kt,
1144
+ alias: e.alias
1145
+ });
1146
+ Je(e.humanReviewTimeoutMs === void 0 ? {} : { humanReviewTimeoutMs: e.humanReviewTimeoutMs }), Oe({
1147
+ source: "plugin",
1148
+ table: P.tableName,
1149
+ timeColumn: "createdAt",
1150
+ ttlMs: e.runsTtlMs ?? Xe(process.env.VOLTRO_AI_FLOW_RUNS_TTL_HOURS, 2160),
1151
+ envVar: Ge,
1152
+ label: "ai flow runs",
1153
+ where: De("status", [
1154
+ "succeeded",
1155
+ "failed",
1156
+ "cancelled"
1157
+ ])
1158
+ });
1159
+ let n = Math.max(1, e.inspectPageMax ?? 200), r = { current: void 0 }, i = (e) => ({
933
1160
  kind: "json",
934
1161
  data: e
935
- }), i = (e, t) => ({
1162
+ }), a = (e, t) => ({
936
1163
  kind: "json",
937
1164
  status: e,
938
1165
  data: { error: t }
939
- }), a = (e, t) => S.promise(async () => {
940
- let a = n.current;
941
- if (!a) return i(503, "store not bound yet");
942
- let o = await a.query({
1166
+ }), o = (e, t) => S.promise(async () => {
1167
+ let n = r.current;
1168
+ if (!n) return a(503, "store not bound yet");
1169
+ let o = await n.query({
943
1170
  table: e,
944
1171
  predicate: void 0,
945
1172
  order: [],
@@ -947,31 +1174,36 @@ var I = ye("_voltro_ai_flows", {
947
1174
  skip: void 0,
948
1175
  projection: void 0
949
1176
  });
950
- return r({
1177
+ return i({
951
1178
  count: o.length,
952
- rows: o
1179
+ rows: o,
1180
+ take: t
953
1181
  });
954
- }).pipe(S.catchAllCause(() => S.succeed(i(500, "query failed"))));
955
- return ge({
1182
+ }).pipe(S.catchAllCause(() => S.succeed(a(500, "query failed")))), s = (e, t) => {
1183
+ let r = /[?&]take=(\d+)/.exec(e)?.[1], i = r === void 0 ? t : Number(r);
1184
+ return Math.min(n, Math.max(1, Number.isFinite(i) ? i : t));
1185
+ }, c = [{
1186
+ method: "GET",
1187
+ path: "/flows",
1188
+ description: "List flow definitions (`?take=` up to the configured max).",
1189
+ handler: (e) => o("_voltro_ai_flows", s(e.url, Math.min(200, n)))
1190
+ }, {
1191
+ method: "GET",
1192
+ path: "/runs",
1193
+ description: "List recent flow runs (`?take=` up to the configured max).",
1194
+ handler: (e) => o("_voltro_ai_flow_runs", s(e.url, Math.min(100, n)))
1195
+ }];
1196
+ return Ce({
956
1197
  name: t,
1198
+ baseName: Kt,
957
1199
  description: "AI Flows — durable multi-step AI pipelines (deterministic + agentic) with human-in-the-loop, chaining, and cadence. Code-first (defineFlow) or data-driven.",
958
1200
  permissions: ["store:write", "inspect:read"],
959
- extendSchema: { tables: Oe },
960
- inspectEndpoints: [{
961
- method: "GET",
962
- path: "/flows",
963
- description: "List flow definitions.",
964
- handler: () => a("_voltro_ai_flows", 200)
965
- }, {
966
- method: "GET",
967
- path: "/runs",
968
- description: "List recent flow runs.",
969
- handler: () => a("_voltro_ai_flow_runs", 100)
970
- }],
1201
+ ...e.tables === !1 ? {} : { extendSchema: { tables: Ve } },
1202
+ inspectEndpoints: c,
971
1203
  bindDataStore: (e) => {
972
- n.current = e;
1204
+ r.current = e;
973
1205
  }
974
1206
  });
975
1207
  };
976
1208
  //#endregion
977
- export { e as BriefField, t as ChainPending, v as FLOW_RUN_WORKFLOW, n as FlowCadence, r as FlowChain, i as FlowMode, a as FlowStatus, o as FlowStep, y 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, ee as Modality, m as ReviewMode, h as ReviewOption, te as RunReview, ne as RunSource, re as RunStatus, ie as RunStep, ae as RunStepStatus, oe as StepType, se as Visibility, L as aiFlowRunsTable, ut as aiFlowsPlugin, I as aiFlowsTable, Oe as aiFlowsTables, Ue as buildFlowRunExecute, he as cadenceMatches, rt as cancelFlow, ce as clampMaxSteps, je as clearRegistry, R as collectRefs, st as createFlow, Je as cronRequestId, qe as defineFlow, lt as deleteFlow, We as flowStep, at as getFlow, H as getRegisteredFlow, z as interpolate, tt as launchFlow, ot as listFlows, U as listRegisteredFlows, $e as makeMediaGenerator, me as nextRuns, g as normalizeFlow, V as registerFlow, Y as resolveIr, it as respondToFlow, nt as retryFlow, Xe as runCadenceTick, _ as sanitizeOutputKey, Ae as unresolvedRefs, ct as updateFlow, Ke as validateFlow };
1209
+ export { ce as BriefField, re as ChainPending, a as ConditionOp, Ge as FLOW_RUNS_TTL_ENV, We as FLOW_RUNS_TTL_HOURS_DEFAULT, v as FLOW_RUN_WORKFLOW, oe as FlowCadence, g as FlowChain, l as FlowMode, ie as FlowStatus, se as FlowStep, me as HUMAN_RESPONSE_SIGNAL_PREFIX, Ue as HUMAN_REVIEW_TIMEOUT_ENV, He as HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT, d as HumanResponse, te as Json, Ke as MAX_CHAIN_DEPTH_DEFAULT, qe as MAX_CHAIN_DEPTH_ENV, le as MAX_STEPS_DEFAULT, f as MAX_STEPS_MAX, p as MAX_STEPS_MIN, ae as MediaInputSlot, ne as MediaInputs, h as Modality, m as ReviewMode, c as ReviewOption, ue as RunReview, pe as RunSource, u as RunStatus, fe as RunStep, o as RunStepStatus, ee as StepCondition, t as StepType, de as Visibility, P as aiFlowRunsTable, qt as aiFlowsPlugin, N as aiFlowsTable, Ve as aiFlowsTables, Ct as buildFlowRunExecute, xe as cadenceMatches, Rt as cancelFlow, s as clampMaxSteps, ot as clearRegistry, L as collectRefs, Ut as createFlow, Ot as cronRequestId, Dt as defineFlow, Gt as deleteFlow, e as describeCondition, _ as evaluateCondition, z as flowSegments, wt as flowStep, I as getAiFlowsDefaults, Vt as getFlow, it as getRegisteredFlow, y as humanResponseSignalName, R as interpolate, i as isTruthy, dt as jsonSchemaToEffectSchema, It as launchFlow, Ht as listFlows, at as listRegisteredFlows, Pt as makeMediaGenerator, be as nextRuns, nt as nonContiguousGroups, r as normalizeFlow, rt as registerFlow, Ye as resetAiFlowsDefaults, Qe as resolveHumanReviewTimeoutMs, X as resolveIr, $e as resolveMaxChainDepth, Bt as respondToFlow, Lt as retryFlow, At as runCadenceTick, n as sanitizeOutputKey, Je as setAiFlowsDefaults, tt as unresolvedRefs, Wt as updateFlow, Et as validateFlow, zt as waitingStepIndex };