@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 CHANGED
@@ -7,4 +7,5 @@ export * from "./utils.js";
7
7
  export * from "./types.js";
8
8
  export * from "./utils.js";
9
9
  export * from "./node/index.js";
10
+ export * from "./session.js";
10
11
  export { useMetrics, useLog } from "./middleware.js";
package/dist/index.js CHANGED
@@ -7,4 +7,5 @@ export * from "./utils.js";
7
7
  export * from "./types.js";
8
8
  export * from "./utils.js";
9
9
  export * from "./node/index.js";
10
+ export * from "./session.js";
10
11
  export { useMetrics, useLog } from "./middleware.js";
@@ -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 {};
@@ -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> {
@@ -639,6 +639,7 @@ export class WorkflowBuilder {
639
639
  input: {},
640
640
  results: {},
641
641
  outputResolver: this.outputResolver,
642
+ __context: this.context,
642
643
  };
643
644
  }
644
645
  validateDependencies() {
@@ -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 ctx = { stepId, input, results, registry, extras, frame };
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];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pogodisco/zephyr",
3
- "version": "1.2.9",
3
+ "version": "1.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },