@pogodisco/zephyr 1.2.7 → 1.2.9
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/registry.d.ts +6 -2
- package/dist/registry.js +44 -0
- package/dist/types.d.ts +3 -1
- package/dist/types.js +46 -0
- package/dist/utils.d.ts +14 -8
- package/dist/utils.js +51 -21
- package/dist/workflow-composer.d.ts +22 -11
- package/dist/workflow-composer.js +5 -7
- package/dist/workflow-executor.js +119 -3
- package/dist/workflow-module.js +0 -50
- package/package.json +1 -1
package/dist/registry.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ActionRegistry, MergeActionRegistries } from "./types.js";
|
|
2
2
|
export declare class ActionRegistryBuilder<R extends ActionRegistry = {}> {
|
|
3
3
|
private registry;
|
|
4
4
|
constructor(initial?: R);
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Accepts ANY function - sync or async, any parameter shape
|
|
7
|
+
* F captures the complete function signature for full type inference
|
|
8
|
+
*/
|
|
9
|
+
action<K extends string, F extends (...args: any[]) => any>(key: K, action: F): ActionRegistryBuilder<MergeActionRegistries<R, Record<K, F>>>;
|
|
6
10
|
extend<Other extends ActionRegistry>(other: ActionRegistryBuilder<Other> | Other): ActionRegistryBuilder<MergeActionRegistries<R, Other>>;
|
|
7
11
|
build(): R;
|
|
8
12
|
}
|
package/dist/registry.js
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
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
|
+
// }
|
|
1
41
|
export class ActionRegistryBuilder {
|
|
2
42
|
constructor(initial) {
|
|
3
43
|
this.registry = {};
|
|
@@ -5,6 +45,10 @@ export class ActionRegistryBuilder {
|
|
|
5
45
|
this.registry = { ...initial };
|
|
6
46
|
}
|
|
7
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Accepts ANY function - sync or async, any parameter shape
|
|
50
|
+
* F captures the complete function signature for full type inference
|
|
51
|
+
*/
|
|
8
52
|
action(key, action) {
|
|
9
53
|
this.registry[key] = action;
|
|
10
54
|
return this;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createWorkflow } from "./workflow-composer.js";
|
|
2
|
-
export type Action<
|
|
2
|
+
export type Action<F extends (...args: any[]) => any = (...args: any[]) => any> = F;
|
|
3
3
|
export interface ActionRegistry {
|
|
4
4
|
[key: string]: Action;
|
|
5
5
|
}
|
|
@@ -13,6 +13,8 @@ export type ExecutionFrame = {
|
|
|
13
13
|
output?: any;
|
|
14
14
|
error?: any;
|
|
15
15
|
};
|
|
16
|
+
export type ActionParams<Reg extends ActionRegistry, K extends keyof Reg> = Parameters<Reg[K]>;
|
|
17
|
+
export type ActionReturn<Reg extends ActionRegistry, K extends keyof Reg> = Awaited<ReturnType<Reg[K]>>;
|
|
16
18
|
export type WorkflowMiddleware<Reg extends ActionRegistry = any> = {
|
|
17
19
|
(ctx: {
|
|
18
20
|
stepId: string;
|
package/dist/types.js
CHANGED
|
@@ -1 +1,47 @@
|
|
|
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>;
|
|
1
47
|
export {};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export declare function
|
|
1
|
+
type AnyFn = (...args: any[]) => Promise<any>;
|
|
2
|
+
type Input<F extends AnyFn> = Parameters<F>[0];
|
|
3
|
+
type Output<F extends AnyFn> = Awaited<ReturnType<F>>;
|
|
4
|
+
/**
|
|
5
|
+
* For generic actions where you want to specify the return type
|
|
6
|
+
* Just a type helper, does nothing at runtime
|
|
7
|
+
*/
|
|
8
|
+
export declare function genericAction<F extends AnyFn>(fn: F): <T = Output<F>>() => (args: Input<F>) => Promise<T>;
|
|
9
|
+
/**
|
|
10
|
+
* For fixed actions - just returns the function
|
|
11
|
+
* The type parameter T is for convenience when you want to override the return type
|
|
12
|
+
*/
|
|
13
|
+
export declare function fixedAction<F extends AnyFn>(fn: F): <T = Output<F>>() => ((args: Input<F>) => Promise<T>);
|
|
14
|
+
export {};
|
package/dist/utils.js
CHANGED
|
@@ -1,25 +1,55 @@
|
|
|
1
|
-
import { defineNode, execNode } from "./node/main.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
+
/**
|
|
43
|
+
* For generic actions where you want to specify the return type
|
|
44
|
+
* Just a type helper, does nothing at runtime
|
|
45
|
+
*/
|
|
12
46
|
export function genericAction(fn) {
|
|
13
|
-
return () =>
|
|
47
|
+
return () => fn;
|
|
14
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* For fixed actions - just returns the function
|
|
51
|
+
* The type parameter T is for convenience when you want to override the return type
|
|
52
|
+
*/
|
|
15
53
|
export function fixedAction(fn) {
|
|
16
|
-
return () =>
|
|
17
|
-
}
|
|
18
|
-
export function useAction(node) {
|
|
19
|
-
// Returns a function that graph can call, but WITHOUT withResponse
|
|
20
|
-
// Just a simple adapter that calls callNode and returns raw _output
|
|
21
|
-
return async (initArgs) => {
|
|
22
|
-
const result = await execNode(node, initArgs);
|
|
23
|
-
return result._output; // Just raw data, throws on error
|
|
24
|
-
};
|
|
54
|
+
return () => fn;
|
|
25
55
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ActionRegistry } from "./types.js";
|
|
1
|
+
import { ActionRegistry, ActionParams, ActionReturn } from "./types.js";
|
|
2
2
|
type SubflowResult<SubResults, SubOutput> = SubOutput extends undefined ? SubResults : SubOutput;
|
|
3
|
-
type StepResult<Reg extends ActionRegistry, ActionName extends keyof Reg> =
|
|
3
|
+
type StepResult<Reg extends ActionRegistry, ActionName extends keyof Reg> = ActionReturn<Reg, ActionName>;
|
|
4
4
|
export type StepDef<Reg extends ActionRegistry, ID extends string = string, ActionName extends keyof Reg = any> = {
|
|
5
5
|
id: ID;
|
|
6
6
|
action: ActionName;
|
|
7
7
|
dependsOn: string[];
|
|
8
|
-
resolve: (ctx: any) =>
|
|
8
|
+
resolve: (ctx: any) => ActionParams<Reg, ActionName>;
|
|
9
9
|
when?: (ctx: any) => boolean;
|
|
10
10
|
};
|
|
11
11
|
export type WorkflowDef<Reg extends ActionRegistry, Input, Results, Steps extends StepDef<Reg, any, any>[] = StepDef<Reg, any, any>[], Output = undefined> = {
|
|
@@ -26,36 +26,47 @@ export declare class WorkflowBuilder<Reg extends ActionRegistry, Input = unknown
|
|
|
26
26
|
private frontier;
|
|
27
27
|
private outputResolver?;
|
|
28
28
|
constructor(name: string, registry: Reg, context: Context);
|
|
29
|
-
step<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve
|
|
29
|
+
step<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?: ActionParams<Reg, ActionName> extends [] ? (ctx?: {
|
|
30
30
|
input: Input;
|
|
31
31
|
results: Results;
|
|
32
32
|
context: Context;
|
|
33
|
-
}) =>
|
|
33
|
+
}) => undefined : (ctx: {
|
|
34
|
+
input: Input;
|
|
35
|
+
results: Results;
|
|
36
|
+
context: Context;
|
|
37
|
+
}) => ActionParams<Reg, ActionName>, dependsOn?: string[]): WorkflowBuilder<Reg, Input, Context, [
|
|
34
38
|
...Steps,
|
|
35
39
|
StepDef<Reg, ID, ActionName>
|
|
36
40
|
], Results & {
|
|
37
41
|
[K in ID]: StepResult<Reg, ActionName>;
|
|
38
42
|
}>;
|
|
39
|
-
seq<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve
|
|
43
|
+
seq<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?: ActionParams<Reg, ActionName> extends [] ? (ctx?: {
|
|
44
|
+
input: Input;
|
|
45
|
+
results: Results;
|
|
46
|
+
context: Context;
|
|
47
|
+
}) => undefined : (ctx: {
|
|
40
48
|
input: Input;
|
|
41
49
|
results: Results;
|
|
42
50
|
context: Context;
|
|
43
|
-
}) =>
|
|
51
|
+
}) => ActionParams<Reg, ActionName>): WorkflowBuilder<Reg, Input, Context, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K in ID]: Awaited<ReturnType<Reg[ActionName]>>; }, undefined>;
|
|
44
52
|
parallel<Branches extends WorkflowBuilder<Reg, Input, Context, any, any>[]>(...branches: {
|
|
45
53
|
[K in keyof Branches]: (builder: WorkflowBuilder<Reg, Input, Context, [], Results>) => Branches[K];
|
|
46
54
|
}): WorkflowBuilder<Reg, Input, Context, [
|
|
47
55
|
...Steps,
|
|
48
56
|
...(Branches[number] extends WorkflowBuilder<Reg, any, any, infer S, any> ? S : never)
|
|
49
57
|
], Results & (Branches[number] extends WorkflowBuilder<Reg, any, any, any, infer R> ? UnionToIntersection<R> : {})>;
|
|
50
|
-
join<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve
|
|
58
|
+
join<ID extends string, ActionName extends keyof Reg & string>(id: ID, action: ActionName, resolve?: ActionParams<Reg, ActionName> extends [] ? (ctx?: {
|
|
59
|
+
input: Input;
|
|
60
|
+
results: Results;
|
|
61
|
+
}) => undefined : (ctx: {
|
|
51
62
|
input: Input;
|
|
52
63
|
results: Results;
|
|
53
|
-
}) =>
|
|
54
|
-
subflow<Prefix extends string, SubInput, SubResults, SubSteps extends StepDef<Reg, any, any>[], SubOutput>(prefix: Prefix, workflow: WorkflowDef<Reg, SubInput, SubResults, SubSteps, SubOutput>, resolveInput
|
|
64
|
+
}) => ActionParams<Reg, ActionName>): WorkflowBuilder<Reg, Input, Context, [...Steps, StepDef<Reg, ID, ActionName>], Results & { [K in ID]: Awaited<ReturnType<Reg[ActionName]>>; }, undefined>;
|
|
65
|
+
subflow<Prefix extends string, SubInput, SubResults, SubSteps extends StepDef<Reg, any, any>[], SubOutput>(prefix: Prefix, workflow: WorkflowDef<Reg, SubInput, SubResults, SubSteps, SubOutput>, resolveInput?: (ctx: {
|
|
55
66
|
input: Input;
|
|
56
67
|
results: Results;
|
|
57
68
|
context: Context;
|
|
58
|
-
}) => SubInput): WorkflowBuilder<Reg, Input, Context, [
|
|
69
|
+
}) => [SubInput] extends [never] ? any : SubInput & Record<Exclude<keyof SubInput, keyof any>, never>): WorkflowBuilder<Reg, Input, Context, [
|
|
59
70
|
...Steps,
|
|
60
71
|
...SubSteps
|
|
61
72
|
], Results & {
|
|
@@ -555,12 +555,14 @@ export class WorkflowBuilder {
|
|
|
555
555
|
/* ------------------------------------------------ */
|
|
556
556
|
/* Base Step */
|
|
557
557
|
/* ------------------------------------------------ */
|
|
558
|
-
step(id, action,
|
|
558
|
+
step(id, action,
|
|
559
|
+
// 👇 resolve returns whatever the action expects (tuple, object, single value, etc.)
|
|
560
|
+
resolve, dependsOn) {
|
|
559
561
|
const deps = dependsOn ?? [...this.frontier];
|
|
560
562
|
this.steps.push({
|
|
561
563
|
id,
|
|
562
564
|
action,
|
|
563
|
-
resolve,
|
|
565
|
+
resolve: (resolve ?? (() => undefined)),
|
|
564
566
|
dependsOn: deps,
|
|
565
567
|
});
|
|
566
568
|
this.frontier = [id];
|
|
@@ -607,7 +609,7 @@ export class WorkflowBuilder {
|
|
|
607
609
|
id: idMap.get(step.id),
|
|
608
610
|
dependsOn: step.dependsOn.map((d) => idMap.get(d)),
|
|
609
611
|
resolve: (ctx) => {
|
|
610
|
-
const subInput = resolveInput(ctx);
|
|
612
|
+
const subInput = resolveInput ? resolveInput(ctx) : undefined;
|
|
611
613
|
return step.resolve({
|
|
612
614
|
input: subInput,
|
|
613
615
|
results: ctx.results,
|
|
@@ -627,9 +629,6 @@ export class WorkflowBuilder {
|
|
|
627
629
|
this.outputResolver = fn;
|
|
628
630
|
return this.build();
|
|
629
631
|
}
|
|
630
|
-
/* ------------------------------------------------ */
|
|
631
|
-
/* Build */
|
|
632
|
-
/* ------------------------------------------------ */
|
|
633
632
|
build() {
|
|
634
633
|
this.validateDependencies();
|
|
635
634
|
return {
|
|
@@ -642,7 +641,6 @@ export class WorkflowBuilder {
|
|
|
642
641
|
outputResolver: this.outputResolver,
|
|
643
642
|
};
|
|
644
643
|
}
|
|
645
|
-
/* ------------------------------------------------ */
|
|
646
644
|
validateDependencies() {
|
|
647
645
|
const stepIds = new Set(this.steps.map((s) => s.id));
|
|
648
646
|
for (const step of this.steps) {
|
|
@@ -97,12 +97,114 @@
|
|
|
97
97
|
//
|
|
98
98
|
// return { results: results as R, extras };
|
|
99
99
|
// }
|
|
100
|
+
// import { composeMiddleware } from "./middleware.js";
|
|
101
|
+
// import { ActionRegistry, ExecutionFrame, WorkflowMiddleware } from "./types.js";
|
|
102
|
+
// import { StepDef, WorkflowDef } from "./workflow-composer.js";
|
|
103
|
+
//
|
|
104
|
+
// export async function executeWorkflow<Reg extends ActionRegistry, I, R, O = R>(
|
|
105
|
+
// workflow: WorkflowDef<Reg, I, R, any, O>,
|
|
106
|
+
// registry: Reg,
|
|
107
|
+
// input: I,
|
|
108
|
+
// middleware: WorkflowMiddleware<Reg>[] = [],
|
|
109
|
+
// ): Promise<{ results: R; output: O; extras: Record<string, any> }> {
|
|
110
|
+
// const results: Record<string, any> = {};
|
|
111
|
+
// const extras: Record<string, any> = {};
|
|
112
|
+
// extras.frames = {} as Record<string, ExecutionFrame>;
|
|
113
|
+
//
|
|
114
|
+
// // --- strongly type steps ---
|
|
115
|
+
//
|
|
116
|
+
// const stepById = new Map<string, StepDef<Reg, any, any>>(
|
|
117
|
+
// workflow.steps.map((s: StepDef<Reg, any, any>) => [s.id, s]),
|
|
118
|
+
// );
|
|
119
|
+
// const remainingDeps = new Map<string, number>();
|
|
120
|
+
// const dependents = new Map<string, string[]>();
|
|
121
|
+
// const ready: string[] = [];
|
|
122
|
+
//
|
|
123
|
+
// // Build dependency graph
|
|
124
|
+
// for (const step of workflow.steps) {
|
|
125
|
+
// remainingDeps.set(step.id, step.dependsOn.length);
|
|
126
|
+
// if (step.dependsOn.length === 0) ready.push(step.id);
|
|
127
|
+
//
|
|
128
|
+
// for (const dep of step.dependsOn) {
|
|
129
|
+
// if (!dependents.has(dep)) dependents.set(dep, []);
|
|
130
|
+
// dependents.get(dep)!.push(step.id);
|
|
131
|
+
// }
|
|
132
|
+
// }
|
|
133
|
+
//
|
|
134
|
+
// let completed = 0;
|
|
135
|
+
//
|
|
136
|
+
// while (ready.length > 0) {
|
|
137
|
+
// const batch = ready.splice(0);
|
|
138
|
+
//
|
|
139
|
+
// await Promise.all(
|
|
140
|
+
// batch.map(async (stepId) => {
|
|
141
|
+
// const step = stepById.get(stepId)!;
|
|
142
|
+
//
|
|
143
|
+
// const frame: ExecutionFrame = {
|
|
144
|
+
// stepId,
|
|
145
|
+
// attempts: 0,
|
|
146
|
+
// start: Date.now(),
|
|
147
|
+
// };
|
|
148
|
+
// extras.frames[stepId] = frame;
|
|
149
|
+
//
|
|
150
|
+
// const ctx = { stepId, input, results, registry, extras, frame };
|
|
151
|
+
//
|
|
152
|
+
// const core = async () => {
|
|
153
|
+
// frame.attempts++;
|
|
154
|
+
// frame.input = step.resolve?.({ input, results }) ?? undefined;
|
|
155
|
+
//
|
|
156
|
+
// try {
|
|
157
|
+
// const action = registry[step.action];
|
|
158
|
+
// const result =
|
|
159
|
+
// frame.input === undefined
|
|
160
|
+
// ? await (action as () => Promise<any>)()
|
|
161
|
+
// : await action(frame.input);
|
|
162
|
+
// // const result = await action(frame.input);
|
|
163
|
+
// frame.output = result;
|
|
164
|
+
// frame.end = Date.now();
|
|
165
|
+
//
|
|
166
|
+
// results[step.id] = result;
|
|
167
|
+
// return result;
|
|
168
|
+
// } catch (err) {
|
|
169
|
+
// frame.error = err;
|
|
170
|
+
// frame.end = Date.now();
|
|
171
|
+
// throw err;
|
|
172
|
+
// }
|
|
173
|
+
// };
|
|
174
|
+
//
|
|
175
|
+
// const composed = composeMiddleware(middleware, ctx, core);
|
|
176
|
+
// await composed();
|
|
177
|
+
//
|
|
178
|
+
// for (const childId of dependents.get(stepId) ?? []) {
|
|
179
|
+
// const remaining = remainingDeps.get(childId)! - 1;
|
|
180
|
+
// remainingDeps.set(childId, remaining);
|
|
181
|
+
// if (remaining === 0) ready.push(childId);
|
|
182
|
+
// }
|
|
183
|
+
//
|
|
184
|
+
// completed++;
|
|
185
|
+
// }),
|
|
186
|
+
// );
|
|
187
|
+
// }
|
|
188
|
+
//
|
|
189
|
+
// if (completed !== workflow.steps.length) {
|
|
190
|
+
// throw new Error("Workflow execution failed (cycle or missing dependency)");
|
|
191
|
+
// }
|
|
192
|
+
//
|
|
193
|
+
// // Resolve output
|
|
194
|
+
// const output: O = workflow.outputResolver
|
|
195
|
+
// ? workflow.outputResolver({ input, results: results as R })
|
|
196
|
+
// : (results as unknown as O);
|
|
197
|
+
//
|
|
198
|
+
// return { results: results as R, output, extras };
|
|
199
|
+
// }
|
|
200
|
+
//
|
|
201
|
+
//
|
|
202
|
+
///// with any fn shape
|
|
100
203
|
import { composeMiddleware } from "./middleware.js";
|
|
101
204
|
export async function executeWorkflow(workflow, registry, input, middleware = []) {
|
|
102
205
|
const results = {};
|
|
103
206
|
const extras = {};
|
|
104
207
|
extras.frames = {};
|
|
105
|
-
// --- strongly type steps ---
|
|
106
208
|
const stepById = new Map(workflow.steps.map((s) => [s.id, s]));
|
|
107
209
|
const remainingDeps = new Map();
|
|
108
210
|
const dependents = new Map();
|
|
@@ -132,10 +234,24 @@ export async function executeWorkflow(workflow, registry, input, middleware = []
|
|
|
132
234
|
const ctx = { stepId, input, results, registry, extras, frame };
|
|
133
235
|
const core = async () => {
|
|
134
236
|
frame.attempts++;
|
|
135
|
-
|
|
237
|
+
// 👇 Get the resolved arguments (should be a tuple or undefined)
|
|
238
|
+
const resolvedArgs = step.resolve?.({ input, results });
|
|
239
|
+
frame.input = resolvedArgs;
|
|
136
240
|
try {
|
|
137
241
|
const action = registry[step.action];
|
|
138
|
-
|
|
242
|
+
let result;
|
|
243
|
+
if (resolvedArgs === undefined) {
|
|
244
|
+
// No arguments - call with nothing
|
|
245
|
+
result = await action();
|
|
246
|
+
}
|
|
247
|
+
else if (Array.isArray(resolvedArgs)) {
|
|
248
|
+
// Tuple arguments - spread as positional params
|
|
249
|
+
result = await action(...resolvedArgs);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// Single object argument (backward compatibility)
|
|
253
|
+
result = await action(resolvedArgs);
|
|
254
|
+
}
|
|
139
255
|
frame.output = result;
|
|
140
256
|
frame.end = Date.now();
|
|
141
257
|
results[step.id] = result;
|
package/dist/workflow-module.js
CHANGED
|
@@ -44,53 +44,3 @@ export function createModule({ registry, context, use, define, }) {
|
|
|
44
44
|
...own,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
// type MergeFlows<T extends any[]> = T extends [infer F, ...infer R]
|
|
48
|
-
// ? F extends { flows: infer Fl }
|
|
49
|
-
// ? MergeFlows<R> & Fl
|
|
50
|
-
// : MergeFlows<R>
|
|
51
|
-
// : {};
|
|
52
|
-
//
|
|
53
|
-
// type Module<
|
|
54
|
-
// Reg extends ActionRegistry,
|
|
55
|
-
// Context extends Record<string, any>,
|
|
56
|
-
// Flows,
|
|
57
|
-
// > = {
|
|
58
|
-
// wf: ReturnType<typeof createWorkflow<Reg, Context>>;
|
|
59
|
-
// flows: Flows;
|
|
60
|
-
// };
|
|
61
|
-
//
|
|
62
|
-
// export function createModule<
|
|
63
|
-
// Reg extends ActionRegistry,
|
|
64
|
-
// Context extends Record<string, any>,
|
|
65
|
-
// Flows extends Record<string, any>,
|
|
66
|
-
// UseModules extends Module<any, any, any>[] = [],
|
|
67
|
-
// >({
|
|
68
|
-
// registry,
|
|
69
|
-
// context,
|
|
70
|
-
// use = [] as unknown as UseModules,
|
|
71
|
-
// define,
|
|
72
|
-
// }: {
|
|
73
|
-
// registry: Reg;
|
|
74
|
-
// context: Context;
|
|
75
|
-
// use?: UseModules;
|
|
76
|
-
// define?: (
|
|
77
|
-
// wf: ReturnType<typeof createWorkflow<Reg, Context>>,
|
|
78
|
-
// deps: MergeFlows<UseModules>,
|
|
79
|
-
// ) => Flows;
|
|
80
|
-
// }) {
|
|
81
|
-
// const wf = createWorkflow(registry, context);
|
|
82
|
-
//
|
|
83
|
-
// const inherited = Object.assign({}, ...use.map((m) => m.flows));
|
|
84
|
-
// const own = define ? define(wf, inherited as MergeFlows<UseModules>) : {};
|
|
85
|
-
//
|
|
86
|
-
// const flows = {
|
|
87
|
-
// ...inherited,
|
|
88
|
-
// ...own,
|
|
89
|
-
// };
|
|
90
|
-
//
|
|
91
|
-
// return {
|
|
92
|
-
// wf,
|
|
93
|
-
// flows,
|
|
94
|
-
// ...flows,
|
|
95
|
-
// } as Module<Reg, Context, typeof flows>;
|
|
96
|
-
// }
|