octaflow 0.14.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/LICENSE +21 -0
- package/README.md +288 -0
- package/dist/ai/index.d.ts +397 -0
- package/dist/ai/index.js +466 -0
- package/dist/core-ERYGlYsS.js +574 -0
- package/dist/dispatcher-BydjyrgU.d.ts +26 -0
- package/dist/dispatcher-pgboss/index.d.ts +170 -0
- package/dist/dispatcher-pgboss/index.js +301 -0
- package/dist/hooks-CDRFQZbT.d.ts +56 -0
- package/dist/index-D_fOYfmf.d.ts +580 -0
- package/dist/index.d.ts +137 -0
- package/dist/index.js +1426 -0
- package/dist/logger-BCus3AOa.d.ts +10 -0
- package/dist/observability-BsrvbhDr.d.ts +249 -0
- package/dist/store-pg/index.d.ts +195 -0
- package/dist/store-pg/index.js +671 -0
- package/package.json +116 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/core/result.d.ts
|
|
3
|
+
interface FlowErrorShape {
|
|
4
|
+
key: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
type Result<T = void, E extends FlowErrorShape = FlowErrorShape> = {
|
|
8
|
+
ok: true;
|
|
9
|
+
value: T;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
error: E;
|
|
13
|
+
};
|
|
14
|
+
declare const ok: <T>(value: T) => Result<T, never>;
|
|
15
|
+
declare const err: <E extends FlowErrorShape>(error: E) => Result<never, E>;
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/core/types.d.ts
|
|
18
|
+
/** Workflow / step identifiers. Numeric to match common bigserial-backed stores. */
|
|
19
|
+
type WorkflowId = number;
|
|
20
|
+
type StepId = number;
|
|
21
|
+
type WorkflowStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
22
|
+
type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'waiting' | 'mapping' | 'compensating' | 'compensated';
|
|
23
|
+
/**
|
|
24
|
+
* Declarative workflow definition: a DAG of steps with dependencies.
|
|
25
|
+
* Steps without dependencies start immediately and in parallel; a step starts
|
|
26
|
+
* as soon as ALL of its dependencies have completed.
|
|
27
|
+
*/
|
|
28
|
+
interface WorkflowDefinition {
|
|
29
|
+
/** Workflow type identifier (e.g. 'document-enrichment'). */
|
|
30
|
+
type: string;
|
|
31
|
+
/** The steps. Order is irrelevant — execution order is derived from dependencies. */
|
|
32
|
+
steps: StepDefinition[];
|
|
33
|
+
}
|
|
34
|
+
interface StepDefinition {
|
|
35
|
+
/** Unique key within the workflow (e.g. 'analyze-images'). */
|
|
36
|
+
key: string;
|
|
37
|
+
/** Handler type — looked up in the StepHandlerRegistry. */
|
|
38
|
+
type: string;
|
|
39
|
+
/** Keys of steps this step depends on. All must complete before this step runs. */
|
|
40
|
+
dependencies?: string[];
|
|
41
|
+
/** Optional static input baked into the step at definition time. */
|
|
42
|
+
input?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
interface StartOptions {
|
|
45
|
+
/** Optional reference for efficient filtering/lookup (e.g. 'document:123'). */
|
|
46
|
+
entityRef?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Opaque metadata persisted on the workflow row. Add-ons use this as an escape
|
|
49
|
+
* hatch (e.g. the AI add-on stamps `keySource`) without flow-core knowing the shape.
|
|
50
|
+
*/
|
|
51
|
+
metadata?: Record<string, unknown>;
|
|
52
|
+
/**
|
|
53
|
+
* Dedup key (per partition). A start with a key that already exists returns the
|
|
54
|
+
* existing workflow instead of creating a duplicate — so a double-click, retried
|
|
55
|
+
* request, or overlapping cron tick can't start the same work twice.
|
|
56
|
+
*/
|
|
57
|
+
idempotencyKey?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Internal: set by a sub-workflow step to link a child workflow back to the
|
|
60
|
+
* parent workflow + step that started it, so the parent step resumes when the child ends.
|
|
61
|
+
*/
|
|
62
|
+
parentWorkflowId?: WorkflowId;
|
|
63
|
+
parentStepId?: StepId;
|
|
64
|
+
}
|
|
65
|
+
interface WorkflowCreatedResult {
|
|
66
|
+
workflowId: WorkflowId;
|
|
67
|
+
totalSteps: number;
|
|
68
|
+
/** Keys of the steps that were immediately enqueued (the dependency-free roots). */
|
|
69
|
+
enqueuedSteps: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Context passed to a step handler. `context` is the host-provided per-step value
|
|
73
|
+
* (a DI scope, an AI model, domain services) produced by the `buildStepContext`
|
|
74
|
+
* hook — flow-core treats it as opaque.
|
|
75
|
+
*/
|
|
76
|
+
interface StepExecutionContext<TContext = unknown> {
|
|
77
|
+
workflowId: WorkflowId;
|
|
78
|
+
stepId: StepId;
|
|
79
|
+
stepKey: string;
|
|
80
|
+
partitionKey: string;
|
|
81
|
+
/** Workflow-level input. */
|
|
82
|
+
workflowInput: Record<string, unknown>;
|
|
83
|
+
/** Static step-level input from the definition. */
|
|
84
|
+
stepInput: Record<string, unknown>;
|
|
85
|
+
/** Outputs of completed dependency steps, keyed by step key. */
|
|
86
|
+
dependencyOutputs: Record<string, unknown>;
|
|
87
|
+
/** Cancellation signal. */
|
|
88
|
+
signal?: AbortSignal;
|
|
89
|
+
/** Host-provided per-step context. */
|
|
90
|
+
context: TContext;
|
|
91
|
+
}
|
|
92
|
+
interface StepError extends FlowErrorShape {
|
|
93
|
+
key: 'step_error';
|
|
94
|
+
message: string;
|
|
95
|
+
/** Whether the failure is transient and the step should be retried. */
|
|
96
|
+
retryable?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* How `retryable` was decided. `'heuristic'` means nothing authoritative said
|
|
99
|
+
* either way and the default classifier guessed from the error's shape/message —
|
|
100
|
+
* the engine's `defaultRetryable` may override those, and only those.
|
|
101
|
+
*/
|
|
102
|
+
retryableFrom?: 'explicit' | 'predicate' | 'heuristic';
|
|
103
|
+
}
|
|
104
|
+
type StepHandler<TContext = unknown> = (ctx: StepExecutionContext<TContext>) => Promise<Result<Record<string, unknown>, StepError>>;
|
|
105
|
+
/** Context for a step's compensation handler — the execution context plus the step's own output. */
|
|
106
|
+
interface StepCompensationContext<TContext = unknown> extends StepExecutionContext<TContext> {
|
|
107
|
+
/** The output the step produced when it completed (what compensation undoes). */
|
|
108
|
+
output: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Optional rollback handler. On workflow failure the engine runs it once for each
|
|
112
|
+
* `completed` step, in reverse dependency order, to undo side effects. Best-effort: a throw is
|
|
113
|
+
* logged + surfaced on the step (not retried).
|
|
114
|
+
*/
|
|
115
|
+
type StepCompensateHandler<TContext = unknown> = (ctx: StepCompensationContext<TContext>) => Promise<void> | void;
|
|
116
|
+
/** Per-step retry policy. Applied by the engine when a step fails retryably. */
|
|
117
|
+
interface RetryPolicy {
|
|
118
|
+
/** Total attempts including the first (1 = no retry). */
|
|
119
|
+
maxAttempts: number;
|
|
120
|
+
/** Backoff curve between attempts. Default `'fixed'`. */
|
|
121
|
+
backoff?: 'fixed' | 'exponential';
|
|
122
|
+
/** Delay before the 2nd attempt, in ms. Default 1000. */
|
|
123
|
+
initialDelayMs?: number;
|
|
124
|
+
/** Cap on the computed backoff delay, in ms. Default 60000. */
|
|
125
|
+
maxDelayMs?: number;
|
|
126
|
+
}
|
|
127
|
+
/** A registered handler plus its optional retry/timeout/delay policy. */
|
|
128
|
+
interface StepRegistration<TContext = unknown> {
|
|
129
|
+
handler: StepHandler<TContext>;
|
|
130
|
+
retry?: RetryPolicy;
|
|
131
|
+
/** Per-step wall-clock timeout in ms. On expiry the step is aborted + retried. */
|
|
132
|
+
timeoutMs?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Durable start delay in ms: once the step becomes ready (all deps complete), its
|
|
135
|
+
* first dispatch is held for this long via the queue. A no-op handler with a delay
|
|
136
|
+
* is a durable "sleep" step. Does not affect retry backoff.
|
|
137
|
+
*/
|
|
138
|
+
delayMs?: number;
|
|
139
|
+
/**
|
|
140
|
+
* When true, a ready step **suspends** (status `waiting`) instead of being dispatched,
|
|
141
|
+
* until `engine.resumeStep(workflowId, stepKey, payload)` delivers an external event.
|
|
142
|
+
* The handler never runs; the resume payload becomes the step's output.
|
|
143
|
+
*/
|
|
144
|
+
waitForEvent?: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* When true, this is a **map** parent: its handler returns `{ items: T[] }`;
|
|
147
|
+
* the engine spawns one child step (of `childType`) per item, suspends the parent as
|
|
148
|
+
* `mapping`, and completes it with `{ items: childOutputs[] }` once all children finish.
|
|
149
|
+
*/
|
|
150
|
+
map?: boolean;
|
|
151
|
+
/** For a map parent: the step `type` registered for its per-item child steps. */
|
|
152
|
+
childType?: string;
|
|
153
|
+
/**
|
|
154
|
+
* When set, this is a **sub-workflow** step: its handler returns the child
|
|
155
|
+
* workflow's input; the engine starts a child workflow from this definition, suspends
|
|
156
|
+
* the parent step as `waiting`, and resumes it with the child's output once it terminates.
|
|
157
|
+
*/
|
|
158
|
+
subWorkflowDefinition?: WorkflowDefinition;
|
|
159
|
+
/** Optional saga rollback handler: undoes this step's effects on workflow failure. */
|
|
160
|
+
compensate?: StepCompensateHandler<TContext>;
|
|
161
|
+
}
|
|
162
|
+
/** Registry mapping step `type` strings to handlers + their policies. */
|
|
163
|
+
interface StepHandlerRegistry<TContext = unknown> {
|
|
164
|
+
register(type: string, handler: StepHandler<TContext>, options?: {
|
|
165
|
+
retry?: RetryPolicy;
|
|
166
|
+
timeoutMs?: number;
|
|
167
|
+
delayMs?: number;
|
|
168
|
+
waitForEvent?: boolean;
|
|
169
|
+
map?: boolean;
|
|
170
|
+
childType?: string;
|
|
171
|
+
subWorkflowDefinition?: WorkflowDefinition;
|
|
172
|
+
compensate?: StepCompensateHandler<TContext>;
|
|
173
|
+
}): void;
|
|
174
|
+
get(type: string): StepHandler<TContext> | undefined;
|
|
175
|
+
getRegistration(type: string): StepRegistration<TContext> | undefined;
|
|
176
|
+
has(type: string): boolean;
|
|
177
|
+
types(): string[];
|
|
178
|
+
}
|
|
179
|
+
interface WorkflowRecord {
|
|
180
|
+
id: WorkflowId;
|
|
181
|
+
type: string;
|
|
182
|
+
status: WorkflowStatus;
|
|
183
|
+
partitionKey: string;
|
|
184
|
+
input: Record<string, unknown>;
|
|
185
|
+
output: Record<string, unknown> | null;
|
|
186
|
+
error: string | null;
|
|
187
|
+
entityRef: string | null;
|
|
188
|
+
idempotencyKey: string | null;
|
|
189
|
+
/** For a sub-workflow child: the parent workflow + step that started it. */
|
|
190
|
+
parentWorkflowId: WorkflowId | null;
|
|
191
|
+
parentStepId: StepId | null;
|
|
192
|
+
totalSteps: number;
|
|
193
|
+
completedSteps: number;
|
|
194
|
+
failedSteps: number;
|
|
195
|
+
metadata: Record<string, unknown> | null;
|
|
196
|
+
createdAt: string;
|
|
197
|
+
startedAt: string | null;
|
|
198
|
+
completedAt: string | null;
|
|
199
|
+
}
|
|
200
|
+
interface StepRecord {
|
|
201
|
+
id: StepId;
|
|
202
|
+
workflowId: WorkflowId;
|
|
203
|
+
key: string;
|
|
204
|
+
type: string;
|
|
205
|
+
status: StepStatus;
|
|
206
|
+
dependencies: string[];
|
|
207
|
+
input: Record<string, unknown> | null;
|
|
208
|
+
output: Record<string, unknown> | null;
|
|
209
|
+
error: string | null;
|
|
210
|
+
metadata: Record<string, unknown> | null;
|
|
211
|
+
/** Number of execution attempts so far (incremented each time the step runs). */
|
|
212
|
+
attempts: number;
|
|
213
|
+
/** For a map child: the id of its map-parent step; null for normal/keyed steps. */
|
|
214
|
+
parentStepId: StepId | null;
|
|
215
|
+
startedAt: string | null;
|
|
216
|
+
completedAt: string | null;
|
|
217
|
+
}
|
|
218
|
+
interface WorkflowWithSteps extends WorkflowRecord {
|
|
219
|
+
steps: StepRecord[];
|
|
220
|
+
}
|
|
221
|
+
interface WorkflowNotFoundError extends FlowErrorShape {
|
|
222
|
+
key: 'workflow_not_found';
|
|
223
|
+
}
|
|
224
|
+
interface InvalidWorkflowDefinitionError extends FlowErrorShape {
|
|
225
|
+
key: 'invalid_workflow_definition';
|
|
226
|
+
}
|
|
227
|
+
interface StepHandlerNotFoundError extends FlowErrorShape {
|
|
228
|
+
key: 'step_handler_not_found';
|
|
229
|
+
stepType: string;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Engine error type. The named members cover flow-core's own failures; the
|
|
233
|
+
* bare `FlowErrorShape` arm lets hooks (e.g. an AI quota guard in `onBeforeStart`)
|
|
234
|
+
* reject a start with a domain-specific error key the engine just passes through.
|
|
235
|
+
*/
|
|
236
|
+
type FlowError = WorkflowNotFoundError | InvalidWorkflowDefinitionError | StepHandlerNotFoundError | StepError | FlowErrorShape;
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region src/core/defineStep.d.ts
|
|
239
|
+
/**
|
|
240
|
+
* A type-safe step definition with Zod validation schemas, parameterized by the
|
|
241
|
+
* host `TContext`. Created by `defineStep()`, consumed by `buildWorkflow()`.
|
|
242
|
+
*/
|
|
243
|
+
interface TypedStep<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput extends Record<string, unknown> = Record<string, unknown>, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}, TContext = unknown> {
|
|
244
|
+
readonly type: string;
|
|
245
|
+
readonly workflowInputSchema: z.ZodType<TInput>;
|
|
246
|
+
readonly outputSchema: z.ZodType<TOutput>;
|
|
247
|
+
readonly dependencies: TDeps;
|
|
248
|
+
/** Untyped handler for registry compatibility. */
|
|
249
|
+
readonly handler: StepHandler<TContext>;
|
|
250
|
+
/** Optional retry policy for this step type. */
|
|
251
|
+
readonly retry?: RetryPolicy;
|
|
252
|
+
/** Optional per-step wall-clock timeout in ms. */
|
|
253
|
+
readonly timeoutMs?: number;
|
|
254
|
+
/** Optional durable start delay in ms (held in the queue once the step is ready). */
|
|
255
|
+
readonly delayMs?: number;
|
|
256
|
+
/** When true, the step suspends (waiting) until `engine.resumeStep` delivers an event. */
|
|
257
|
+
readonly waitForEvent?: boolean;
|
|
258
|
+
/** When true, this is a map parent — see `defineMapStep`. */
|
|
259
|
+
readonly map?: boolean;
|
|
260
|
+
/** For a map parent: the step type registered for per-item children. */
|
|
261
|
+
readonly childType?: string;
|
|
262
|
+
/** For a map parent: the child step's registration, registered alongside the parent. */
|
|
263
|
+
readonly childRegistration?: {
|
|
264
|
+
type: string;
|
|
265
|
+
handler: StepHandler<TContext>;
|
|
266
|
+
retry?: RetryPolicy;
|
|
267
|
+
timeoutMs?: number;
|
|
268
|
+
};
|
|
269
|
+
/** For a sub-workflow step: the child workflow definition the engine starts. */
|
|
270
|
+
readonly subWorkflowDefinition?: WorkflowDefinition;
|
|
271
|
+
/** For a sub-workflow step: registers the child workflow's step handlers alongside the parent. */
|
|
272
|
+
readonly subWorkflowRegister?: (registry: StepHandlerRegistry<TContext>) => void;
|
|
273
|
+
/** Untyped saga rollback handler, built from the typed `compensate` config. */
|
|
274
|
+
readonly compensate?: StepCompensateHandler<TContext>;
|
|
275
|
+
}
|
|
276
|
+
/** Extract the output type of a typed step. */
|
|
277
|
+
type StepOutput<T> = T extends TypedStep<any, infer O, any, any> ? O : never;
|
|
278
|
+
/** Derive the aggregated workflow output from a steps map: `{ [stepKey]: stepOutput }`. */
|
|
279
|
+
type WorkflowOutput<TSteps extends Record<string, TypedStep<any, any, any, any>>> = { [K in keyof TSteps]: StepOutput<TSteps[K]>; };
|
|
280
|
+
/**
|
|
281
|
+
* Typed execution context passed to step handlers. `workflowInput` is validated
|
|
282
|
+
* against the step's `workflowInputSchema`; each `deps` entry is validated against
|
|
283
|
+
* its dependency's `outputSchema`.
|
|
284
|
+
*/
|
|
285
|
+
interface TypedStepContext<TInput extends Record<string, unknown>, TDeps extends Record<string, TypedStep<any, any, any, TContext>>, TContext> {
|
|
286
|
+
workflowId: number;
|
|
287
|
+
stepId: number;
|
|
288
|
+
stepKey: string;
|
|
289
|
+
partitionKey: string;
|
|
290
|
+
workflowInput: TInput;
|
|
291
|
+
stepInput: Record<string, unknown>;
|
|
292
|
+
deps: { [K in keyof TDeps]: StepOutput<TDeps[K]>; };
|
|
293
|
+
signal?: AbortSignal;
|
|
294
|
+
context: TContext;
|
|
295
|
+
}
|
|
296
|
+
interface DefineStepConfig<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, TDeps extends Record<string, TypedStep<any, any, any, TContext>>, TContext> {
|
|
297
|
+
type: string;
|
|
298
|
+
workflowInputSchema: z.ZodType<TInput>;
|
|
299
|
+
outputSchema: z.ZodType<TOutput>;
|
|
300
|
+
dependencies?: TDeps;
|
|
301
|
+
handler: (ctx: TypedStepContext<TInput, TDeps, TContext>) => Promise<TOutput>;
|
|
302
|
+
/** Optional retry policy (max attempts, backoff). */
|
|
303
|
+
retry?: RetryPolicy;
|
|
304
|
+
/**
|
|
305
|
+
* Decide whether a thrown error is transient, replacing the default message
|
|
306
|
+
* heuristic ({@link isRetryableError}) for this step. An error carrying an
|
|
307
|
+
* explicit marker ({@link markRetryable}) still wins over this.
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* isRetryable: (e) => e instanceof HttpError && e.status >= 500,
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
isRetryable?: (error: unknown) => boolean;
|
|
314
|
+
/** Optional per-step wall-clock timeout in ms. */
|
|
315
|
+
timeoutMs?: number;
|
|
316
|
+
/** Optional durable start delay in ms — held in the queue once the step is ready. */
|
|
317
|
+
delayMs?: number;
|
|
318
|
+
/** When true, the step suspends (waiting) until `engine.resumeStep` delivers an event. */
|
|
319
|
+
waitForEvent?: boolean;
|
|
320
|
+
/**
|
|
321
|
+
* Optional saga rollback handler: on workflow failure the engine runs it once for
|
|
322
|
+
* this step (if it completed), in reverse dependency order. Receives the typed context plus
|
|
323
|
+
* the step's own `output` (what to undo). Best-effort — a throw is logged + surfaced.
|
|
324
|
+
*/
|
|
325
|
+
compensate?: (ctx: TypedStepContext<TInput, TDeps, TContext> & {
|
|
326
|
+
output: TOutput;
|
|
327
|
+
}) => Promise<void> | void;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Define a type-safe workflow step with Zod validation. Wraps a typed handler
|
|
331
|
+
* into an untyped `StepHandler` with a 5-phase pipeline:
|
|
332
|
+
*
|
|
333
|
+
* 1. Parse `workflowInput` against `workflowInputSchema`
|
|
334
|
+
* 2. Parse each dependency output against its `outputSchema`
|
|
335
|
+
* 3. Build the typed context
|
|
336
|
+
* 4. Call the handler
|
|
337
|
+
* 5. Parse the output against `outputSchema`
|
|
338
|
+
*
|
|
339
|
+
* Validation errors are non-retryable (a schema mismatch is a programming error).
|
|
340
|
+
*/
|
|
341
|
+
declare function defineStep<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, TContext = unknown, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: DefineStepConfig<TInput, TOutput, TDeps, TContext>): TypedStep<TInput, TOutput, TDeps, TContext>;
|
|
342
|
+
/**
|
|
343
|
+
* Define a **wait-for-event** step: once its dependencies complete, it suspends
|
|
344
|
+
* (status `waiting`) instead of running, until `engine.resumeStep(workflowId, stepKey,
|
|
345
|
+
* payload)` delivers an external event. The resume payload becomes the step's output
|
|
346
|
+
* (validated by dependents against `outputSchema`), then the DAG advances.
|
|
347
|
+
*
|
|
348
|
+
* Use for human-in-the-loop approvals, webhooks, or any async external dependency.
|
|
349
|
+
*/
|
|
350
|
+
declare function defineWaitStep<TOutput extends Record<string, unknown> = Record<string, unknown>, TContext = unknown, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: {
|
|
351
|
+
type: string;
|
|
352
|
+
/** Shape of the event payload delivered via `resumeStep`. */
|
|
353
|
+
outputSchema: z.ZodType<TOutput>;
|
|
354
|
+
dependencies?: TDeps;
|
|
355
|
+
}): TypedStep<Record<string, never>, TOutput, TDeps, TContext>;
|
|
356
|
+
/**
|
|
357
|
+
* Define a **map** step: dynamic fan-out. `items(ctx)` produces a runtime-sized
|
|
358
|
+
* list from the step's deps/input; the engine spawns one child per item (each running
|
|
359
|
+
* `each(item, …)` with its own retry/timeout), suspends the parent as `mapping`, and
|
|
360
|
+
* completes it with `{ items: childOutputs[] }` (ordered) once all children finish. A
|
|
361
|
+
* failed item fails the whole map. Use for "do X for each of N images/sections/locales".
|
|
362
|
+
*
|
|
363
|
+
* The map step's output type is `{ items: TItemOutput[] }`; dependents read `deps.X.items`.
|
|
364
|
+
*/
|
|
365
|
+
declare function defineMapStep<TItem, TItemOutput extends Record<string, unknown>, TWorkflowInput extends Record<string, unknown> = Record<string, unknown>, TContext = unknown, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: {
|
|
366
|
+
type: string;
|
|
367
|
+
workflowInputSchema: z.ZodType<TWorkflowInput>;
|
|
368
|
+
/** Schema for one item's output. */
|
|
369
|
+
itemOutputSchema: z.ZodType<TItemOutput>;
|
|
370
|
+
dependencies?: TDeps;
|
|
371
|
+
/** Produce the list of items to fan out over. */
|
|
372
|
+
items: (ctx: TypedStepContext<TWorkflowInput, TDeps, TContext>) => Promise<TItem[]> | TItem[];
|
|
373
|
+
/** Process one item. */
|
|
374
|
+
each: (item: TItem, info: {
|
|
375
|
+
index: number;
|
|
376
|
+
context: TContext;
|
|
377
|
+
workflowId: number;
|
|
378
|
+
partitionKey: string;
|
|
379
|
+
}) => Promise<TItemOutput> | TItemOutput;
|
|
380
|
+
/** Optional per-item retry policy. */
|
|
381
|
+
itemRetry?: RetryPolicy;
|
|
382
|
+
/** Per-item retryability predicate — see `defineStep`'s `isRetryable`. */
|
|
383
|
+
itemIsRetryable?: (error: unknown) => boolean;
|
|
384
|
+
/** Optional per-item wall-clock timeout in ms. */
|
|
385
|
+
itemTimeoutMs?: number;
|
|
386
|
+
}): TypedStep<TWorkflowInput, {
|
|
387
|
+
items: TItemOutput[];
|
|
388
|
+
}, TDeps, TContext>;
|
|
389
|
+
/**
|
|
390
|
+
* Define a **sub-workflow** step: once its deps complete, `input(ctx)` maps the
|
|
391
|
+
* parent context to the child workflow's input; the engine **starts the child workflow**
|
|
392
|
+
* (sharing the partition), suspends this step as `waiting`, and resumes it with the child's
|
|
393
|
+
* output once the child terminates. A failed/cancelled child fails this step (and cascades).
|
|
394
|
+
*
|
|
395
|
+
* Pass the built child workflow (`buildWorkflow(...)`); its step handlers are registered
|
|
396
|
+
* automatically alongside the parent. The step's output type is the child's output shape —
|
|
397
|
+
* give `outputSchema` to type it for dependents (defaults to an opaque record).
|
|
398
|
+
*/
|
|
399
|
+
declare function defineSubWorkflowStep<TOutput extends Record<string, unknown> = Record<string, unknown>, TWorkflowInput extends Record<string, unknown> = Record<string, unknown>, TContext = unknown, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: {
|
|
400
|
+
type: string;
|
|
401
|
+
workflowInputSchema: z.ZodType<TWorkflowInput>;
|
|
402
|
+
/** The built child workflow to start (`buildWorkflow(...)`) — must share the parent's `TContext`. */
|
|
403
|
+
childWorkflow: {
|
|
404
|
+
definition: WorkflowDefinition;
|
|
405
|
+
register: (registry: StepHandlerRegistry<TContext>) => void;
|
|
406
|
+
};
|
|
407
|
+
/** Map the parent step's context to the child workflow's input. */
|
|
408
|
+
input: (ctx: TypedStepContext<TWorkflowInput, TDeps, TContext>) => Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
409
|
+
/** Shape of the child workflow's output (for typing dependents). Defaults to an opaque record. */
|
|
410
|
+
outputSchema?: z.ZodType<TOutput>;
|
|
411
|
+
dependencies?: TDeps;
|
|
412
|
+
}): TypedStep<TWorkflowInput, TOutput, TDeps, TContext>;
|
|
413
|
+
/**
|
|
414
|
+
* Define a durable **sleep** step: a no-op step that, once its dependencies complete,
|
|
415
|
+
* is held in the queue for `sleepMs` before completing — advancing the DAG afterwards.
|
|
416
|
+
* The delay is durable (survives restarts) because it lives in the queue, not in memory.
|
|
417
|
+
*
|
|
418
|
+
* A sleep step is just `defineStep` with `delayMs` and an empty handler; use this for
|
|
419
|
+
* cooldowns, "continue in 1 hour", or spacing out downstream work.
|
|
420
|
+
*/
|
|
421
|
+
declare function defineSleepStep<TContext = unknown, TDeps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: {
|
|
422
|
+
type: string;
|
|
423
|
+
/** How long to sleep once the step becomes ready, in ms. */
|
|
424
|
+
sleepMs: number;
|
|
425
|
+
dependencies?: TDeps;
|
|
426
|
+
}): TypedStep<Record<string, never>, Record<string, never>, TDeps, TContext>;
|
|
427
|
+
/** Minimal engine surface `buildWorkflow().start()` needs — avoids a circular import. */
|
|
428
|
+
interface StartableEngine {
|
|
429
|
+
startWorkflow(definition: WorkflowDefinition, input: Record<string, unknown>, options?: StartOptions): Promise<Result<WorkflowCreatedResult, FlowError>>;
|
|
430
|
+
}
|
|
431
|
+
interface TypedWorkflow<TInput extends Record<string, unknown>, TContext> {
|
|
432
|
+
readonly type: string;
|
|
433
|
+
readonly inputSchema: z.ZodType<TInput>;
|
|
434
|
+
readonly definition: WorkflowDefinition;
|
|
435
|
+
/** Register every step handler with a registry. */
|
|
436
|
+
register(registry: StepHandlerRegistry<TContext>): void;
|
|
437
|
+
/** Type-safe start with input validation. */
|
|
438
|
+
start(engine: StartableEngine, input: TInput, options?: StartOptions): Promise<Result<WorkflowCreatedResult, FlowError>>;
|
|
439
|
+
}
|
|
440
|
+
interface BuildWorkflowConfig<TInput extends Record<string, unknown>, TSteps extends Record<string, TypedStep<any, any, any, TContext>>, TContext> {
|
|
441
|
+
type: string;
|
|
442
|
+
inputSchema: z.ZodType<TInput>;
|
|
443
|
+
steps: TSteps;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Build a typed workflow from step definitions. Derives the `WorkflowDefinition`
|
|
447
|
+
* DAG from each step's dependency metadata and validates at construction time
|
|
448
|
+
* that every dependency key references a real step.
|
|
449
|
+
*/
|
|
450
|
+
declare function buildWorkflow<TInput extends Record<string, unknown>, TContext = unknown, TSteps extends Record<string, TypedStep<any, any, any, TContext>> = {}>(config: BuildWorkflowConfig<TInput, TSteps, TContext>): TypedWorkflow<TInput, TContext>;
|
|
451
|
+
//#endregion
|
|
452
|
+
//#region src/core/public-view.d.ts
|
|
453
|
+
/** The five states a UI renders. Suspensions display as in-flight. */
|
|
454
|
+
type StepDisplayStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
|
|
455
|
+
declare const STEP_DISPLAY_STATUS_SCHEMA: z.ZodEnum<{
|
|
456
|
+
completed: "completed";
|
|
457
|
+
failed: "failed";
|
|
458
|
+
pending: "pending";
|
|
459
|
+
running: "running";
|
|
460
|
+
skipped: "skipped";
|
|
461
|
+
}>;
|
|
462
|
+
/**
|
|
463
|
+
* Engine step statuses folded to display states. `waiting` (suspended for an
|
|
464
|
+
* event), `mapping` (fan-out in flight), and `compensating` (rollback running)
|
|
465
|
+
* are all "still in flight" from a reader's point of view; a `compensated`
|
|
466
|
+
* step's work was undone, which reads as `skipped`, with the failure that
|
|
467
|
+
* triggered the rollback reported by the failed step itself. Exhaustive over
|
|
468
|
+
* {@link StepStatus} so a new engine status is a compile error here, not a
|
|
469
|
+
* silent hole in a consumer's API.
|
|
470
|
+
*/
|
|
471
|
+
declare const STEP_DISPLAY_STATUS: Record<StepStatus, StepDisplayStatus>;
|
|
472
|
+
/** Fold one engine step status to its display state. */
|
|
473
|
+
declare function toDisplayStepStatus(status: StepStatus): StepDisplayStatus;
|
|
474
|
+
/** A step as served to API consumers. Timestamps are ISO strings. */
|
|
475
|
+
interface PublicWorkflowStep {
|
|
476
|
+
id: number;
|
|
477
|
+
key: string;
|
|
478
|
+
type: string;
|
|
479
|
+
status: StepDisplayStatus;
|
|
480
|
+
dependencies: string[];
|
|
481
|
+
input: Record<string, unknown> | null;
|
|
482
|
+
output: Record<string, unknown> | null;
|
|
483
|
+
error: string | null;
|
|
484
|
+
startedAt: string | null;
|
|
485
|
+
completedAt: string | null;
|
|
486
|
+
}
|
|
487
|
+
/** A workflow (with steps) as served to API consumers. Timestamps are ISO strings. */
|
|
488
|
+
interface PublicWorkflow {
|
|
489
|
+
id: number;
|
|
490
|
+
type: string;
|
|
491
|
+
status: WorkflowWithSteps['status'];
|
|
492
|
+
input: Record<string, unknown>;
|
|
493
|
+
output: Record<string, unknown> | null;
|
|
494
|
+
error: string | null;
|
|
495
|
+
entityRef: string | null;
|
|
496
|
+
totalSteps: number;
|
|
497
|
+
completedSteps: number;
|
|
498
|
+
failedSteps: number;
|
|
499
|
+
steps: PublicWorkflowStep[];
|
|
500
|
+
createdAt: string;
|
|
501
|
+
startedAt: string | null;
|
|
502
|
+
completedAt: string | null;
|
|
503
|
+
}
|
|
504
|
+
declare const WORKFLOW_STATUS_SCHEMA: z.ZodEnum<{
|
|
505
|
+
cancelled: "cancelled";
|
|
506
|
+
completed: "completed";
|
|
507
|
+
failed: "failed";
|
|
508
|
+
pending: "pending";
|
|
509
|
+
running: "running";
|
|
510
|
+
}>;
|
|
511
|
+
declare const PUBLIC_WORKFLOW_STEP_SCHEMA: z.ZodObject<{
|
|
512
|
+
id: z.ZodNumber;
|
|
513
|
+
key: z.ZodString;
|
|
514
|
+
type: z.ZodString;
|
|
515
|
+
status: z.ZodEnum<{
|
|
516
|
+
completed: "completed";
|
|
517
|
+
failed: "failed";
|
|
518
|
+
pending: "pending";
|
|
519
|
+
running: "running";
|
|
520
|
+
skipped: "skipped";
|
|
521
|
+
}>;
|
|
522
|
+
dependencies: z.ZodArray<z.ZodString>;
|
|
523
|
+
input: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
524
|
+
output: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
525
|
+
error: z.ZodNullable<z.ZodString>;
|
|
526
|
+
startedAt: z.ZodNullable<z.ZodString>;
|
|
527
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
528
|
+
}, z.core.$strip>;
|
|
529
|
+
declare const PUBLIC_WORKFLOW_SCHEMA: z.ZodObject<{
|
|
530
|
+
id: z.ZodNumber;
|
|
531
|
+
type: z.ZodString;
|
|
532
|
+
status: z.ZodEnum<{
|
|
533
|
+
cancelled: "cancelled";
|
|
534
|
+
completed: "completed";
|
|
535
|
+
failed: "failed";
|
|
536
|
+
pending: "pending";
|
|
537
|
+
running: "running";
|
|
538
|
+
}>;
|
|
539
|
+
input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
540
|
+
output: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
541
|
+
error: z.ZodNullable<z.ZodString>;
|
|
542
|
+
entityRef: z.ZodNullable<z.ZodString>;
|
|
543
|
+
totalSteps: z.ZodNumber;
|
|
544
|
+
completedSteps: z.ZodNumber;
|
|
545
|
+
failedSteps: z.ZodNumber;
|
|
546
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
547
|
+
id: z.ZodNumber;
|
|
548
|
+
key: z.ZodString;
|
|
549
|
+
type: z.ZodString;
|
|
550
|
+
status: z.ZodEnum<{
|
|
551
|
+
completed: "completed";
|
|
552
|
+
failed: "failed";
|
|
553
|
+
pending: "pending";
|
|
554
|
+
running: "running";
|
|
555
|
+
skipped: "skipped";
|
|
556
|
+
}>;
|
|
557
|
+
dependencies: z.ZodArray<z.ZodString>;
|
|
558
|
+
input: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
559
|
+
output: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
560
|
+
error: z.ZodNullable<z.ZodString>;
|
|
561
|
+
startedAt: z.ZodNullable<z.ZodString>;
|
|
562
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
563
|
+
}, z.core.$strip>>;
|
|
564
|
+
createdAt: z.ZodString;
|
|
565
|
+
startedAt: z.ZodNullable<z.ZodString>;
|
|
566
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
567
|
+
}, z.core.$strip>;
|
|
568
|
+
/**
|
|
569
|
+
* Project a step record to its public view. Drops `workflowId` (redundant
|
|
570
|
+
* under the parent), `metadata`, `attempts`, and `parentStepId`; folds the
|
|
571
|
+
* status.
|
|
572
|
+
*/
|
|
573
|
+
declare function toPublicStep(step: StepRecord): PublicWorkflowStep;
|
|
574
|
+
/**
|
|
575
|
+
* Project a workflow (with steps) to its public view. Drops `partitionKey`,
|
|
576
|
+
* `idempotencyKey`, `parentWorkflowId`/`parentStepId`, and `metadata`.
|
|
577
|
+
*/
|
|
578
|
+
declare function toPublicWorkflow(workflow: WorkflowWithSteps): PublicWorkflow;
|
|
579
|
+
//#endregion
|
|
580
|
+
export { StepError as A, WorkflowDefinition as B, FlowError as C, StepCompensateHandler as D, StartOptions as E, StepId as F, WorkflowWithSteps as G, WorkflowNotFoundError as H, StepRecord as I, err as J, FlowErrorShape as K, StepRegistration as L, StepHandler as M, StepHandlerNotFoundError as N, StepCompensationContext as O, StepHandlerRegistry as P, StepStatus as R, defineWaitStep as S, RetryPolicy as T, WorkflowRecord as U, WorkflowId as V, WorkflowStatus as W, ok as Y, buildWorkflow as _, STEP_DISPLAY_STATUS as a, defineStep as b, WORKFLOW_STATUS_SCHEMA as c, toPublicWorkflow as d, StepOutput as f, WorkflowOutput as g, TypedWorkflow as h, PublicWorkflowStep as i, StepExecutionContext as j, StepDefinition as k, toDisplayStepStatus as l, TypedStepContext as m, PUBLIC_WORKFLOW_STEP_SCHEMA as n, STEP_DISPLAY_STATUS_SCHEMA as o, TypedStep as p, Result as q, PublicWorkflow as r, StepDisplayStatus as s, PUBLIC_WORKFLOW_SCHEMA as t, toPublicStep as u, defineMapStep as v, InvalidWorkflowDefinitionError as w, defineSubWorkflowStep as x, defineSleepStep as y, WorkflowCreatedResult as z };
|