@voltro/plugin-ai-flows 0.33.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/CHANGELOG.md +1801 -0
- package/dist/index.d.ts +247 -50
- package/dist/index.js +256 -167
- package/dist/ir.d.ts +63 -5
- package/dist/ir.js +4 -2
- package/dist/web.d.ts +258 -5
- package/dist/web.js +96 -1
- package/dist/workflow.d.ts +28 -3
- package/dist/workflow.js +2 -2
- package/package.json +11 -10
package/dist/index.d.ts
CHANGED
|
@@ -42,20 +42,9 @@ export declare const aiFlowRunsTable: Table<"_voltro_ai_flow_runs", FieldDefinit
|
|
|
42
42
|
readonly currentStep: ColumnBuilder<number, "integer", true>;
|
|
43
43
|
readonly totalSteps: ColumnBuilder<number, "integer", true>;
|
|
44
44
|
/** The HITL answer, written by `respond`. */
|
|
45
|
-
readonly humanResponse: ColumnBuilder<
|
|
46
|
-
readonly value?: string | undefined;
|
|
47
|
-
readonly text?: string | undefined;
|
|
48
|
-
readonly decision?: "approve" | "reject" | undefined;
|
|
49
|
-
readonly respondedAt?: string | undefined;
|
|
50
|
-
} | null, "json", boolean>;
|
|
45
|
+
readonly humanResponse: ColumnBuilder<HumanResponse | null, "json", boolean>;
|
|
51
46
|
/** Staged follow-up when the chain requires confirmation. */
|
|
52
|
-
readonly chainPending: ColumnBuilder<
|
|
53
|
-
readonly status: "pending" | "confirmed" | "dismissed";
|
|
54
|
-
readonly input: {
|
|
55
|
-
readonly [x: string]: unknown;
|
|
56
|
-
};
|
|
57
|
-
readonly flowRef: string;
|
|
58
|
-
} | null, "json", boolean>;
|
|
47
|
+
readonly chainPending: ColumnBuilder<ChainPending | null, "json", boolean>;
|
|
59
48
|
/** Accumulated cost in micro-USD (app view projects to €/cents). */
|
|
60
49
|
readonly costMicroUsd: ColumnBuilder<number, "integer", true>;
|
|
61
50
|
readonly durationMs: ColumnBuilder<number | null, "integer", boolean>;
|
|
@@ -79,6 +68,12 @@ export declare const aiFlowRunsTable: Table<"_voltro_ai_flow_runs", FieldDefinit
|
|
|
79
68
|
readonly updatedBy: ColumnDefinition<string | null, "reference", boolean>;
|
|
80
69
|
}, true, never>;
|
|
81
70
|
|
|
71
|
+
/** Tunables an `aiFlowsPlugin({...})` call can set from `app.config.ts`. */
|
|
72
|
+
export declare interface AiFlowsDefaults {
|
|
73
|
+
/** Park bound for a `human` step, in ms. `0` = wait forever. */
|
|
74
|
+
readonly humanReviewTimeoutMs?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
82
77
|
/**
|
|
83
78
|
* The AI-Flows plugin. Install it in `app.config.ts` `plugins: [...]`. It
|
|
84
79
|
* contributes the canonical `ai_flows` + `ai_flow_runs` tables plus the
|
|
@@ -94,6 +89,59 @@ export declare const aiFlowsPlugin: (options?: AiFlowsPluginOptions) => VoltroPl
|
|
|
94
89
|
export declare interface AiFlowsPluginOptions {
|
|
95
90
|
/** Namespace for this plugin's routes / inspect endpoints. Default `aiFlows`. */
|
|
96
91
|
readonly alias?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Contribute this plugin's tables via `extendSchema.tables`. Default `true`.
|
|
94
|
+
*
|
|
95
|
+
* Set `false` when your app ALREADY declares equivalent tables and you want to
|
|
96
|
+
* keep them — the seam this exists for. The plugin then contributes no DDL and
|
|
97
|
+
* the declarative differ never proposes its tables; everything else (routes,
|
|
98
|
+
* inspect, interceptors) is unchanged.
|
|
99
|
+
*
|
|
100
|
+
* **What you take over, exactly:** `_voltro_ai_flows` (definitions) and
|
|
101
|
+
* `_voltro_ai_flow_runs` (runs). The retention sweep registered below still
|
|
102
|
+
* targets `_voltro_ai_flow_runs` by name, so your table inherits the same TTL
|
|
103
|
+
* — which is the intent, but say so to whoever owns that table.
|
|
104
|
+
*
|
|
105
|
+
* It is not offered on every plugin, and the omissions are deliberate rather
|
|
106
|
+
* than unfinished: a `tables: false` that quietly disables a table carrying an
|
|
107
|
+
* AUTHORIZATION or SAFETY decision — the SAML replay cache, SCIM provisioning
|
|
108
|
+
* state, billing's usage counters, cdc-out's outbox — is a security regression
|
|
109
|
+
* shipped as an ergonomics feature. Those plugins need a named store seam
|
|
110
|
+
* first, not a boolean.
|
|
111
|
+
*/
|
|
112
|
+
readonly tables?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* How long a `human` step parks awaiting its review before the run fails, in
|
|
115
|
+
* ms. Default 7 days (`VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS` overrides at
|
|
116
|
+
* deploy time); `0` = wait forever. A flow's `humanTimeoutMs` and a step's own
|
|
117
|
+
* `timeoutMs` both outrank this.
|
|
118
|
+
*/
|
|
119
|
+
readonly humanReviewTimeoutMs?: number;
|
|
120
|
+
/**
|
|
121
|
+
* How long a FINISHED flow run is kept, in ms. Default 90 days
|
|
122
|
+
* (`VOLTRO_AI_FLOW_RUNS_TTL_HOURS`).
|
|
123
|
+
*
|
|
124
|
+
* `_voltro_ai_flow_runs` stores every step's full output plus review payloads
|
|
125
|
+
* and grows with traffic, so it is registered with the framework retention
|
|
126
|
+
* sweep like every other run-family table. Two properties of that policy are
|
|
127
|
+
* deliberate:
|
|
128
|
+
*
|
|
129
|
+
* - **Only TERMINAL runs are swept.** The predicate is status-aware
|
|
130
|
+
* (`succeeded | failed | cancelled`), so a run parked on a human review
|
|
131
|
+
* survives regardless of age — a plain time-TTL would delete the pending
|
|
132
|
+
* approvals this plugin exists to support.
|
|
133
|
+
* - **Media artifacts are NOT swept with the row.** A run's steps carry hosted
|
|
134
|
+
* URLs whose blobs belong to the storage plugin; deleting the row orphans
|
|
135
|
+
* them. Keep this TTL at or above the app's own media-purge window, or purge
|
|
136
|
+
* by run id before the row ages out.
|
|
137
|
+
*/
|
|
138
|
+
readonly runsTtlMs?: number;
|
|
139
|
+
/**
|
|
140
|
+
* Ceiling on rows ONE inspect call may return (`/flows`, `/runs`). Default
|
|
141
|
+
* 200. A run row carries every step's full output, so the page size is a real
|
|
142
|
+
* response-size knob, not a formality.
|
|
143
|
+
*/
|
|
144
|
+
readonly inspectPageMax?: number;
|
|
97
145
|
}
|
|
98
146
|
|
|
99
147
|
/** `ai_flows` — a reusable flow DEFINITION (the data front door persists these;
|
|
@@ -115,33 +163,12 @@ export declare const aiFlowsTable: Table<"_voltro_ai_flows", FieldDefinitions<{
|
|
|
115
163
|
/** The ordered plan (`FlowStep[]`); null ≡ empty. */
|
|
116
164
|
readonly steps: ColumnBuilder<readonly FlowStep[] | null, "json", boolean>;
|
|
117
165
|
/** The launch-form brief (`BriefField[]`). */
|
|
118
|
-
readonly inputSchema: ColumnBuilder<readonly
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}[] | null, "json", boolean>;
|
|
125
|
-
readonly chainTo: ColumnBuilder<{
|
|
126
|
-
readonly flowRef: string;
|
|
127
|
-
readonly mappings: readonly {
|
|
128
|
-
readonly sourceKey: string;
|
|
129
|
-
readonly targetKey: string;
|
|
130
|
-
}[];
|
|
131
|
-
readonly requireConfirmation?: boolean | undefined;
|
|
132
|
-
} | null, "json", boolean>;
|
|
133
|
-
readonly cadence: ColumnBuilder<{
|
|
134
|
-
readonly frequency?: "weekly" | "monthly" | undefined;
|
|
135
|
-
readonly repeats: readonly number[];
|
|
136
|
-
readonly intervalWeeks?: number | undefined;
|
|
137
|
-
readonly anchorDate?: string | undefined;
|
|
138
|
-
readonly weekOfMonth?: 1 | 2 | 3 | 4 | "last" | undefined;
|
|
139
|
-
readonly hour?: number | undefined;
|
|
140
|
-
readonly minute?: 0 | 15 | 30 | 45 | undefined;
|
|
141
|
-
readonly defaultInput?: {
|
|
142
|
-
readonly [x: string]: unknown;
|
|
143
|
-
} | undefined;
|
|
144
|
-
} | null, "json", boolean>;
|
|
166
|
+
readonly inputSchema: ColumnBuilder<readonly BriefField[] | null, "json", boolean>;
|
|
167
|
+
readonly chainTo: ColumnBuilder<FlowChain | null, "json", boolean>;
|
|
168
|
+
readonly cadence: ColumnBuilder<FlowCadence | null, "json", boolean>;
|
|
169
|
+
/** Flow-wide park bound for `human` steps, in ms (a step's own `timeoutMs`
|
|
170
|
+
* wins). Null → the plugin default. `0` = wait forever. */
|
|
171
|
+
readonly humanTimeoutMs: ColumnBuilder<number | null, "integer", boolean>;
|
|
145
172
|
/** Master on/off — gates scheduling. */
|
|
146
173
|
readonly isEnabled: ColumnBuilder<boolean, "boolean", true>;
|
|
147
174
|
readonly metadata: ColumnBuilder<Record<string, unknown> | null, "json", boolean>;
|
|
@@ -177,7 +204,17 @@ export declare const BriefField: Schema.Struct<{
|
|
|
177
204
|
placeholder: Schema.optional<typeof Schema.String>;
|
|
178
205
|
}>;
|
|
179
206
|
|
|
180
|
-
|
|
207
|
+
/** An INTERFACE for the same reason as {@link FlowStep} — it is reached from an
|
|
208
|
+
* exported table (`aiFlows.inputSchema`), so an alias to a mapped type gets
|
|
209
|
+
* expanded structurally into the api report, in an order that is not stable
|
|
210
|
+
* across build scopes. The `Equals` pin below fails to compile on any drift. */
|
|
211
|
+
export declare interface BriefField {
|
|
212
|
+
readonly key: string;
|
|
213
|
+
readonly label: string;
|
|
214
|
+
readonly type: 'text' | 'textarea' | 'number' | 'boolean';
|
|
215
|
+
readonly required?: boolean | undefined;
|
|
216
|
+
readonly placeholder?: string | undefined;
|
|
217
|
+
}
|
|
181
218
|
|
|
182
219
|
/**
|
|
183
220
|
* Build the `flow.run` executor over a live `AppContext` + injected capabilities.
|
|
@@ -221,7 +258,12 @@ export declare const ChainPending: Schema.Struct<{
|
|
|
221
258
|
status: Schema.Literal<["pending", "confirmed", "dismissed"]>;
|
|
222
259
|
}>;
|
|
223
260
|
|
|
224
|
-
|
|
261
|
+
/** An INTERFACE — reached from `aiFlowRuns.chainPending`; see {@link BriefField}. */
|
|
262
|
+
export declare interface ChainPending {
|
|
263
|
+
readonly flowRef: string;
|
|
264
|
+
readonly input: Json;
|
|
265
|
+
readonly status: 'pending' | 'confirmed' | 'dismissed';
|
|
266
|
+
}
|
|
225
267
|
|
|
226
268
|
export declare const clampMaxSteps: (n: number | null | undefined) => number;
|
|
227
269
|
|
|
@@ -257,6 +299,9 @@ export declare interface DefineFlowInput {
|
|
|
257
299
|
};
|
|
258
300
|
readonly chain?: FlowChain;
|
|
259
301
|
readonly cadence?: FlowCadence;
|
|
302
|
+
/** Flow-wide park bound for every `human` step that sets no `timeoutMs` of its
|
|
303
|
+
* own, in ms. `0` = wait forever. */
|
|
304
|
+
readonly humanTimeoutMs?: number;
|
|
260
305
|
}
|
|
261
306
|
|
|
262
307
|
/** Hard-delete a flow row by id. Returns whether a row was removed. */
|
|
@@ -268,7 +313,8 @@ export declare interface EngineDeps {
|
|
|
268
313
|
/** Resolve an `agent` step's `agentRef` → system prompt + model. Absent →
|
|
269
314
|
* agent steps with an `agentRef` fail with FlowCapabilityMissing. */
|
|
270
315
|
readonly resolveAgent?: (agentRef: string) => Effect.Effect<AgentResolution, FlowNotFound, unknown>;
|
|
271
|
-
/** Media generator for image/video/audio steps (
|
|
316
|
+
/** Media generator for image/video/audio steps (`makeMediaGenerator` in
|
|
317
|
+
* `mediaAdapter.ts` is the @voltro/ai-backed implementation). */
|
|
272
318
|
readonly generateMedia?: MediaGenerator;
|
|
273
319
|
/** Fallback model per modality when a step omits `model`. */
|
|
274
320
|
readonly defaultModels?: {
|
|
@@ -288,11 +334,23 @@ export declare interface EngineDeps {
|
|
|
288
334
|
/** Long-term-memory prefix prepended to the orchestrator system prompt (wire
|
|
289
335
|
* to the app's ai_user_memories). Best-effort. */
|
|
290
336
|
readonly memoryPrefix?: (ownerId: string | null) => Effect.Effect<string, never, unknown>;
|
|
337
|
+
/** Default park bound for `human` steps in ms, for flows that set none. Sits
|
|
338
|
+
* between the flow's own `humanTimeoutMs` and the `aiFlowsPlugin({...})`
|
|
339
|
+
* option / `VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS` (see `defaults.ts`).
|
|
340
|
+
* `0` = wait forever. */
|
|
341
|
+
readonly humanReviewTimeoutMs?: number;
|
|
291
342
|
}
|
|
292
343
|
|
|
293
344
|
/** The canonical name the launch action starts + the app re-export registers. */
|
|
294
345
|
export declare const FLOW_RUN_WORKFLOW = "flow.run";
|
|
295
346
|
|
|
347
|
+
/** Deploy-time override for {@link FLOW_RUNS_TTL_HOURS_DEFAULT}, in hours. */
|
|
348
|
+
export declare const FLOW_RUNS_TTL_ENV = "VOLTRO_AI_FLOW_RUNS_TTL_HOURS";
|
|
349
|
+
|
|
350
|
+
/** Framework default retention for `_voltro_ai_flow_runs`: 90 days of finished
|
|
351
|
+
* runs. Only TERMINAL runs are swept — see `index.ts`. */
|
|
352
|
+
export declare const FLOW_RUNS_TTL_HOURS_DEFAULT: number;
|
|
353
|
+
|
|
296
354
|
/** A required brief field was blank at launch. */
|
|
297
355
|
declare class FlowBriefIncomplete extends FlowBriefIncomplete_base {
|
|
298
356
|
}
|
|
@@ -322,7 +380,25 @@ export declare const FlowCadence: Schema.Struct<{
|
|
|
322
380
|
defaultInput: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
323
381
|
}>;
|
|
324
382
|
|
|
325
|
-
|
|
383
|
+
/**
|
|
384
|
+
* An INTERFACE — reached from `aiFlows.cadence`; see {@link BriefField}.
|
|
385
|
+
*
|
|
386
|
+
* This one is not hypothetical: a single-package `api:report` and a
|
|
387
|
+
* full-monorepo build emitted `hour`/`minute` in DIFFERENT positions inside the
|
|
388
|
+
* structurally-expanded alias, so the api-surface gate rejected a file nobody
|
|
389
|
+
* had touched, showing the same members moving. That is the exact failure
|
|
390
|
+
* {@link FlowStep}'s comment describes.
|
|
391
|
+
*/
|
|
392
|
+
export declare interface FlowCadence {
|
|
393
|
+
readonly frequency?: 'weekly' | 'monthly' | undefined;
|
|
394
|
+
readonly repeats: ReadonlyArray<number>;
|
|
395
|
+
readonly intervalWeeks?: number | undefined;
|
|
396
|
+
readonly anchorDate?: string | undefined;
|
|
397
|
+
readonly weekOfMonth?: 1 | 2 | 3 | 4 | 'last' | undefined;
|
|
398
|
+
readonly hour?: number | undefined;
|
|
399
|
+
readonly minute?: 0 | 15 | 30 | 45 | undefined;
|
|
400
|
+
readonly defaultInput?: Json | undefined;
|
|
401
|
+
}
|
|
326
402
|
|
|
327
403
|
/** A generation step required a capability the host did not provide (e.g. a
|
|
328
404
|
* media modality with no configured generator, or storage for the artifact). */
|
|
@@ -347,7 +423,15 @@ export declare const FlowChain: Schema.Struct<{
|
|
|
347
423
|
requireConfirmation: Schema.optional<typeof Schema.Boolean>;
|
|
348
424
|
}>;
|
|
349
425
|
|
|
350
|
-
|
|
426
|
+
/** An INTERFACE — reached from `aiFlows.chainTo`; see {@link BriefField}. */
|
|
427
|
+
export declare interface FlowChain {
|
|
428
|
+
readonly flowRef: string;
|
|
429
|
+
readonly mappings: ReadonlyArray<{
|
|
430
|
+
readonly targetKey: string;
|
|
431
|
+
readonly sourceKey: string;
|
|
432
|
+
}>;
|
|
433
|
+
readonly requireConfirmation?: boolean | undefined;
|
|
434
|
+
}
|
|
351
435
|
|
|
352
436
|
/** The raw flow definition either front door supplies before normalization.
|
|
353
437
|
* Optional fields tolerate explicit `undefined` (row reads produce it). */
|
|
@@ -361,6 +445,7 @@ export declare interface FlowDefinitionInput {
|
|
|
361
445
|
readonly orchestratorInstructions?: string | null | undefined;
|
|
362
446
|
readonly chain?: FlowChain | null | undefined;
|
|
363
447
|
readonly cadence?: FlowCadence | null | undefined;
|
|
448
|
+
readonly humanTimeoutMs?: number | null | undefined;
|
|
364
449
|
}
|
|
365
450
|
|
|
366
451
|
/** The single representation the engine interprets, from either front door. */
|
|
@@ -376,6 +461,10 @@ export declare interface FlowIR {
|
|
|
376
461
|
};
|
|
377
462
|
readonly chain?: FlowChain;
|
|
378
463
|
readonly cadence?: FlowCadence;
|
|
464
|
+
/** Flow-wide default for a `human` step's park bound, in ms. A step's own
|
|
465
|
+
* `timeoutMs` wins; absent here too → the engine/plugin default. `0` = wait
|
|
466
|
+
* forever. */
|
|
467
|
+
readonly humanTimeoutMs?: number;
|
|
379
468
|
}
|
|
380
469
|
|
|
381
470
|
/** A lifecycle event the host can turn into a notification (best-effort). */
|
|
@@ -479,6 +568,11 @@ export declare const FlowStep: Schema.Struct<{
|
|
|
479
568
|
value: typeof Schema.String;
|
|
480
569
|
label: typeof Schema.String;
|
|
481
570
|
}>>>;
|
|
571
|
+
/** `human` step only — how long the run parks awaiting this review before it
|
|
572
|
+
* fails, in milliseconds. Omitted → the flow's `humanTimeoutMs`, then the
|
|
573
|
+
* engine/plugin default (see `resolveHumanReviewTimeoutMs`). `0` means WAIT
|
|
574
|
+
* FOREVER (the park is slot-free, so an unbounded wait costs no worker). */
|
|
575
|
+
timeoutMs: Schema.optional<typeof Schema.Number>;
|
|
482
576
|
}>;
|
|
483
577
|
|
|
484
578
|
/**
|
|
@@ -519,6 +613,7 @@ export declare interface FlowStep {
|
|
|
519
613
|
readonly schema?: Json | undefined;
|
|
520
614
|
readonly reviewMode?: ReviewMode | undefined;
|
|
521
615
|
readonly options?: ReadonlyArray<ReviewOption> | undefined;
|
|
616
|
+
readonly timeoutMs?: number | undefined;
|
|
522
617
|
}
|
|
523
618
|
|
|
524
619
|
/** Typed builders for each step kind — terser + safer than hand-writing the
|
|
@@ -566,7 +661,8 @@ export declare const flowStep: {
|
|
|
566
661
|
prompt: string;
|
|
567
662
|
outputKey?: string;
|
|
568
663
|
}) => FlowStepDraft;
|
|
569
|
-
/** Pause for human review.
|
|
664
|
+
/** Pause for human review. `timeoutMs` bounds the park (default: the flow's
|
|
665
|
+
* `humanTimeoutMs`, then the plugin default — 7 days; `0` = wait forever). */
|
|
570
666
|
human: (o: {
|
|
571
667
|
title?: string;
|
|
572
668
|
description?: string;
|
|
@@ -574,12 +670,16 @@ export declare const flowStep: {
|
|
|
574
670
|
options?: ReadonlyArray<ReviewOption>;
|
|
575
671
|
prompt?: string;
|
|
576
672
|
outputKey?: string;
|
|
673
|
+
timeoutMs?: number;
|
|
577
674
|
}) => FlowStepDraft;
|
|
578
675
|
};
|
|
579
676
|
|
|
580
677
|
/** A step without its `id` — `defineFlow` assigns stable index-based ids. */
|
|
581
678
|
export declare type FlowStepDraft = Omit<FlowStep, 'id'>;
|
|
582
679
|
|
|
680
|
+
/** The recorded `app.config.ts` tunables. */
|
|
681
|
+
export declare const getAiFlowsDefaults: () => AiFlowsDefaults;
|
|
682
|
+
|
|
583
683
|
/** One stored flow by id, or undefined (tenant-scoped by the runtime). */
|
|
584
684
|
export declare const getFlow: (ctx: AppContext, args: {
|
|
585
685
|
id: string;
|
|
@@ -588,8 +688,18 @@ export declare const getFlow: (ctx: AppContext, args: {
|
|
|
588
688
|
/** Resolve a code-registered flow by name, or `undefined` for a data flow. */
|
|
589
689
|
export declare const getRegisteredFlow: (name: string) => FlowIR | undefined;
|
|
590
690
|
|
|
591
|
-
/**
|
|
592
|
-
|
|
691
|
+
/** Namespace of the signal a `human` step parks on. Never used on its own —
|
|
692
|
+
* the signal a step actually awaits is {@link humanResponseSignalName}. */
|
|
693
|
+
export declare const HUMAN_RESPONSE_SIGNAL_PREFIX = "flow-human-response";
|
|
694
|
+
|
|
695
|
+
/** Deploy-time override for {@link HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT}, in
|
|
696
|
+
* hours. `0` (or a negative value) means WAIT FOREVER. */
|
|
697
|
+
export declare const HUMAN_REVIEW_TIMEOUT_ENV = "VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS";
|
|
698
|
+
|
|
699
|
+
/** Framework default park bound for a human review: 7 days. Long enough to
|
|
700
|
+
* survive a weekend + a holiday Monday, short enough that an abandoned review
|
|
701
|
+
* eventually settles instead of pinning a run forever. */
|
|
702
|
+
export declare const HUMAN_REVIEW_TIMEOUT_HOURS_DEFAULT: number;
|
|
593
703
|
|
|
594
704
|
/** The HITL answer, written by `respond`. */
|
|
595
705
|
export declare const HumanResponse: Schema.Struct<{
|
|
@@ -599,7 +709,38 @@ export declare const HumanResponse: Schema.Struct<{
|
|
|
599
709
|
respondedAt: Schema.optional<typeof Schema.String>;
|
|
600
710
|
}>;
|
|
601
711
|
|
|
602
|
-
|
|
712
|
+
/** An INTERFACE — reached from `aiFlowRuns.humanResponse`; see {@link BriefField}. */
|
|
713
|
+
export declare interface HumanResponse {
|
|
714
|
+
readonly decision?: 'approve' | 'reject' | undefined;
|
|
715
|
+
readonly value?: string | undefined;
|
|
716
|
+
readonly text?: string | undefined;
|
|
717
|
+
readonly respondedAt?: string | undefined;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* The signal name ONE human step parks on, derived from that step's position in
|
|
722
|
+
* the (journal-pinned) plan.
|
|
723
|
+
*
|
|
724
|
+
* **Why this is per-step and not one constant.** `awaitSignalSuspending` derives
|
|
725
|
+
* its `DurableDeferred` from workflow-name + signal-name per execution, so a
|
|
726
|
+
* single `'flow-human-response'` for every human step in a flow meant the SECOND
|
|
727
|
+
* review awaited the deferred the FIRST answer had already completed — it
|
|
728
|
+
* resolved instantly, with the first reviewer's payload, and the run finished
|
|
729
|
+
* carrying an approval nobody gave. Measured before the fix: a two-review flow,
|
|
730
|
+
* one answer, `status: 'succeeded'`, `output: { first: 'answer-one', second:
|
|
731
|
+
* 'answer-one' }`. The same collision aliased the wait's durable timeout clock
|
|
732
|
+
* (`await-signal-timeout/<name>`), so the second park inherited the first's
|
|
733
|
+
* expiry too.
|
|
734
|
+
*
|
|
735
|
+
* **Why the INDEX is the identity.** It must be identical on every replay and
|
|
736
|
+
* derivable by the responder without re-resolving the flow definition (which may
|
|
737
|
+
* have been edited mid-run). The step list is pinned in the run's journal at
|
|
738
|
+
* step 0, so a step's index is fixed for the life of the run; the responder
|
|
739
|
+
* reads it back off the run row's live timeline. A counter, a clock, or a
|
|
740
|
+
* `randomUUID` would all break replay; the authored step `id` would break the
|
|
741
|
+
* moment a definition is re-ordered under a live run.
|
|
742
|
+
*/
|
|
743
|
+
export declare const humanResponseSignalName: (stepIndex: number) => string;
|
|
603
744
|
|
|
604
745
|
/** Replace `{{key}}` with `context[key]` (objects/arrays JSON-stringified; an
|
|
605
746
|
* absent/null value renders empty). */
|
|
@@ -610,6 +751,25 @@ export declare const Json: Schema.Record$<typeof Schema.String, typeof Schema.Un
|
|
|
610
751
|
|
|
611
752
|
export declare type Json = typeof Json.Type;
|
|
612
753
|
|
|
754
|
+
/** A JSON-Schema node as stored on a `structured` step. */
|
|
755
|
+
export declare type JsonSchemaNode = Record<string, unknown>;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Adapt a `structured` step's JSON Schema to the Effect `Schema` the engine
|
|
759
|
+
* hands `generateObject`. An absent / unusable schema falls back to the open
|
|
760
|
+
* record, so a step authored without one behaves exactly as before.
|
|
761
|
+
*
|
|
762
|
+
* ```ts
|
|
763
|
+
* jsonSchemaToEffectSchema({
|
|
764
|
+
* type: 'object',
|
|
765
|
+
* properties: { title: { type: 'string' }, tags: { type: 'array', items: { type: 'string' } } },
|
|
766
|
+
* required: ['title'],
|
|
767
|
+
* })
|
|
768
|
+
* // ≡ Schema.Struct({ title: Schema.String, tags: Schema.optional(Schema.Array(Schema.String)) })
|
|
769
|
+
* ```
|
|
770
|
+
*/
|
|
771
|
+
export declare const jsonSchemaToEffectSchema: (jsonSchema: JsonSchemaNode | undefined) => Schema.Schema<unknown, unknown>;
|
|
772
|
+
|
|
613
773
|
/** Launch a fresh run of a flow (by code name or row id). Validates the brief,
|
|
614
774
|
* creates the run row, and starts the durable `flow.run` workflow. */
|
|
615
775
|
export declare const launchFlow: (ctx: AppContext, args: {
|
|
@@ -745,16 +905,38 @@ export declare const normalizeFlow: (def: FlowDefinitionInput) => FlowIR;
|
|
|
745
905
|
* `defineFlow` when the module is loaded. */
|
|
746
906
|
export declare const registerFlow: (ir: FlowIR) => void;
|
|
747
907
|
|
|
908
|
+
/** Test seam — forget the recorded tunables. */
|
|
909
|
+
export declare const resetAiFlowsDefaults: () => void;
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Resolve a human step's park bound down the precedence ladder. Pure — the env
|
|
913
|
+
* read is passed in so a test can drive it without touching `process.env`.
|
|
914
|
+
*/
|
|
915
|
+
export declare const resolveHumanReviewTimeoutMs: (input: {
|
|
916
|
+
readonly step?: {
|
|
917
|
+
readonly timeoutMs?: number | undefined;
|
|
918
|
+
};
|
|
919
|
+
readonly flow?: {
|
|
920
|
+
readonly humanTimeoutMs?: number | undefined;
|
|
921
|
+
};
|
|
922
|
+
readonly deps?: {
|
|
923
|
+
readonly humanReviewTimeoutMs?: number | undefined;
|
|
924
|
+
};
|
|
925
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
926
|
+
}) => number;
|
|
927
|
+
|
|
748
928
|
/** Resolve the IR: code registry by name first, else the stored `ai_flows` row. */
|
|
749
929
|
export declare const resolveIr: (ctx: AppContext, flowRef: string) => Effect.Effect<FlowIR, FlowNotFound>;
|
|
750
930
|
|
|
751
931
|
/** Record a human's answer to a `waiting` run + signal the parked workflow to
|
|
752
|
-
* resume.
|
|
932
|
+
* resume. The signal is addressed to THAT STEP's own durable deferred — one
|
|
933
|
+
* shared name meant a later review resolved with an earlier answer. */
|
|
753
934
|
export declare const respondToFlow: (ctx: AppContext, args: {
|
|
754
935
|
runId: string;
|
|
755
936
|
response: HumanResponse;
|
|
756
937
|
}) => Effect.Effect<{
|
|
757
938
|
runId: string;
|
|
939
|
+
stepIndex: number;
|
|
758
940
|
}, FlowRunNotFound | FlowNotAwaitingResponse, never>;
|
|
759
941
|
|
|
760
942
|
/** Re-run a run from its first unfinished step. Reuses the SAME requestId so the
|
|
@@ -871,6 +1053,9 @@ export declare type RunStepStatus = typeof RunStepStatus.Type;
|
|
|
871
1053
|
/** Sanitize an outputKey to the `{{ref}}`-safe charset. */
|
|
872
1054
|
export declare const sanitizeOutputKey: (key: string) => string;
|
|
873
1055
|
|
|
1056
|
+
/** Record the `app.config.ts` tunables (called by the plugin factory). */
|
|
1057
|
+
export declare const setAiFlowsDefaults: (defaults: AiFlowsDefaults) => void;
|
|
1058
|
+
|
|
874
1059
|
/** The five step types. `generate` fans out to four modalities. */
|
|
875
1060
|
export declare const StepType: Schema.Literal<["agent", "generate", "structured", "note", "human"]>;
|
|
876
1061
|
|
|
@@ -905,4 +1090,16 @@ export declare const Visibility: Schema.Literal<["private", "organization", "sha
|
|
|
905
1090
|
|
|
906
1091
|
export declare type Visibility = typeof Visibility.Type;
|
|
907
1092
|
|
|
1093
|
+
/**
|
|
1094
|
+
* Which human step a `waiting` run is parked on — the index the engine used to
|
|
1095
|
+
* derive the step's signal name.
|
|
1096
|
+
*
|
|
1097
|
+
* Read from the LIVE TIMELINE the engine wrote when it parked (`steps[i].status
|
|
1098
|
+
* === 'waiting'`), with `currentStep` as the fallback for a row whose timeline
|
|
1099
|
+
* hasn't been written yet. Deliberately NOT re-resolved from the flow definition:
|
|
1100
|
+
* a definition edited mid-run would hand back a different plan than the one the
|
|
1101
|
+
* run's journal pinned, and the answer would be delivered to the wrong step.
|
|
1102
|
+
*/
|
|
1103
|
+
export declare const waitingStepIndex: (row: Record<string, unknown>) => number;
|
|
1104
|
+
|
|
908
1105
|
export { }
|