@voltro/plugin-ai-flows 0.32.0 → 0.34.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/ir.d.ts CHANGED
@@ -9,7 +9,17 @@ export declare const BriefField: Schema.Struct<{
9
9
  placeholder: Schema.optional<typeof Schema.String>;
10
10
  }>;
11
11
 
12
- export declare type BriefField = typeof BriefField.Type;
12
+ /** An INTERFACE for the same reason as {@link FlowStep} — it is reached from an
13
+ * exported table (`aiFlows.inputSchema`), so an alias to a mapped type gets
14
+ * expanded structurally into the api report, in an order that is not stable
15
+ * across build scopes. The `Equals` pin below fails to compile on any drift. */
16
+ export declare interface BriefField {
17
+ readonly key: string;
18
+ readonly label: string;
19
+ readonly type: 'text' | 'textarea' | 'number' | 'boolean';
20
+ readonly required?: boolean | undefined;
21
+ readonly placeholder?: string | undefined;
22
+ }
13
23
 
14
24
  /** Staged follow-up when `chainTo.requireConfirmation` is set. */
15
25
  export declare const ChainPending: Schema.Struct<{
@@ -18,7 +28,12 @@ export declare const ChainPending: Schema.Struct<{
18
28
  status: Schema.Literal<["pending", "confirmed", "dismissed"]>;
19
29
  }>;
20
30
 
21
- export declare type ChainPending = typeof ChainPending.Type;
31
+ /** An INTERFACE reached from `aiFlowRuns.chainPending`; see {@link BriefField}. */
32
+ export declare interface ChainPending {
33
+ readonly flowRef: string;
34
+ readonly input: Json;
35
+ readonly status: 'pending' | 'confirmed' | 'dismissed';
36
+ }
22
37
 
23
38
  export declare const clampMaxSteps: (n: number | null | undefined) => number;
24
39
 
@@ -40,7 +55,25 @@ export declare const FlowCadence: Schema.Struct<{
40
55
  defaultInput: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
41
56
  }>;
42
57
 
43
- export declare type FlowCadence = typeof FlowCadence.Type;
58
+ /**
59
+ * An INTERFACE — reached from `aiFlows.cadence`; see {@link BriefField}.
60
+ *
61
+ * This one is not hypothetical: a single-package `api:report` and a
62
+ * full-monorepo build emitted `hour`/`minute` in DIFFERENT positions inside the
63
+ * structurally-expanded alias, so the api-surface gate rejected a file nobody
64
+ * had touched, showing the same members moving. That is the exact failure
65
+ * {@link FlowStep}'s comment describes.
66
+ */
67
+ export declare interface FlowCadence {
68
+ readonly frequency?: 'weekly' | 'monthly' | undefined;
69
+ readonly repeats: ReadonlyArray<number>;
70
+ readonly intervalWeeks?: number | undefined;
71
+ readonly anchorDate?: string | undefined;
72
+ readonly weekOfMonth?: 1 | 2 | 3 | 4 | 'last' | undefined;
73
+ readonly hour?: number | undefined;
74
+ readonly minute?: 0 | 15 | 30 | 45 | undefined;
75
+ readonly defaultInput?: Json | undefined;
76
+ }
44
77
 
45
78
  /** Follow-up flow spec. On success, map source → the child's brief. */
46
79
  export declare const FlowChain: Schema.Struct<{
@@ -53,7 +86,15 @@ export declare const FlowChain: Schema.Struct<{
53
86
  requireConfirmation: Schema.optional<typeof Schema.Boolean>;
54
87
  }>;
55
88
 
56
- export declare type FlowChain = typeof FlowChain.Type;
89
+ /** An INTERFACE reached from `aiFlows.chainTo`; see {@link BriefField}. */
90
+ export declare interface FlowChain {
91
+ readonly flowRef: string;
92
+ readonly mappings: ReadonlyArray<{
93
+ readonly targetKey: string;
94
+ readonly sourceKey: string;
95
+ }>;
96
+ readonly requireConfirmation?: boolean | undefined;
97
+ }
57
98
 
58
99
  /** The raw flow definition either front door supplies before normalization.
59
100
  * Optional fields tolerate explicit `undefined` (row reads produce it). */
@@ -67,6 +108,7 @@ export declare interface FlowDefinitionInput {
67
108
  readonly orchestratorInstructions?: string | null | undefined;
68
109
  readonly chain?: FlowChain | null | undefined;
69
110
  readonly cadence?: FlowCadence | null | undefined;
111
+ readonly humanTimeoutMs?: number | null | undefined;
70
112
  }
71
113
 
72
114
  /** The single representation the engine interprets, from either front door. */
@@ -82,6 +124,10 @@ export declare interface FlowIR {
82
124
  };
83
125
  readonly chain?: FlowChain;
84
126
  readonly cadence?: FlowCadence;
127
+ /** Flow-wide default for a `human` step's park bound, in ms. A step's own
128
+ * `timeoutMs` wins; absent here too → the engine/plugin default. `0` = wait
129
+ * forever. */
130
+ readonly humanTimeoutMs?: number;
85
131
  }
86
132
 
87
133
  /** Execution mode. Replaces the legacy `allowDeviation` boolean — a mode is not
@@ -132,6 +178,11 @@ export declare const FlowStep: Schema.Struct<{
132
178
  value: typeof Schema.String;
133
179
  label: typeof Schema.String;
134
180
  }>>>;
181
+ /** `human` step only — how long the run parks awaiting this review before it
182
+ * fails, in milliseconds. Omitted → the flow's `humanTimeoutMs`, then the
183
+ * engine/plugin default (see `resolveHumanReviewTimeoutMs`). `0` means WAIT
184
+ * FOREVER (the park is slot-free, so an unbounded wait costs no worker). */
185
+ timeoutMs: Schema.optional<typeof Schema.Number>;
135
186
  }>;
