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