@voltro/plugin-ai-flows 0.34.0 → 0.36.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 +235 -0
- package/dist/index.d.ts +168 -8
- package/dist/index.js +420 -277
- package/dist/ir-BOv5uwYI.js +142 -0
- package/dist/ir.d.ts +79 -2
- package/dist/ir.js +2 -104
- package/dist/web.d.ts +48 -2
- package/dist/workflow.d.ts +14 -0
- package/dist/workflow.js +2 -1
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,15 @@ export declare const aiFlowRunsTable: Table<"_voltro_ai_flow_runs", FieldDefinit
|
|
|
45
45
|
readonly humanResponse: ColumnBuilder<HumanResponse | null, "json", boolean>;
|
|
46
46
|
/** Staged follow-up when the chain requires confirmation. */
|
|
47
47
|
readonly chainPending: ColumnBuilder<ChainPending | null, "json", boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Why a declared `chainTo` did NOT start — a cycle, or the depth ceiling.
|
|
50
|
+
*
|
|
51
|
+
* A column rather than a log line, because the run row is what a user looks
|
|
52
|
+
* at: a chain that silently does not fire is indistinguishable from a chain
|
|
53
|
+
* that was never declared, and "the second flow never ran" is precisely the
|
|
54
|
+
* report this would otherwise generate.
|
|
55
|
+
*/
|
|
56
|
+
readonly chainRefusal: ColumnBuilder<string | null, "text", boolean>;
|
|
48
57
|
/** Accumulated cost in micro-USD (app view projects to €/cents). */
|
|
49
58
|
readonly costMicroUsd: ColumnBuilder<number, "integer", true>;
|
|
50
59
|
readonly durationMs: ColumnBuilder<number | null, "integer", boolean>;
|
|
@@ -72,6 +81,9 @@ export declare const aiFlowRunsTable: Table<"_voltro_ai_flow_runs", FieldDefinit
|
|
|
72
81
|
export declare interface AiFlowsDefaults {
|
|
73
82
|
/** Park bound for a `human` step, in ms. `0` = wait forever. */
|
|
74
83
|
readonly humanReviewTimeoutMs?: number;
|
|
84
|
+
/** How many flows one `chainTo` chain may traverse. See
|
|
85
|
+
* {@link MAX_CHAIN_DEPTH_DEFAULT}. */
|
|
86
|
+
readonly maxChainDepth?: number;
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
/**
|
|
@@ -273,6 +285,11 @@ export declare const clearRegistry: () => void;
|
|
|
273
285
|
/** Every `{{ref}}` name referenced in `text` (order-preserving, may repeat). */
|
|
274
286
|
export declare const collectRefs: (text: string) => ReadonlyArray<string>;
|
|
275
287
|
|
|
288
|
+
/** The comparison a `when:` performs. */
|
|
289
|
+
export declare const ConditionOp: Schema.Literal<["truthy", "falsy", "eq", "neq", "contains"]>;
|
|
290
|
+
|
|
291
|
+
export declare type ConditionOp = typeof ConditionOp.Type;
|
|
292
|
+
|
|
276
293
|
/** Create a flow row. Generates an id when absent; tenant/audit columns are
|
|
277
294
|
* auto-stamped by the runtime. */
|
|
278
295
|
export declare const createFlow: (ctx: AppContext, fields: Record<string, unknown>) => Effect.Effect<Readonly<Record<string, unknown>>, never, never>;
|
|
@@ -309,6 +326,10 @@ export declare const deleteFlow: (ctx: AppContext, args: {
|
|
|
309
326
|
id: string;
|
|
310
327
|
}) => Effect.Effect<boolean, never, never>;
|
|
311
328
|
|
|
329
|
+
/** A one-line rendering for the run timeline and the editor preview. Exported
|
|
330
|
+
* so the reason a step was skipped is the SAME sentence in both places. */
|
|
331
|
+
export declare const describeCondition: (condition: StepCondition) => string;
|
|
332
|
+
|
|
312
333
|
export declare interface EngineDeps {
|
|
313
334
|
/** Resolve an `agent` step's `agentRef` → system prompt + model. Absent →
|
|
314
335
|
* agent steps with an `agentRef` fail with FlowCapabilityMissing. */
|
|
@@ -339,8 +360,24 @@ export declare interface EngineDeps {
|
|
|
339
360
|
* option / `VOLTRO_AI_FLOW_HUMAN_REVIEW_TIMEOUT_HOURS` (see `defaults.ts`).
|
|
340
361
|
* `0` = wait forever. */
|
|
341
362
|
readonly humanReviewTimeoutMs?: number;
|
|
363
|
+
/** How many flows one `chainTo` chain may traverse, INCLUDING the flow that
|
|
364
|
+
* started it. Sits between nothing and the `aiFlowsPlugin({...})` option /
|
|
365
|
+
* `VOLTRO_AI_FLOW_MAX_CHAIN_DEPTH` (see `defaults.ts`). A cycle is refused
|
|
366
|
+
* separately and cannot be raised by this number. */
|
|
367
|
+
readonly maxChainDepth?: number;
|
|
342
368
|
}
|
|
343
369
|
|
|
370
|
+
/**
|
|
371
|
+
* Evaluate `condition` against a run context.
|
|
372
|
+
*
|
|
373
|
+
* A condition on a ref the context does not carry evaluates as ABSENT — false
|
|
374
|
+
* for `truthy`/`eq`/`contains`, true for `falsy`/`neq`. That asymmetry is the
|
|
375
|
+
* honest reading of "the producing step did not run", and it is why
|
|
376
|
+
* `validateFlow` refuses a dangling ref at registration: at run time, a typo and
|
|
377
|
+
* a genuinely-skipped producer are indistinguishable here.
|
|
378
|
+
*/
|
|
379
|
+
export declare const evaluateCondition: (condition: StepCondition, context: Readonly<Record<string, unknown>>) => boolean;
|
|
380
|
+
|
|
344
381
|
/** The canonical name the launch action starts + the app re-export registers. */
|
|
345
382
|
export declare const FLOW_RUN_WORKFLOW = "flow.run";
|
|
346
383
|
|
|
@@ -525,8 +562,34 @@ export declare interface FlowRunPayload {
|
|
|
525
562
|
readonly input: Record<string, unknown>;
|
|
526
563
|
readonly source: 'manual' | 'cron';
|
|
527
564
|
readonly requestId: string;
|
|
565
|
+
readonly chainPath?: ReadonlyArray<string> | undefined;
|
|
528
566
|
}
|
|
529
567
|
|
|
568
|
+
/** One unit of execution: a single step, or a set that runs concurrently. */
|
|
569
|
+
export declare interface FlowSegment {
|
|
570
|
+
/** `undefined` for an ungrouped single step. */
|
|
571
|
+
readonly group?: string | undefined;
|
|
572
|
+
/** The steps in this segment, with their ORIGINAL indices — the durable step
|
|
573
|
+
* name and the timeline slot both key off the index, so it travels. */
|
|
574
|
+
readonly steps: ReadonlyArray<{
|
|
575
|
+
readonly index: number;
|
|
576
|
+
readonly step: FlowStep;
|
|
577
|
+
}>;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Split a step list into execution segments.
|
|
582
|
+
*
|
|
583
|
+
* Only CONSECUTIVE steps sharing a group name form a segment. A group that
|
|
584
|
+
* reappears after an interruption forms a SECOND segment — which is almost
|
|
585
|
+
* certainly not what the author meant, so `validateFlow` refuses it rather than
|
|
586
|
+
* letting this function silently produce two sequential fan-outs from what reads
|
|
587
|
+
* like one. This function stays permissive on purpose: it is used by the
|
|
588
|
+
* validator, and a validator whose input has already been sanitised cannot
|
|
589
|
+
* report on it.
|
|
590
|
+
*/
|
|
591
|
+
export declare const flowSegments: (steps: ReadonlyArray<FlowStep>) => ReadonlyArray<FlowSegment>;
|
|
592
|
+
|
|
530
593
|
/** Flow-definition lifecycle. */
|
|
531
594
|
export declare const FlowStatus: Schema.Literal<["draft", "active", "archived"]>;
|
|
532
595
|
|
|
@@ -568,6 +631,24 @@ export declare const FlowStep: Schema.Struct<{
|
|
|
568
631
|
value: typeof Schema.String;
|
|
569
632
|
label: typeof Schema.String;
|
|
570
633
|
}>>>;
|
|
634
|
+
/** Gate this step on a prior value. Absent → the step always runs. A step
|
|
635
|
+
* whose condition is false is SKIPPED, not failed: it produces no output, so
|
|
636
|
+
* anything referencing its `outputKey` sees an absent value. */
|
|
637
|
+
when: Schema.optional<Schema.Struct<{
|
|
638
|
+
ref: typeof Schema.String;
|
|
639
|
+
op: Schema.Literal<["truthy", "falsy", "eq", "neq", "contains"]>;
|
|
640
|
+
value: Schema.optional<typeof Schema.Unknown>;
|
|
641
|
+
}>>;
|
|
642
|
+
/**
|
|
643
|
+
* Fan-out group. CONSECUTIVE steps sharing a group name run CONCURRENTLY,
|
|
644
|
+
* each still journaled as its own durable step.
|
|
645
|
+
*
|
|
646
|
+
* Steps in one group may not reference each other's outputs — they have no
|
|
647
|
+
* order between them — and `validateFlow` refuses a flow that tries. A `human`
|
|
648
|
+
* step may not join a group either: it suspends the whole workflow, which is
|
|
649
|
+
* not a thing one branch of a fan-out can do.
|
|
650
|
+
*/
|
|
651
|
+
group: Schema.optional<typeof Schema.String>;
|
|
571
652
|
/** `human` step only — how long the run parks awaiting this review before it
|
|
572
653
|
* fails, in milliseconds. Omitted → the flow's `humanTimeoutMs`, then the
|
|
573
654
|
* engine/plugin default (see `resolveHumanReviewTimeoutMs`). `0` means WAIT
|
|
@@ -613,6 +694,8 @@ export declare interface FlowStep {
|
|
|
613
694
|
readonly schema?: Json | undefined;
|
|
614
695
|
readonly reviewMode?: ReviewMode | undefined;
|
|
615
696
|
readonly options?: ReadonlyArray<ReviewOption> | undefined;
|
|
697
|
+
readonly when?: StepCondition | undefined;
|
|
698
|
+
readonly group?: string | undefined;
|
|
616
699
|
readonly timeoutMs?: number | undefined;
|
|
617
700
|
}
|
|
618
701
|
|
|
@@ -626,7 +709,7 @@ export declare const flowStep: {
|
|
|
626
709
|
prompt: string;
|
|
627
710
|
model?: string;
|
|
628
711
|
outputKey?: string;
|
|
629
|
-
}) => FlowStepDraft;
|
|
712
|
+
} & StepControls) => FlowStepDraft;
|
|
630
713
|
/** An image/video/audio generation. */
|
|
631
714
|
media: (modality: Modality, o: {
|
|
632
715
|
title?: string;
|
|
@@ -635,7 +718,7 @@ export declare const flowStep: {
|
|
|
635
718
|
model?: string;
|
|
636
719
|
params?: Record<string, unknown>;
|
|
637
720
|
outputKey?: string;
|
|
638
|
-
}) => FlowStepDraft;
|
|
721
|
+
} & StepControls) => FlowStepDraft;
|
|
639
722
|
/** Delegate to an allowed sub-agent (text-only). */
|
|
640
723
|
agent: (o: {
|
|
641
724
|
title?: string;
|
|
@@ -644,7 +727,7 @@ export declare const flowStep: {
|
|
|
644
727
|
prompt: string;
|
|
645
728
|
model?: string;
|
|
646
729
|
outputKey?: string;
|
|
647
|
-
}) => FlowStepDraft;
|
|
730
|
+
} & StepControls) => FlowStepDraft;
|
|
648
731
|
/** Return a JSON object validated against a JSON Schema. */
|
|
649
732
|
structured: (o: {
|
|
650
733
|
title?: string;
|
|
@@ -653,14 +736,14 @@ export declare const flowStep: {
|
|
|
653
736
|
schema: Record<string, unknown>;
|
|
654
737
|
model?: string;
|
|
655
738
|
outputKey?: string;
|
|
656
|
-
}) => FlowStepDraft;
|
|
739
|
+
} & StepControls) => FlowStepDraft;
|
|
657
740
|
/** Free-text guidance — the interpolated prompt itself is the output. */
|
|
658
741
|
note: (o: {
|
|
659
742
|
title?: string;
|
|
660
743
|
description?: string;
|
|
661
744
|
prompt: string;
|
|
662
745
|
outputKey?: string;
|
|
663
|
-
}) => FlowStepDraft;
|
|
746
|
+
} & StepControls) => FlowStepDraft;
|
|
664
747
|
/** Pause for human review. `timeoutMs` bounds the park (default: the flow's
|
|
665
748
|
* `humanTimeoutMs`, then the plugin default — 7 days; `0` = wait forever). */
|
|
666
749
|
human: (o: {
|
|
@@ -671,7 +754,7 @@ export declare const flowStep: {
|
|
|
671
754
|
prompt?: string;
|
|
672
755
|
outputKey?: string;
|
|
673
756
|
timeoutMs?: number;
|
|
674
|
-
}) => FlowStepDraft;
|
|
757
|
+
} & Pick<StepControls, "when">) => FlowStepDraft;
|
|
675
758
|
};
|
|
676
759
|
|
|
677
760
|
/** A step without its `id` — `defineFlow` assigns stable index-based ids. */
|
|
@@ -746,6 +829,20 @@ export declare const humanResponseSignalName: (stepIndex: number) => string;
|
|
|
746
829
|
* absent/null value renders empty). */
|
|
747
830
|
export declare const interpolate: (text: string, context: Record<string, unknown>) => string;
|
|
748
831
|
|
|
832
|
+
/**
|
|
833
|
+
* Truthiness, defined once so the engine and the editor cannot disagree.
|
|
834
|
+
*
|
|
835
|
+
* Deliberately NOT JavaScript's: `0` and `''` are falsy in JS, and a step gated
|
|
836
|
+
* on a count or a generated string would then be skipped for a legitimate value.
|
|
837
|
+
* A flow author writing `when: { ref: 'count', op: 'truthy' }` means "there is a
|
|
838
|
+
* count", not "the count is non-zero" — the second is `{ op: 'neq', value: 0 }`,
|
|
839
|
+
* which they can say if they mean it.
|
|
840
|
+
*
|
|
841
|
+
* Absent, null and the empty ARRAY are the falsy set: those are the three
|
|
842
|
+
* shapes a step that produced nothing actually leaves behind.
|
|
843
|
+
*/
|
|
844
|
+
export declare const isTruthy: (v: unknown) => boolean;
|
|
845
|
+
|
|
749
846
|
/** A JSON value (for `params` / `input` / a `structured` step's JSON Schema). */
|
|
750
847
|
export declare const Json: Schema.Record$<typeof Schema.String, typeof Schema.Unknown>;
|
|
751
848
|
|
|
@@ -798,6 +895,20 @@ export declare const makeMediaGenerator: (persist: MediaPersist, opts?: {
|
|
|
798
895
|
readonly resolveModel?: (model: string) => ProviderConfig;
|
|
799
896
|
}) => MediaGenerator;
|
|
800
897
|
|
|
898
|
+
/**
|
|
899
|
+
* How many flows one chain may traverse, including the flow that started it.
|
|
900
|
+
*
|
|
901
|
+
* Five, because a chain is a hand-authored pipeline and nobody writes six on
|
|
902
|
+
* purpose — but the number is a FIELD rather than a constant precisely because
|
|
903
|
+
* "nobody does that" is an assumption about other people's apps. A cycle is
|
|
904
|
+
* refused separately and unconditionally; this bounds the acyclic case, where
|
|
905
|
+
* every hop is a real LLM run somebody pays for.
|
|
906
|
+
*/
|
|
907
|
+
export declare const MAX_CHAIN_DEPTH_DEFAULT = 5;
|
|
908
|
+
|
|
909
|
+
/** Deploy-time override for {@link MAX_CHAIN_DEPTH_DEFAULT}. */
|
|
910
|
+
export declare const MAX_CHAIN_DEPTH_ENV = "VOLTRO_AI_FLOW_MAX_CHAIN_DEPTH";
|
|
911
|
+
|
|
801
912
|
/** Legacy default was 30, clamped to [1,100]. (Distinct from `@voltro/ai`'s
|
|
802
913
|
* own `maxSteps` default of 8 for a single tool loop.) */
|
|
803
914
|
export declare const MAX_STEPS_DEFAULT = 30;
|
|
@@ -894,6 +1005,9 @@ export declare type Modality = typeof Modality.Type;
|
|
|
894
1005
|
*/
|
|
895
1006
|
export declare const nextRuns: (cadence: FlowCadence, from: Date, count?: number) => ReadonlyArray<Date>;
|
|
896
1007
|
|
|
1008
|
+
/** Group names that appear in more than one segment — a non-contiguous group. */
|
|
1009
|
+
export declare const nonContiguousGroups: (segments: ReadonlyArray<FlowSegment>) => ReadonlyArray<string>;
|
|
1010
|
+
|
|
897
1011
|
/**
|
|
898
1012
|
* Lower a raw flow definition (from code or a row) to the normalized IR:
|
|
899
1013
|
* default the mode, clamp maxSteps, sanitize outputKeys, drop empties. Pure +
|
|
@@ -928,6 +1042,20 @@ export declare const resolveHumanReviewTimeoutMs: (input: {
|
|
|
928
1042
|
/** Resolve the IR: code registry by name first, else the stored `ai_flows` row. */
|
|
929
1043
|
export declare const resolveIr: (ctx: AppContext, flowRef: string) => Effect.Effect<FlowIR, FlowNotFound>;
|
|
930
1044
|
|
|
1045
|
+
/**
|
|
1046
|
+
* Resolve the chain-depth ceiling down the same ladder as every other tunable:
|
|
1047
|
+
* engine deps → plugin option (`app.config.ts`) → env → framework default.
|
|
1048
|
+
*
|
|
1049
|
+
* A value below 1 is IGNORED rather than honoured. `0` would mean "no flow may
|
|
1050
|
+
* chain at all", which is expressible by not declaring a chain, and reading it
|
|
1051
|
+
* literally would turn a typo into a silently disabled feature — the same
|
|
1052
|
+
* reasoning `msFromHoursEnv` applies to a negative timeout.
|
|
1053
|
+
*/
|
|
1054
|
+
export declare const resolveMaxChainDepth: (deps?: {
|
|
1055
|
+
readonly maxChainDepth?: number | undefined;
|
|
1056
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
1057
|
+
}) => number;
|
|
1058
|
+
|
|
931
1059
|
/** Record a human's answer to a `waiting` run + signal the parked workflow to
|
|
932
1060
|
* resume. The signal is addressed to THAT STEP's own durable deferred — one
|
|
933
1061
|
* shared name meant a later review resolved with an earlier answer. */
|
|
@@ -1001,7 +1129,7 @@ export declare const RunStep: Schema.Struct<{
|
|
|
1001
1129
|
title: typeof Schema.String;
|
|
1002
1130
|
description: Schema.optional<typeof Schema.String>;
|
|
1003
1131
|
type: Schema.Literal<["agent", "generate", "structured", "note", "human"]>;
|
|
1004
|
-
status: Schema.Literal<["pending", "running", "waiting", "succeeded", "failed"]>;
|
|
1132
|
+
status: Schema.Literal<["pending", "running", "waiting", "succeeded", "failed", "skipped"]>;
|
|
1005
1133
|
startedAt: Schema.optional<typeof Schema.String>;
|
|
1006
1134
|
completedAt: Schema.optional<typeof Schema.String>;
|
|
1007
1135
|
/** Per-step cost in micro-USD (the app view projects to €/cents). */
|
|
@@ -1015,6 +1143,9 @@ export declare const RunStep: Schema.Struct<{
|
|
|
1015
1143
|
text: typeof Schema.String;
|
|
1016
1144
|
}>>;
|
|
1017
1145
|
errorMessage: Schema.optional<typeof Schema.String>;
|
|
1146
|
+
/** Why a `skipped` step was skipped — the rendered condition, so the timeline
|
|
1147
|
+
* says "{{approved}} is not set" instead of leaving a silent gap. */
|
|
1148
|
+
skipReason: Schema.optional<typeof Schema.String>;
|
|
1018
1149
|
review: Schema.optional<Schema.Struct<{
|
|
1019
1150
|
mode: Schema.Literal<["approve", "choice", "text"]>;
|
|
1020
1151
|
options: Schema.optional<Schema.Array$<Schema.Struct<{
|
|
@@ -1043,10 +1174,11 @@ export declare interface RunStep {
|
|
|
1043
1174
|
readonly text: string;
|
|
1044
1175
|
} | undefined;
|
|
1045
1176
|
readonly errorMessage?: string | undefined;
|
|
1177
|
+
readonly skipReason?: string | undefined;
|
|
1046
1178
|
readonly review?: RunReview | undefined;
|
|
1047
1179
|
}
|
|
1048
1180
|
|
|
1049
|
-
export declare const RunStepStatus: Schema.Literal<["pending", "running", "waiting", "succeeded", "failed"]>;
|
|
1181
|
+
export declare const RunStepStatus: Schema.Literal<["pending", "running", "waiting", "succeeded", "failed", "skipped"]>;
|
|
1050
1182
|
|
|
1051
1183
|
export declare type RunStepStatus = typeof RunStepStatus.Type;
|
|
1052
1184
|
|
|
@@ -1056,6 +1188,34 @@ export declare const sanitizeOutputKey: (key: string) => string;
|
|
|
1056
1188
|
/** Record the `app.config.ts` tunables (called by the plugin factory). */
|
|
1057
1189
|
export declare const setAiFlowsDefaults: (defaults: AiFlowsDefaults) => void;
|
|
1058
1190
|
|
|
1191
|
+
declare const StepCondition: Schema.Struct<{
|
|
1192
|
+
/** A brief-field key or an EARLIER step's `outputKey`. */
|
|
1193
|
+
ref: typeof Schema.String;
|
|
1194
|
+
op: Schema.Literal<["truthy", "falsy", "eq", "neq", "contains"]>;
|
|
1195
|
+
/** The right-hand side for `eq` / `neq` / `contains`. Ignored by the unary ops. */
|
|
1196
|
+
value: Schema.optional<typeof Schema.Unknown>;
|
|
1197
|
+
}>;
|
|
1198
|
+
|
|
1199
|
+
/** An INTERFACE, for the same api-report reason as `FlowStep` — it is reached
|
|
1200
|
+
* from an exported table column, and an alias to a mapped type gets expanded
|
|
1201
|
+
* structurally in an order that is not stable across build scopes. */
|
|
1202
|
+
declare interface StepCondition {
|
|
1203
|
+
readonly ref: string;
|
|
1204
|
+
readonly op: ConditionOp;
|
|
1205
|
+
readonly value?: unknown;
|
|
1206
|
+
}
|
|
1207
|
+
export { StepCondition }
|
|
1208
|
+
export { StepCondition as StepConditionType }
|
|
1209
|
+
|
|
1210
|
+
/** Gating + fan-out, accepted by every builder. Kept as one type so a new
|
|
1211
|
+
* builder cannot quietly omit them — the six builders below spread it. */
|
|
1212
|
+
declare interface StepControls {
|
|
1213
|
+
/** Run this step only when the condition holds; otherwise SKIP it. */
|
|
1214
|
+
readonly when?: StepCondition;
|
|
1215
|
+
/** Consecutive steps sharing a group run CONCURRENTLY. */
|
|
1216
|
+
readonly group?: string;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1059
1219
|
/** The five step types. `generate` fans out to four modalities. */
|
|
1060
1220
|
export declare const StepType: Schema.Literal<["agent", "generate", "structured", "note", "human"]>;
|
|
1061
1221
|
|