136
187
 
137
188
  /**
@@ -172,6 +223,7 @@ export declare interface FlowStep {
172
223
  readonly schema?: Json | undefined;
173
224
  readonly reviewMode?: ReviewMode | undefined;
174
225
  readonly options?: ReadonlyArray<ReviewOption> | undefined;
226
+ readonly timeoutMs?: number | undefined;
175
227
  }
176
228
 
177
229
  /** The HITL answer, written by `respond`. */
@@ -182,7 +234,13 @@ export declare const HumanResponse: Schema.Struct<{
182
234
  respondedAt: Schema.optional<typeof Schema.String>;
183
235
  }>;
184
236
 
185
- export declare type HumanResponse = typeof HumanResponse.Type;
237
+ /** An INTERFACE reached from `aiFlowRuns.humanResponse`; see {@link BriefField}. */
238
+ export declare interface HumanResponse {
239
+ readonly decision?: 'approve' | 'reject' | undefined;
240
+ readonly value?: string | undefined;
241
+ readonly text?: string | undefined;
242
+ readonly respondedAt?: string | undefined;
243
+ }
186
244
 
187
245
  /** A JSON value (for `params` / `input` / a `structured` step's JSON Schema). */
188
246
  export declare const Json: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
package/dist/ir.js CHANGED
@@ -29,7 +29,8 @@ var t = e.Literal("deterministic", "agentic"), n = e.Literal("draft", "active",
29
29
  agentRef: e.optional(e.String),
30
30
  schema: e.optional(f),
31
31
  reviewMode: e.optional(c),
32
- options: e.optional(e.Array(l))
32
+ options: e.optional(e.Array(l)),
33
+ timeoutMs: e.optional(e.Number)
33
34
  }), m = e.Struct({
34
35
  key: e.String,
35
36
  label: e.String,
@@ -95,7 +96,8 @@ var t = e.Literal("deterministic", "agentic"), n = e.Literal("draft", "active",
95
96
  brief: e.brief ?? [],
96
97
  ...n ? { orchestrator: n } : {},
97
98
  ...e.chain ? { chain: e.chain } : {},
98
- ...e.cadence ? { cadence: e.cadence } : {}
99
+ ...e.cadence ? { cadence: e.cadence } : {},
100
+ ...e.humanTimeoutMs != null && Number.isFinite(e.humanTimeoutMs) ? { humanTimeoutMs: e.humanTimeoutMs } : {}
99
101
  };
100
102
  };
101
103
  //#endregion
package/dist/web.d.ts CHANGED
@@ -9,7 +9,17 @@ export declare const BriefField: Schema.Struct<{
9
9
  placeholder: Schema.optional<typeof Schema.String>;
10
10
  }>;
11
11
 
12
- export declare type BriefField = typeof BriefField.Type;
12
+ /** An INTERFACE for the same reason as {@link FlowStep} — it is reached from an
13
+ * exported table (`aiFlows.inputSchema`), so an alias to a mapped type gets
14
+ * expanded structurally into the api report, in an order that is not stable
15
+ * across build scopes. The `Equals` pin below fails to compile on any drift. */
16
+ export declare interface BriefField {
17
+ readonly key: string;
18
+ readonly label: string;
19
+ readonly type: 'text' | 'textarea' | 'number' | 'boolean';
20
+ readonly required?: boolean | undefined;
21
+ readonly placeholder?: string | undefined;
22
+ }
13
23
 
14
24
  /**
15
25
  * Does `cadence` fire at wall-clock `now`? True only on a 15-min slot matching
@@ -18,6 +28,8 @@ export declare type BriefField = typeof BriefField.Type;
18
28
  */
19
29
  export declare const cadenceMatches: (cadence: FlowCadence, now: Date) => boolean;
20
30
 
31
+ export declare const DEFAULT_FLOW_RPC_TAGS: FlowRpcTags;
32
+
21
33
  /** Schedule spec — richer than a single cron expr (weekly interval + anchor,
22
34
  * monthly weekOfMonth), evaluated by the shared `cadenceMatches` predicate. */
23
35
  export declare const FlowCadence: Schema.Struct<{
@@ -36,7 +48,25 @@ export declare const FlowCadence: Schema.Struct<{
36
48
  defaultInput: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
37
49
  }>;
38
50
 
39
- export declare type FlowCadence = typeof FlowCadence.Type;
51
+ /**
52
+ * An INTERFACE — reached from `aiFlows.cadence`; see {@link BriefField}.
53
+ *
54
+ * This one is not hypothetical: a single-package `api:report` and a
55
+ * full-monorepo build emitted `hour`/`minute` in DIFFERENT positions inside the
56
+ * structurally-expanded alias, so the api-surface gate rejected a file nobody
57
+ * had touched, showing the same members moving. That is the exact failure
58
+ * {@link FlowStep}'s comment describes.
59
+ */
60
+ export declare interface FlowCadence {
61
+ readonly frequency?: 'weekly' | 'monthly' | undefined;
62
+ readonly repeats: ReadonlyArray<number>;
63
+ readonly intervalWeeks?: number | undefined;
64
+ readonly anchorDate?: string | undefined;
65
+ readonly weekOfMonth?: 1 | 2 | 3 | 4 | 'last' | undefined;
66
+ readonly hour?: number | undefined;
67
+ readonly minute?: 0 | 15 | 30 | 45 | undefined;
68
+ readonly defaultInput?: Json | undefined;
69
+ }
40
70
 
41
71
  /** Follow-up flow spec. On success, map source → the child's brief. */
42
72
  export declare const FlowChain: Schema.Struct<{
@@ -49,7 +79,23 @@ export declare const FlowChain: Schema.Struct<{
49
79
  requireConfirmation: Schema.optional<typeof Schema.Boolean>;
50
80
  }>;
51
81
 
52
- export declare type FlowChain = typeof FlowChain.Type;
82
+ /** An INTERFACE reached from `aiFlows.chainTo`; see {@link BriefField}. */
83
+ export declare interface FlowChain {
84
+ readonly flowRef: string;
85
+ readonly mappings: ReadonlyArray<{
86
+ readonly targetKey: string;
87
+ readonly sourceKey: string;
88
+ }>;
89
+ readonly requireConfirmation?: boolean | undefined;
90
+ }
91
+
92
+ /** Per-hook wiring: which api, and which tags if the app renamed them. */
93
+ export declare interface FlowHookOptions {
94
+ /** Framework api name. Default `'app'`. */
95
+ readonly apiName?: string;
96
+ /** Override any subset of {@link DEFAULT_FLOW_RPC_TAGS}. */
97
+ readonly tags?: Partial<FlowRpcTags>;
98
+ }
53
99
 
54
100
  /** Execution mode. Replaces the legacy `allowDeviation` boolean — a mode is not
55
101
  * a boolean. `deterministic` runs the plan verbatim (resumable per step);
@@ -58,6 +104,54 @@ export declare const FlowMode: Schema.Literal<["deterministic", "agentic"]>;
58
104
 
59
105
  export declare type FlowMode = typeof FlowMode.Type;
60
106
 
107
+ /** The rpc tags the hooks call. Defaults match the convention the docs wire up
108
+ * (`api/flows/aiFlows.<verb>.{action,query}.server.ts`). */
109
+ export declare interface FlowRpcTags {
110
+ readonly launch: string;
111
+ readonly retry: string;
112
+ readonly cancel: string;
113
+ readonly respond: string;
114
+ /** Query returning ONE run row by id. */
115
+ readonly run: string;
116
+ /** Query returning the caller's recent runs. */
117
+ readonly runs: string;
118
+ /** Query returning the flow DEFINITIONS the caller may launch. */
119
+ readonly flows: string;
120
+ }
121
+
122
+ /** What `useFlowRun` hands a timeline component. */
123
+ export declare interface FlowRunState {
124
+ readonly run: FlowRunView | undefined;
125
+ readonly steps: ReadonlyArray<RunStep>;
126
+ readonly status: RunStatus | undefined;
127
+ /** `true` while the run is parked on a human step. */
128
+ readonly awaitingReview: boolean;
129
+ /** The review the run is parked on (prompt + mode + options), if any. */
130
+ readonly review: RunReview | undefined;
131
+ /** Index of the step being executed / reviewed. */
132
+ readonly currentStep: number;
133
+ /** `true` once the run can no longer change. */
134
+ readonly done: boolean;
135
+ readonly loading: boolean;
136
+ }
137
+
138
+ /** The run row shape the hooks project — the reactive columns a timeline needs. */
139
+ export declare interface FlowRunView {
140
+ readonly id: string;
141
+ readonly flowRef?: string;
142
+ readonly flowName?: string | null;
143
+ readonly status?: RunStatus;
144
+ readonly steps?: ReadonlyArray<RunStep> | null;
145
+ readonly currentStep?: number;
146
+ readonly totalSteps?: number;
147
+ readonly output?: Record<string, unknown> | null;
148
+ readonly humanResponse?: HumanResponse | null;
149
+ readonly costMicroUsd?: number;
150
+ readonly errorMessage?: string | null;
151
+ readonly startedAt?: string | null;
152
+ readonly completedAt?: string | null;
153
+ }
154
+
61
155
  /** Flow-definition lifecycle. */
62
156
  export declare const FlowStatus: Schema.Literal<["draft", "active", "archived"]>;
63
157
 
@@ -99,6 +193,11 @@ export declare const FlowStep: Schema.Struct<{
99
193
  value: typeof Schema.String;
100
194
  label: typeof Schema.String;
101
195
  }>>>;
196
+ /** `human` step only — how long the run parks awaiting this review before it
197
+ * fails, in milliseconds. Omitted → the flow's `humanTimeoutMs`, then the
198
+ * engine/plugin default (see `resolveHumanReviewTimeoutMs`). `0` means WAIT
199
+ * FOREVER (the park is slot-free, so an unbounded wait costs no worker). */
200
+ timeoutMs: Schema.optional<typeof Schema.Number>;
102
201
  }>;
103
202
 
104
203
  /**
@@ -139,6 +238,23 @@ export declare interface FlowStep {
139
238
  readonly schema?: Json | undefined;
140
239
  readonly reviewMode?: ReviewMode | undefined;
141
240
  readonly options?: ReadonlyArray<ReviewOption> | undefined;
241
+ readonly timeoutMs?: number | undefined;
242
+ }
243
+
244
+ /** The HITL answer, written by `respond`. */
245
+ export declare const HumanResponse: Schema.Struct<{
246
+ decision: Schema.optional<Schema.Literal<["approve", "reject"]>>;
247
+ value: Schema.optional<typeof Schema.String>;
248
+ text: Schema.optional<typeof Schema.String>;
249
+ respondedAt: Schema.optional<typeof Schema.String>;
250
+ }>;
251
+
252
+ /** An INTERFACE — reached from `aiFlowRuns.humanResponse`; see {@link BriefField}. */
253
+ export declare interface HumanResponse {
254
+ readonly decision?: 'approve' | 'reject' | undefined;
255
+ readonly value?: string | undefined;
256
+ readonly text?: string | undefined;
257
+ readonly respondedAt?: string | undefined;
142
258
  }
143
259
 
144
260
  /** A JSON value (for `params` / `input` / a `structured` step's JSON Schema). */
@@ -146,6 +262,18 @@ declare const Json: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
146
262
 
147
263
  declare type Json = typeof Json.Type;
148
264
 
265
+ export declare interface LaunchFlowInput {
266
+ readonly flowRef: string;
267
+ readonly input?: Record<string, unknown>;
268
+ readonly source?: 'manual' | 'cron';
269
+ }
270
+
271
+ export declare interface LaunchFlowResult {
272
+ readonly runId: string;
273
+ readonly requestId: string;
274
+ readonly status: RunStatus;
275
+ }
276
+
149
277
  declare const MediaInputs: Schema.Record$<typeof Schema.String, Schema.Union<[Schema.Struct<{
150
278
  from: Schema.Literal<["upload"]>;
151
279
  url: typeof Schema.String;
@@ -179,7 +307,7 @@ export declare const ReviewOption: Schema.Struct<{
179
307
  export declare type ReviewOption = typeof ReviewOption.Type;
180
308
 
181
309
  /** Human-review config projected onto a `waiting` run step. */
182
- declare const RunReview: Schema.Struct<{
310
+ export declare const RunReview: Schema.Struct<{
183
311
  mode: Schema.Literal<["approve", "choice", "text"]>;
184
312
  options: Schema.optional<Schema.Array$<Schema.Struct<{
185
313
  value: typeof Schema.String;
@@ -188,7 +316,7 @@ declare const RunReview: Schema.Struct<{
188
316
  prompt: typeof Schema.String;
189
317
  }>;
190
318
 
191
- declare type RunReview = typeof RunReview.Type;
319
+ export declare type RunReview = typeof RunReview.Type;
192
320
 
193
321
  /** Run status — ONE canonical set (the legacy vocabulary; the Voltro-port
194
322
  * additions `awaiting_human`/`completed`/`rejected` are collapsed: `waiting`
@@ -256,6 +384,131 @@ export declare const StepType: Schema.Literal<["agent", "generate", "structured"
256
384
 
257
385
  export declare type StepType = typeof StepType.Type;
258
386
 
387
+ /** Cooperatively cancel a run (the engine stops before its next step). */
388
+ export declare const useCancelFlow: (options?: FlowHookOptions) => {
389
+ cancel: (runId: string) => Promise<{
390
+ runId: string;
391
+ status: RunStatus;
392
+ }>;
393
+ pending: boolean;
394
+ error: unknown;
395
+ };
396
+
397
+ /**
398
+ * The whole review widget in one hook: the live run + the answer callbacks,
399
+ * with the pending review's prompt/options already unwrapped.
400
+ */
401
+ export declare const useFlowReview: (runId: string | undefined, options?: FlowHookOptions) => {
402
+ prompt: string | undefined;
403
+ mode: "text" | "approve" | "choice" | undefined;
404
+ options: readonly {
405
+ readonly value: string;
406
+ readonly label: string;
407
+ }[];
408
+ /** `true` when there is a review this caller can answer right now. */
409
+ canRespond: boolean;
410
+ respond: (runId: string, response: HumanResponse) => Promise<{
411
+ runId: string;
412
+ stepIndex?: number;
413
+ }>;
414
+ approve: (runId: string, text?: string) => Promise<{
415
+ runId: string;
416
+ stepIndex?: number;
417
+ }>;
418
+ reject: (runId: string, text?: string) => Promise<{
419
+ runId: string;
420
+ stepIndex?: number;
421
+ }>;
422
+ /** Pick one of a `choice` review's options. */
423
+ choose: (runId: string, value: string) => Promise<{
424
+ runId: string;
425
+ stepIndex?: number;
426
+ }>;
427
+ /** Answer a `text` review. */
428
+ submitText: (runId: string, text: string) => Promise<{
429
+ runId: string;
430
+ stepIndex?: number;
431
+ }>;
432
+ pending: boolean;
433
+ error: unknown;
434
+ run: FlowRunView | undefined;
435
+ steps: ReadonlyArray<RunStep>;
436
+ status: RunStatus | undefined;
437
+ awaitingReview: boolean;
438
+ review: RunReview | undefined;
439
+ currentStep: number;
440
+ done: boolean;
441
+ loading: boolean;
442
+ };
443
+
444
+ /**
445
+ * Live view of ONE flow run. The run row is reactive, so the timeline streams:
446
+ * every step transition the engine writes shows up without a refetch.
447
+ *
448
+ * ```tsx
449
+ * const { steps, awaitingReview, review } = useFlowRun(runId)
450
+ * ```
451
+ */
452
+ export declare const useFlowRun: (runId: string | undefined, options?: FlowHookOptions) => FlowRunState;
453
+
454
+ /** The caller's recent runs (whatever the app's `runs` query returns). */
455
+ export declare const useFlowRuns: (filter?: Readonly<Record<string, unknown>>, options?: FlowHookOptions) => ReadonlyArray<FlowRunView>;
456
+
457
+ /** The flow DEFINITIONS the caller can launch (the gallery / picker). */
458
+ export declare const useFlows: <T = Record<string, unknown>>(filter?: Readonly<Record<string, unknown>>, options?: FlowHookOptions) => ReadonlyArray<T>;
459
+
460
+ /** Start a run. Returns the `runId` to hand `useFlowRun`. */
461
+ export declare const useLaunchFlow: (options?: FlowHookOptions) => {
462
+ launch: (input: LaunchFlowInput) => Promise<LaunchFlowResult>;
463
+ pending: boolean;
464
+ error: unknown;
465
+ lastRun: LaunchFlowResult | undefined;
466
+ };
467
+
468
+ /**
469
+ * Answer the review a run is parked on. The server resolves WHICH human step the
470
+ * answer belongs to from the run's live timeline, so the UI never has to track a
471
+ * step index — and a flow with several reviews gets one answer per review.
472
+ *
473
+ * ```tsx
474
+ * const { approve, reject, choose, submitText } = useRespondToFlow()
475
+ * <button onClick={() => approve(runId)}>Approve</button>
476
+ * ```
477
+ */
478
+ export declare const useRespondToFlow: (options?: FlowHookOptions) => {
479
+ respond: (runId: string, response: HumanResponse) => Promise<{
480
+ runId: string;
481
+ stepIndex?: number;
482
+ }>;
483
+ approve: (runId: string, text?: string) => Promise<{
484
+ runId: string;
485
+ stepIndex?: number;
486
+ }>;
487
+ reject: (runId: string, text?: string) => Promise<{
488
+ runId: string;
489
+ stepIndex?: number;
490
+ }>;
491
+ /** Pick one of a `choice` review's options. */
492
+ choose: (runId: string, value: string) => Promise<{
493
+ runId: string;
494
+ stepIndex?: number;
495
+ }>;
496
+ /** Answer a `text` review. */
497
+ submitText: (runId: string, text: string) => Promise<{
498
+ runId: string;
499
+ stepIndex?: number;
500
+ }>;
501
+ pending: boolean;
502
+ error: unknown;
503
+ };
504
+
505
+ /** Re-run a run from its first unfinished step (same requestId → journal replay). */
506
+ export declare const useRetryFlow: (options?: FlowHookOptions) => {
507
+ retry: (runId: string) => Promise<LaunchFlowResult>;
508
+ pending: boolean;
509
+ error: unknown;
510
+ };
511
+
259
512
  /** Gallery scope. `shared` → per-subject share list; `organization` → tenant. */
260
513
  export declare const Visibility: Schema.Literal<["private", "organization", "shared"]>;
261
514
 
package/dist/web.js CHANGED
@@ -1,2 +1,97 @@
1
1
  import { n as e, t } from "./cadence-Bt6dPelT.js";
2
- export { t as cadenceMatches, e as nextRuns };
2
+ import { useAction as n, useSubscription as r } from "@voltro/client";
3
+ //#region src/web.ts
4
+ var i = {
5
+ launch: "aiFlows.launch",
6
+ retry: "aiFlows.retry",
7
+ cancel: "aiFlows.cancel",
8
+ respond: "aiFlows.respond",
9
+ run: "aiFlows.run",
10
+ runs: "aiFlows.runs",
11
+ flows: "aiFlows.flows"
12
+ }, a = (e) => e?.tags === void 0 ? i : {
13
+ ...i,
14
+ ...e.tags
15
+ }, o = (e) => e?.apiName ?? "app", s = [
16
+ "succeeded",
17
+ "failed",
18
+ "cancelled"
19
+ ], c = (e, t) => {
20
+ let n = r(o(t), a(t).run, { id: e ?? "" }, { skip: e === void 0 || e === "" }), i = "data" in n ? n.data : void 0, c = (Array.isArray(i) ? i[0] : i) ?? void 0, l = c?.steps ?? [], u = l.find((e) => e.status === "waiting");
21
+ return {
22
+ run: c,
23
+ steps: l,
24
+ status: c?.status,
25
+ awaitingReview: c?.status === "waiting",
26
+ review: u?.review,
27
+ currentStep: c?.currentStep ?? 0,
28
+ done: c?.status !== void 0 && s.includes(c.status),
29
+ loading: c === void 0
30
+ };
31
+ }, l = (e = {}, t) => {
32
+ let n = r(o(t), a(t).runs, e);
33
+ return ("data" in n ? n.data : void 0) ?? [];
34
+ }, u = (e = {}, t) => {
35
+ let n = r(o(t), a(t).flows, e);
36
+ return ("data" in n ? n.data : void 0) ?? [];
37
+ }, d = (e) => {
38
+ let t = n(o(e), a(e).launch);
39
+ return {
40
+ launch: (e) => t.run(e),
41
+ pending: t.pending,
42
+ error: t.error,
43
+ lastRun: t.lastResult
44
+ };
45
+ }, f = (e) => {
46
+ let t = n(o(e), a(e).retry);
47
+ return {
48
+ retry: (e) => t.run({ runId: e }),
49
+ pending: t.pending,
50
+ error: t.error
51
+ };
52
+ }, p = (e) => {
53
+ let t = n(o(e), a(e).cancel);
54
+ return {
55
+ cancel: (e) => t.run({ runId: e }),
56
+ pending: t.pending,
57
+ error: t.error
58
+ };
59
+ }, m = (e) => {
60
+ let t = n(o(e), a(e).respond), r = (e, n) => t.run({
61
+ runId: e,
62
+ response: n
63
+ });
64
+ return {
65
+ respond: r,
66
+ approve: (e, t) => r(e, {
67
+ decision: "approve",
68
+ ...t === void 0 ? {} : { text: t }
69
+ }),
70
+ reject: (e, t) => r(e, {
71
+ decision: "reject",
72
+ ...t === void 0 ? {} : { text: t }
73
+ }),
74
+ choose: (e, t) => r(e, {
75
+ decision: "approve",
76
+ value: t
77
+ }),
78
+ submitText: (e, t) => r(e, {
79
+ decision: "approve",
80
+ text: t
81
+ }),
82
+ pending: t.pending,
83
+ error: t.error
84
+ };
85
+ }, h = (e, t) => {
86
+ let n = c(e, t), r = m(t), i = n.review?.options ?? [];
87
+ return {
88
+ ...n,
89
+ ...r,
90
+ prompt: n.review?.prompt,
91
+ mode: n.review?.mode,
92
+ options: i,
93
+ canRespond: n.awaitingReview && e !== void 0
94
+ };
95
+ };
96
+ //#endregion
97
+ export { i as DEFAULT_FLOW_RPC_TAGS, t as cadenceMatches, e as nextRuns, p as useCancelFlow, h as useFlowReview, c as useFlowRun, l as useFlowRuns, u as useFlows, d as useLaunchFlow, m as useRespondToFlow, f as useRetryFlow };
@@ -36,10 +36,35 @@ export declare const flowRunWorkflow: Workflow<"flow.run", Schema.Struct<{
36
36
  }>, typeof Schema.Never> & WorkflowMessagesCarrier<{
37
37
  readonly signals: {};
38
38
  readonly updates: {};
39
- readonly queries: {};
40
39
  }>;
41
40
 
42
- /** The signal a `human` step parks on; `respondToFlow` sends it to resume. */
43
- export declare const HUMAN_RESPONSE_SIGNAL = "flow-human-response";
41
+ /** Namespace of the signal a `human` step parks on. Never used on its own
42
+ * the signal a step actually awaits is {@link humanResponseSignalName}. */
43
+ export declare const HUMAN_RESPONSE_SIGNAL_PREFIX = "flow-human-response";
44
+
45
+ /**
46
+ * The signal name ONE human step parks on, derived from that step's position in
47
+ * the (journal-pinned) plan.
48
+ *
49
+ * **Why this is per-step and not one constant.** `awaitSignalSuspending` derives
50
+ * its `DurableDeferred` from workflow-name + signal-name per execution, so a
51
+ * single `'flow-human-response'` for every human step in a flow meant the SECOND
52
+ * review awaited the deferred the FIRST answer had already completed — it
53
+ * resolved instantly, with the first reviewer's payload, and the run finished
54
+ * carrying an approval nobody gave. Measured before the fix: a two-review flow,
55
+ * one answer, `status: 'succeeded'`, `output: { first: 'answer-one', second:
56
+ * 'answer-one' }`. The same collision aliased the wait's durable timeout clock
57
+ * (`await-signal-timeout/<name>`), so the second park inherited the first's
58
+ * expiry too.
59
+ *
60
+ * **Why the INDEX is the identity.** It must be identical on every replay and
61
+ * derivable by the responder without re-resolving the flow definition (which may
62
+ * have been edited mid-run). The step list is pinned in the run's journal at
63
+ * step 0, so a step's index is fixed for the life of the run; the responder
64
+ * reads it back off the run row's live timeline. A counter, a clock, or a
65
+ * `randomUUID` would all break replay; the authored step `id` would break the
66
+ * moment a definition is re-ordered under a live run.
67
+ */
68
+ export declare const humanResponseSignalName: (stepIndex: number) => string;
44
69
 
45
70
  export { }
package/dist/workflow.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Schema as e } from "effect";
2
2
  import { workflow as t } from "@voltro/workflow/define";
3
3
  //#region src/workflow.ts
4
- var n = "flow.run", r = "flow-human-response", i = t({
4
+ var n = "flow.run", r = "flow-human-response", i = (e) => `${r}:${e}`, a = t({
5
5
  name: n,
6
6
  payload: {
7
7
  runId: e.String,
@@ -20,4 +20,4 @@ var n = "flow.run", r = "flow-human-response", i = t({
20
20
  idempotencyKey: ({ requestId: e }) => `flow-run:${e}`
21
21
  });
22
22
  //#endregion
23
- export { n as FLOW_RUN_WORKFLOW, r as HUMAN_RESPONSE_SIGNAL, i as flowRunWorkflow };
23
+ export { n as FLOW_RUN_WORKFLOW, r as HUMAN_RESPONSE_SIGNAL_PREFIX, a as flowRunWorkflow, i as humanResponseSignalName };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-ai-flows",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "description": "AI Flows — durable multi-step AI pipelines (deterministic + agentic) with human-in-the-loop, chaining, and cadence. Author flows in code (defineFlow) or as data (visual editor rows); one engine runs both on @voltro/workflow durability, @voltro/ai generation, storage artifacts, and notifications.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -47,7 +47,8 @@
47
47
  "types": "./dist/web.d.ts",
48
48
  "import": "./dist/web.js",
49
49
  "default": "./dist/web.js"
50
- }
50
+ },
51
+ "./package.json": "./package.json"
51
52
  },
52
53
  "main": "./dist/index.js",
53
54
  "module": "./dist/index.js",
@@ -57,15 +58,16 @@
57
58
  "node": ">=24.0.0"
58
59
  },
59
60
  "dependencies": {
60
- "@voltro/ai": "0.32.0",
61
- "@voltro/database": "0.32.0",
62
- "@voltro/env": "0.32.0",
63
- "@voltro/plugin-audit": "0.32.0",
64
- "@voltro/plugin-multitenancy": "0.32.0",
65
- "@voltro/plugin-soft-delete": "0.32.0",
66
- "@voltro/protocol": "0.32.0",
67
- "@voltro/runtime": "0.32.0",
68
- "@voltro/workflow": "0.32.0"
61
+ "@voltro/ai": "0.34.0",
62
+ "@voltro/client": "0.34.0",
63
+ "@voltro/database": "0.34.0",
64
+ "@voltro/env": "0.34.0",
65
+ "@voltro/plugin-audit": "0.34.0",
66
+ "@voltro/plugin-multitenancy": "0.34.0",
67
+ "@voltro/plugin-soft-delete": "0.34.0",
68
+ "@voltro/protocol": "0.34.0",
69
+ "@voltro/runtime": "0.34.0",
70
+ "@voltro/workflow": "0.34.0"
69
71
  },
70
72
  "peerDependencies": {
71
73
  "effect": "^3.22.0"