@pogodisco/zephyr 1.2.9 → 1.3.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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/session.d.ts +25 -0
- package/dist/session.js +58 -0
- package/dist/workflow-composer.d.ts +1 -0
- package/dist/workflow-composer.js +1 -0
- package/dist/workflow-executor.js +11 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ActionRegistry, WorkflowMiddleware } from "./types.js";
|
|
2
|
+
import { WorkflowDef } from "./workflow-composer.js";
|
|
3
|
+
type ModuleFlows<Reg extends ActionRegistry> = Record<string, WorkflowDef<Reg, any, any>>;
|
|
4
|
+
export declare class WorkflowSession<Reg extends ActionRegistry, State extends Record<string, any>> {
|
|
5
|
+
private registry;
|
|
6
|
+
private subscribers;
|
|
7
|
+
private running;
|
|
8
|
+
private queue;
|
|
9
|
+
state: State;
|
|
10
|
+
middleware: WorkflowMiddleware[];
|
|
11
|
+
private moduleFlows;
|
|
12
|
+
/**
|
|
13
|
+
* @param baseModule Module to extend (inherits workflows)
|
|
14
|
+
* @param registry Action registry
|
|
15
|
+
* @param initialContext Initial context (session state) — will be mutated in workflows
|
|
16
|
+
*/
|
|
17
|
+
constructor(baseModule: ModuleFlows<Reg>, registry: Reg, initialContext: State, middleware: WorkflowMiddleware[]);
|
|
18
|
+
getState(): State;
|
|
19
|
+
subscribe(fn: (state: Partial<State>) => void): () => boolean;
|
|
20
|
+
private notify;
|
|
21
|
+
/** Queue a workflow execution by key and input; state/context is automatically updated */
|
|
22
|
+
dispatch(key: keyof ModuleFlows<Reg>, input?: any): void;
|
|
23
|
+
private processQueue;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { executeWorkflow } from "./workflow-executor.js";
|
|
2
|
+
import { createModule } from "./workflow-module.js";
|
|
3
|
+
export class WorkflowSession {
|
|
4
|
+
/**
|
|
5
|
+
* @param baseModule Module to extend (inherits workflows)
|
|
6
|
+
* @param registry Action registry
|
|
7
|
+
* @param initialContext Initial context (session state) — will be mutated in workflows
|
|
8
|
+
*/
|
|
9
|
+
constructor(baseModule, registry, initialContext, middleware) {
|
|
10
|
+
this.registry = registry;
|
|
11
|
+
this.subscribers = new Set();
|
|
12
|
+
this.running = false;
|
|
13
|
+
this.queue = [];
|
|
14
|
+
this.middleware = [];
|
|
15
|
+
// Use the same object for session state and module context
|
|
16
|
+
this.state = initialContext;
|
|
17
|
+
this.middleware = middleware;
|
|
18
|
+
// Per-session module: inherits workflows, shares the same state/context object
|
|
19
|
+
this.moduleFlows = createModule({
|
|
20
|
+
registry: this.registry,
|
|
21
|
+
context: this.state,
|
|
22
|
+
use: [baseModule],
|
|
23
|
+
define: () => ({}), // no new flows needed
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getState() {
|
|
27
|
+
return this.state;
|
|
28
|
+
}
|
|
29
|
+
subscribe(fn) {
|
|
30
|
+
this.subscribers.add(fn);
|
|
31
|
+
fn(this.state); // immediately notify
|
|
32
|
+
return () => this.subscribers.delete(fn);
|
|
33
|
+
}
|
|
34
|
+
notify() {
|
|
35
|
+
for (const fn of this.subscribers)
|
|
36
|
+
fn(this.state);
|
|
37
|
+
}
|
|
38
|
+
/** Queue a workflow execution by key and input; state/context is automatically updated */
|
|
39
|
+
dispatch(key, input = {}) {
|
|
40
|
+
this.queue.push({ key, input });
|
|
41
|
+
if (!this.running)
|
|
42
|
+
this.processQueue();
|
|
43
|
+
}
|
|
44
|
+
async processQueue() {
|
|
45
|
+
this.running = true;
|
|
46
|
+
while (this.queue.length) {
|
|
47
|
+
const { key, input } = this.queue.shift();
|
|
48
|
+
const workflow = this.moduleFlows[key];
|
|
49
|
+
if (!workflow)
|
|
50
|
+
throw new Error(`Workflow ${String(key)} not found`);
|
|
51
|
+
// state/context already lives on the module; no need to pass a separate context
|
|
52
|
+
await executeWorkflow(workflow, this.registry, input, this.middleware);
|
|
53
|
+
// Notify subscribers after workflow mutates state
|
|
54
|
+
this.notify();
|
|
55
|
+
}
|
|
56
|
+
this.running = false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -16,6 +16,7 @@ export type WorkflowDef<Reg extends ActionRegistry, Input, Results, Steps extend
|
|
|
16
16
|
input: Input;
|
|
17
17
|
results: Results;
|
|
18
18
|
outputResolver?: (ctx: any) => Output;
|
|
19
|
+
__context?: any;
|
|
19
20
|
};
|
|
20
21
|
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
21
22
|
export declare class WorkflowBuilder<Reg extends ActionRegistry, Input = unknown, Context extends Record<string, any> = {}, Steps extends StepDef<Reg, any, any>[] = [], Results = {}, Output = undefined> {
|
|
@@ -231,11 +231,20 @@ export async function executeWorkflow(workflow, registry, input, middleware = []
|
|
|
231
231
|
start: Date.now(),
|
|
232
232
|
};
|
|
233
233
|
extras.frames[stepId] = frame;
|
|
234
|
-
const
|
|
234
|
+
const context = workflow.__context;
|
|
235
|
+
const ctx = {
|
|
236
|
+
stepId,
|
|
237
|
+
input,
|
|
238
|
+
results,
|
|
239
|
+
context,
|
|
240
|
+
registry,
|
|
241
|
+
extras,
|
|
242
|
+
frame,
|
|
243
|
+
};
|
|
235
244
|
const core = async () => {
|
|
236
245
|
frame.attempts++;
|
|
237
246
|
// 👇 Get the resolved arguments (should be a tuple or undefined)
|
|
238
|
-
const resolvedArgs = step.resolve?.({ input, results });
|
|
247
|
+
const resolvedArgs = step.resolve?.({ input, results, context });
|
|
239
248
|
frame.input = resolvedArgs;
|
|
240
249
|
try {
|
|
241
250
|
const action = registry[step.action];
|