@pogodisco/zephyr 1.3.4 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/observer.d.ts +4 -0
- package/dist/observer.js +69 -0
- package/dist/registry.js +0 -40
- package/dist/session.d.ts +3 -3
- package/dist/session.js +4 -4
- package/dist/types.d.ts +1 -1
- package/dist/types.js +0 -46
- package/dist/utils.js +0 -41
- package/dist/workflow-composer.d.ts +56 -23
- package/dist/workflow-composer.js +230 -350
- package/dist/workflow-executor.d.ts +3 -3
- package/dist/workflow-executor.js +44 -224
- package/dist/workflow-module.d.ts +11 -6
- package/dist/workflow-module.js +8 -38
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ActionRegistry, WorkflowObserver } from "./types.js";
|
|
2
|
+
export declare function composeObserver<Reg extends ActionRegistry>(middleware: WorkflowObserver<Reg>[], ctx: Parameters<WorkflowObserver<Reg>>[0], core: () => Promise<any>): () => Promise<any>;
|
|
3
|
+
export declare function useLog(): WorkflowObserver;
|
|
4
|
+
export declare function useMetrics(): WorkflowObserver;
|
package/dist/observer.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { eventStream } from "./event-stream.js";
|
|
2
|
+
export function composeObserver(middleware, ctx, core) {
|
|
3
|
+
let index = -1;
|
|
4
|
+
async function dispatch(i) {
|
|
5
|
+
if (i <= index)
|
|
6
|
+
throw new Error("next() called multiple times");
|
|
7
|
+
index = i;
|
|
8
|
+
const fn = middleware[i];
|
|
9
|
+
if (!fn)
|
|
10
|
+
return core();
|
|
11
|
+
return fn(ctx, () => dispatch(i + 1));
|
|
12
|
+
}
|
|
13
|
+
return () => dispatch(0);
|
|
14
|
+
}
|
|
15
|
+
export function useLog() {
|
|
16
|
+
return async ({ frame, stepId }, next) => {
|
|
17
|
+
eventStream.emit({
|
|
18
|
+
type: "node_start",
|
|
19
|
+
node: stepId,
|
|
20
|
+
timestamp: frame.start,
|
|
21
|
+
input: frame.input,
|
|
22
|
+
});
|
|
23
|
+
try {
|
|
24
|
+
const res = await next();
|
|
25
|
+
eventStream.emit({
|
|
26
|
+
type: "node_success",
|
|
27
|
+
node: stepId,
|
|
28
|
+
output: frame.output,
|
|
29
|
+
duration: frame.end - frame.start,
|
|
30
|
+
attempts: frame.attempts,
|
|
31
|
+
timestamp: Date.now(),
|
|
32
|
+
});
|
|
33
|
+
return res;
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
eventStream.emit({
|
|
37
|
+
type: "node_fail",
|
|
38
|
+
node: stepId,
|
|
39
|
+
error: frame.error,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
attempts: frame.attempts,
|
|
42
|
+
});
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function useMetrics() {
|
|
48
|
+
return async ({ stepId, extras }, next) => {
|
|
49
|
+
if (!extras?.metrics) {
|
|
50
|
+
extras.metrics = {};
|
|
51
|
+
}
|
|
52
|
+
const start = Date.now();
|
|
53
|
+
try {
|
|
54
|
+
const res = await next();
|
|
55
|
+
extras.metrics[stepId] = {
|
|
56
|
+
status: "success",
|
|
57
|
+
duration: Date.now() - start,
|
|
58
|
+
};
|
|
59
|
+
return res;
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
extras.metrics[stepId] = {
|
|
63
|
+
status: "fail",
|
|
64
|
+
duration: Date.now() - start,
|
|
65
|
+
};
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
package/dist/registry.js
CHANGED
|
@@ -1,43 +1,3 @@
|
|
|
1
|
-
// import { Action, ActionRegistry, MergeActionRegistries } from "./types.js";
|
|
2
|
-
//
|
|
3
|
-
// export class ActionRegistryBuilder<R extends ActionRegistry = {}> {
|
|
4
|
-
// private registry: Partial<R> = {};
|
|
5
|
-
//
|
|
6
|
-
// constructor(initial?: R) {
|
|
7
|
-
// if (initial) {
|
|
8
|
-
// this.registry = { ...initial };
|
|
9
|
-
// }
|
|
10
|
-
// }
|
|
11
|
-
//
|
|
12
|
-
// action<K extends string, I, O>(
|
|
13
|
-
// key: K,
|
|
14
|
-
// action: Action<I, O>,
|
|
15
|
-
// ): ActionRegistryBuilder<MergeActionRegistries<R, Record<K, Action<I, O>>>> {
|
|
16
|
-
// (this.registry as any)[key] = action;
|
|
17
|
-
// return this as any;
|
|
18
|
-
// }
|
|
19
|
-
//
|
|
20
|
-
// // Extend with another registry (with override)
|
|
21
|
-
// extend<Other extends ActionRegistry>(
|
|
22
|
-
// other: ActionRegistryBuilder<Other> | Other,
|
|
23
|
-
// ): ActionRegistryBuilder<MergeActionRegistries<R, Other>> {
|
|
24
|
-
// const otherRegistry =
|
|
25
|
-
// other instanceof ActionRegistryBuilder ? other.build() : other;
|
|
26
|
-
//
|
|
27
|
-
// Object.assign(this.registry, otherRegistry);
|
|
28
|
-
// return this as any;
|
|
29
|
-
// }
|
|
30
|
-
//
|
|
31
|
-
// build(): R {
|
|
32
|
-
// return this.registry as R;
|
|
33
|
-
// }
|
|
34
|
-
// }
|
|
35
|
-
//
|
|
36
|
-
// export function createActionRegistry<R extends ActionRegistry = {}>(
|
|
37
|
-
// initial?: R,
|
|
38
|
-
// ): ActionRegistryBuilder<R> {
|
|
39
|
-
// return new ActionRegistryBuilder(initial);
|
|
40
|
-
// }
|
|
41
1
|
export class ActionRegistryBuilder {
|
|
42
2
|
constructor(initial) {
|
|
43
3
|
this.registry = {};
|
package/dist/session.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionRegistry,
|
|
1
|
+
import { ActionRegistry, WorkflowObserver } from "./types.js";
|
|
2
2
|
import { WorkflowDef } from "./workflow-composer.js";
|
|
3
3
|
type ModuleFlows<Reg extends ActionRegistry> = Record<string, WorkflowDef<Reg, any, any>>;
|
|
4
4
|
export declare class WorkflowSession<Reg extends ActionRegistry, State extends Record<string, any>> {
|
|
@@ -7,14 +7,14 @@ export declare class WorkflowSession<Reg extends ActionRegistry, State extends R
|
|
|
7
7
|
private running;
|
|
8
8
|
private queue;
|
|
9
9
|
state: State;
|
|
10
|
-
|
|
10
|
+
observers: WorkflowObserver[];
|
|
11
11
|
private moduleFlows;
|
|
12
12
|
/**
|
|
13
13
|
* @param baseModule Module to extend (inherits workflows)
|
|
14
14
|
* @param registry Action registry
|
|
15
15
|
* @param initialContext Initial context (session state) — will be mutated in workflows
|
|
16
16
|
*/
|
|
17
|
-
constructor(baseModule: ModuleFlows<Reg>, registry: Reg, initialContext: State,
|
|
17
|
+
constructor(baseModule: ModuleFlows<Reg>, registry: Reg, initialContext: State, observers: WorkflowObserver[]);
|
|
18
18
|
getState(): State;
|
|
19
19
|
subscribe(fn: (state: Partial<State>) => void): () => boolean;
|
|
20
20
|
private notify;
|
package/dist/session.js
CHANGED
|
@@ -6,15 +6,15 @@ export class WorkflowSession {
|
|
|
6
6
|
* @param registry Action registry
|
|
7
7
|
* @param initialContext Initial context (session state) — will be mutated in workflows
|
|
8
8
|
*/
|
|
9
|
-
constructor(baseModule, registry, initialContext,
|
|
9
|
+
constructor(baseModule, registry, initialContext, observers) {
|
|
10
10
|
this.registry = registry;
|
|
11
11
|
this.subscribers = new Set();
|
|
12
12
|
this.running = false;
|
|
13
13
|
this.queue = [];
|
|
14
|
-
this.
|
|
14
|
+
this.observers = [];
|
|
15
15
|
// Use the same object for session state and module context
|
|
16
16
|
this.state = initialContext;
|
|
17
|
-
this.
|
|
17
|
+
this.observers = observers;
|
|
18
18
|
// Per-session module: inherits workflows, shares the same state/context object
|
|
19
19
|
this.moduleFlows = createModule({
|
|
20
20
|
registry: this.registry,
|
|
@@ -49,7 +49,7 @@ export class WorkflowSession {
|
|
|
49
49
|
if (!workflow)
|
|
50
50
|
throw new Error(`Workflow ${String(key)} not found`);
|
|
51
51
|
// state/context already lives on the module; no need to pass a separate context
|
|
52
|
-
await executeWorkflow(workflow, this.registry, input, this.
|
|
52
|
+
await executeWorkflow(workflow, this.registry, input, this.observers);
|
|
53
53
|
// Notify subscribers after workflow mutates state
|
|
54
54
|
this.notify();
|
|
55
55
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type ExecutionFrame = {
|
|
|
14
14
|
};
|
|
15
15
|
export type ActionParams<Reg, K extends keyof Reg> = Reg[K] extends (...args: infer P) => any ? P : never;
|
|
16
16
|
export type ActionReturn<Reg, K extends keyof Reg> = Reg[K] extends (...args: any[]) => infer R ? Awaited<R> : never;
|
|
17
|
-
export type
|
|
17
|
+
export type WorkflowObserver<Reg extends ActionRegistry = any> = {
|
|
18
18
|
(ctx: {
|
|
19
19
|
stepId: string;
|
|
20
20
|
input: any;
|
package/dist/types.js
CHANGED
|
@@ -1,47 +1 @@
|
|
|
1
|
-
// import { createWorkflow } from "./workflow-composer.js";
|
|
2
|
-
//
|
|
3
|
-
// export type Action<I = any, O = any> = (args: I) => Promise<O>;
|
|
4
|
-
//
|
|
5
|
-
// export interface ActionRegistry {
|
|
6
|
-
// [key: string]: Action;
|
|
7
|
-
// }
|
|
8
|
-
//
|
|
9
|
-
// export type MergeActionRegistries<
|
|
10
|
-
// A extends ActionRegistry,
|
|
11
|
-
// B extends ActionRegistry,
|
|
12
|
-
// > = Omit<A, keyof B> & B;
|
|
13
|
-
//
|
|
14
|
-
// export type ExecutionFrame = {
|
|
15
|
-
// stepId: string;
|
|
16
|
-
// attempts: number;
|
|
17
|
-
// start: number;
|
|
18
|
-
// end?: number;
|
|
19
|
-
// input?: any;
|
|
20
|
-
// output?: any;
|
|
21
|
-
// error?: any;
|
|
22
|
-
// };
|
|
23
|
-
//
|
|
24
|
-
// export type WorkflowMiddleware<Reg extends ActionRegistry = any> = {
|
|
25
|
-
// (
|
|
26
|
-
// ctx: {
|
|
27
|
-
// stepId: string;
|
|
28
|
-
// input: any;
|
|
29
|
-
// results: Record<string, any>;
|
|
30
|
-
// registry: Reg;
|
|
31
|
-
// extras: Record<string, any>;
|
|
32
|
-
// frame: ExecutionFrame;
|
|
33
|
-
// },
|
|
34
|
-
// next: () => Promise<any>,
|
|
35
|
-
// ): Promise<any>;
|
|
36
|
-
// };
|
|
37
|
-
//
|
|
38
|
-
// export type WF<
|
|
39
|
-
// Reg extends ActionRegistry,
|
|
40
|
-
// Context extends Record<string, any>,
|
|
41
|
-
// > = ReturnType<typeof createWorkflow<Reg, Context>>;
|
|
42
|
-
// // TODO: this needs enforcing
|
|
43
|
-
// type Observer = (
|
|
44
|
-
// frame: Readonly<ExecutionFrame>,
|
|
45
|
-
// extras: Record<string, any>,
|
|
46
|
-
// ) => void | Promise<void>;
|
|
47
1
|
export {};
|
package/dist/utils.js
CHANGED
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
// import { defineNode, execNode } from "./node/main.js";
|
|
2
|
-
// import { TaskMap, TaskNodeWithContracts, TasksFromFns } from "./node/types.js";
|
|
3
|
-
//
|
|
4
|
-
// export function createAction<
|
|
5
|
-
// FN extends (args: any) => any, // Allow sync or async
|
|
6
|
-
// Out = Awaited<ReturnType<FN>>, // Unwrap Promise if present
|
|
7
|
-
// >(fn: FN) {
|
|
8
|
-
// // Just return the raw node definition, not wrapped with useNode
|
|
9
|
-
// return defineNode<TasksFromFns<{ run: FN }>, Parameters<FN>[0], Out>({
|
|
10
|
-
// run: {
|
|
11
|
-
// fn, // Function can throw or return data
|
|
12
|
-
// argMap: (r) => r._init,
|
|
13
|
-
// },
|
|
14
|
-
// _output: (r) => r.run as Out,
|
|
15
|
-
// });
|
|
16
|
-
// }
|
|
17
|
-
//
|
|
18
|
-
// export function genericAction<FN extends (args: any) => any>(fn: FN) {
|
|
19
|
-
// return <T = Awaited<ReturnType<FN>>>() => useAction(createAction<FN, T>(fn));
|
|
20
|
-
// }
|
|
21
|
-
//
|
|
22
|
-
// export function fixedAction<
|
|
23
|
-
// FN extends (args: any) => any,
|
|
24
|
-
// T = Awaited<ReturnType<FN>>,
|
|
25
|
-
// >(fn: FN): () => (args: Parameters<FN>[0]) => Promise<T> {
|
|
26
|
-
// return () => useAction(createAction<FN, T>(fn));
|
|
27
|
-
// }
|
|
28
|
-
//
|
|
29
|
-
// export function useAction<
|
|
30
|
-
// T extends TaskMap,
|
|
31
|
-
// I extends Record<string, any> | undefined,
|
|
32
|
-
// O,
|
|
33
|
-
// >(node: TaskNodeWithContracts<T, I, O>) {
|
|
34
|
-
// // Returns a function that graph can call, but WITHOUT withResponse
|
|
35
|
-
// // Just a simple adapter that calls callNode and returns raw _output
|
|
36
|
-
// return async (initArgs: I): Promise<O> => {
|
|
37
|
-
// const result = await execNode(node, initArgs);
|
|
38
|
-
// return result._output; // Just raw data, throws on error
|
|
39
|
-
// };
|
|
40
|
-
// }
|
|
41
|
-
//
|
|
42
1
|
/**
|
|
43
2
|
* For generic actions - preserves the generic parameter
|
|
44
3
|
*/
|
|
@@ -1,11 +1,52 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ActionParams, ActionRegistry, ActionReturn } from "./types.js";
|
|
2
|
+
type NormalizedCall = {
|
|
3
|
+
kind: "none";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "positional";
|
|
6
|
+
args: any[];
|
|
7
|
+
} | {
|
|
8
|
+
kind: "object";
|
|
9
|
+
args: any;
|
|
10
|
+
};
|
|
11
|
+
export type ResolvedStepInput = NormalizedCall | {
|
|
12
|
+
kind: "loop";
|
|
13
|
+
items: NormalizedCall[];
|
|
14
|
+
};
|
|
15
|
+
type CallHelpers<Reg extends ActionRegistry, ActionName extends keyof Reg> = {
|
|
16
|
+
args: (...args: ActionParams<Reg, ActionName>) => {
|
|
17
|
+
kind: "positional";
|
|
18
|
+
args: ActionParams<Reg, ActionName>;
|
|
19
|
+
};
|
|
20
|
+
obj: ActionParams<Reg, ActionName> extends [infer A] ? (arg: A) => {
|
|
21
|
+
kind: "object";
|
|
22
|
+
args: A;
|
|
23
|
+
} : never;
|
|
24
|
+
none: () => {
|
|
25
|
+
kind: "none";
|
|
26
|
+
};
|
|
27
|
+
loop: (items: {
|
|
28
|
+
kind: "positional";
|
|
29
|
+
args: ActionParams<Reg, ActionName>;
|
|
30
|
+
}[] | {
|
|
31
|
+
kind: "object";
|
|
32
|
+
args: ActionParams<Reg, ActionName>[0];
|
|
33
|
+
}[]) => {
|
|
34
|
+
kind: "loop";
|
|
35
|
+
items: typeof items;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
2
38
|
type SubflowResult<SubResults, SubOutput> = SubOutput extends undefined ? SubResults : SubOutput;
|
|
3
|
-
type
|
|
39
|
+
type WorkflowInput<T> = T extends WorkflowDef<any, infer I, any, any, any> ? I : never;
|
|
40
|
+
type WorkflowResults<T> = T extends WorkflowDef<any, any, infer R, any, any> ? R : never;
|
|
41
|
+
type WorkflowOutput<T> = T extends WorkflowDef<any, any, any, any, infer O> ? O : never;
|
|
42
|
+
export type StepResultFromResolve<Reg extends ActionRegistry, ActionName extends keyof Reg, R extends ResolvedStepInput> = R extends {
|
|
43
|
+
kind: "loop";
|
|
44
|
+
} ? ActionReturn<Reg, ActionName>[] : ActionReturn<Reg, ActionName>;
|
|
4
45
|
export type StepDef<Reg extends ActionRegistry, ID extends string = string, ActionName extends keyof Reg = any> = {
|
|
5
46
|
id: ID;
|
|
6
47
|
action: ActionName;
|
|
7
48
|
dependsOn: string[];
|
|
8
|
-
resolve: (ctx: any) =>
|
|
49
|
+
resolve: (ctx: any) => ResolvedStepInput;
|
|
9
50
|
when?: (ctx: any) => boolean;
|
|
10
51
|
};
|
|
11
52
|
export type WorkflowDef<Reg extends ActionRegistry, Input, Results, Steps extends StepDef<Reg, any, any>[] = StepDef<Reg, any, any>[], Output = undefined> = {
|
|
@@ -27,53 +68,45 @@ export declare class WorkflowBuilder<Reg extends ActionRegistry, Input = unknown
|
|
|
27
68
|
private frontier;
|
|
28
69
|
private outputResolver?;
|
|
29
70
|
constructor(name: string, registry: Reg, context: Context);
|
|
30
|
-
step<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?:
|
|
71
|
+
step<ID extends string, ActionName extends keyof Reg & string, ResolveOut extends ResolvedStepInput = ResolvedStepInput>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
31
72
|
input: Input;
|
|
32
73
|
results: Results;
|
|
33
74
|
context: Context;
|
|
34
|
-
}) =>
|
|
35
|
-
input: Input;
|
|
36
|
-
results: Results;
|
|
37
|
-
context: Context;
|
|
38
|
-
}) => ActionParams<Reg, ActionName>, dependsOn?: string[]): WorkflowBuilder<Reg, Input, Context, [
|
|
75
|
+
} & CallHelpers<Reg, ActionName>) => ResolveOut, dependsOn?: string[], options?: {}): WorkflowBuilder<Reg, Input, Context, [
|
|
39
76
|
...Steps,
|
|
40
77
|
StepDef<Reg, ID, ActionName>
|
|
41
78
|
], Results & {
|
|
42
|
-
[K in ID]:
|
|
79
|
+
[K in ID]: StepResultFromResolve<Reg, ActionName, ResolveOut>;
|
|
43
80
|
}>;
|
|
44
|
-
seq<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?:
|
|
45
|
-
input: Input;
|
|
46
|
-
results: Results;
|
|
47
|
-
context: Context;
|
|
48
|
-
}) => undefined : (ctx: {
|
|
81
|
+
seq<ID extends string, ActionName extends keyof Reg & string, ResolveOut extends ResolvedStepInput = ResolvedStepInput>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
49
82
|
input: Input;
|
|
50
83
|
results: Results;
|
|
51
84
|
context: Context;
|
|
52
|
-
}
|
|
85
|
+
} & CallHelpers<Reg, ActionName>) => ResolveOut, options?: {}): WorkflowBuilder<Reg, Input, Context, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K in ID]: StepResultFromResolve<Reg, ActionName, ResolveOut>; }, undefined>;
|
|
53
86
|
parallel<Branches extends WorkflowBuilder<Reg, Input, Context, any, any>[]>(...branches: {
|
|
54
87
|
[K in keyof Branches]: (builder: WorkflowBuilder<Reg, Input, Context, [], Results>) => Branches[K];
|
|
55
88
|
}): WorkflowBuilder<Reg, Input, Context, [
|
|
56
89
|
...Steps,
|
|
57
90
|
...(Branches[number] extends WorkflowBuilder<Reg, any, any, infer S, any> ? S : never)
|
|
58
91
|
], Results & (Branches[number] extends WorkflowBuilder<Reg, any, any, any, infer R> ? UnionToIntersection<R> : {})>;
|
|
59
|
-
join<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?:
|
|
92
|
+
join<ID extends string, ActionName extends keyof Reg & string, ResolveOut extends ResolvedStepInput = ResolvedStepInput>(id: ID, action: ActionName, resolve?: (ctx: {
|
|
60
93
|
input: Input;
|
|
61
94
|
results: Results;
|
|
62
95
|
context: Context;
|
|
63
|
-
}) =>
|
|
96
|
+
} & CallHelpers<Reg, ActionName>) => ResolveOut, options?: {}): WorkflowBuilder<Reg, Input, Context, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K in ID]: StepResultFromResolve<Reg, ActionName, ResolveOut>; }, undefined>;
|
|
97
|
+
subflow<Prefix extends string, SubSteps extends StepDef<Reg, any, any>[], WF extends WorkflowDef<Reg, any, any, SubSteps, any>>(prefix: Prefix, workflow: WF, resolveInput: WorkflowInput<WF> extends undefined ? ((ctx: {
|
|
64
98
|
input: Input;
|
|
65
99
|
results: Results;
|
|
66
100
|
context: Context;
|
|
67
|
-
}) =>
|
|
68
|
-
subflow<Prefix extends string, SubInput, SubResults, SubSteps extends StepDef<Reg, any, any>[], SubOutput>(prefix: Prefix, workflow: WorkflowDef<Reg, SubInput, SubResults, SubSteps, SubOutput>, resolveInput?: (ctx: {
|
|
101
|
+
}) => WorkflowInput<WF>) | undefined : (ctx: {
|
|
69
102
|
input: Input;
|
|
70
103
|
results: Results;
|
|
71
104
|
context: Context;
|
|
72
|
-
}) =>
|
|
105
|
+
}) => WorkflowInput<WF>, options?: {}): WorkflowBuilder<Reg, Input, Context, [
|
|
73
106
|
...Steps,
|
|
74
|
-
...
|
|
107
|
+
...WF["steps"]
|
|
75
108
|
], Results & {
|
|
76
|
-
[K in Prefix]: SubflowResult<
|
|
109
|
+
[K in Prefix]: SubflowResult<WorkflowResults<WF>, WorkflowOutput<WF>>;
|
|
77
110
|
}>;
|
|
78
111
|
when(predicate: (ctx: {
|
|
79
112
|
input: Input;
|