@gobing-ai/ts-dual-workflow-engine 0.3.7 → 0.3.10

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/README.md CHANGED
@@ -690,7 +690,8 @@ All three layers are **additive** — EventBus does not replace logging or traci
690
690
  | `workflow.action.start` | `{ node, kind }` | When an action starts executing |
691
691
  | `workflow.action.done` | `{ node, kind, durationMs, ok }` | When an action finishes (success or failure) |
692
692
  | `workflow.action.failed_continue` | `{ node, transitionsTaken, error? }` | When a non-fatal action failure is continued past (`onError: 'continue'`) |
693
-
693
+ | `workflow.custom` | `{ name, payload }` | Emitted by the builtin `event.emit` action for custom user-defined events |
694
+ | `workflow.hitl.note` | `{ node, message }` | Emitted by the builtin `note` action for workflow-visible annotations |
694
695
  ### Usage
695
696
 
696
697
  Pass an `EventBus` via `WorkflowRunOptions.events`:
package/dist/events.d.ts CHANGED
@@ -45,5 +45,15 @@ export type WorkflowEngineEvents = {
45
45
  transitionsTaken: number;
46
46
  error?: string;
47
47
  }) => void;
48
+ /** Emitted by the builtin `event.emit` action for custom user-defined events. */
49
+ 'workflow.custom': (data: {
50
+ name: string;
51
+ payload: Record<string, unknown>;
52
+ }) => void;
53
+ /** Emitted by the builtin `note` action for workflow-visible annotations. */
54
+ 'workflow.hitl.note': (data: {
55
+ node: string;
56
+ message: string;
57
+ }) => void;
48
58
  };
49
59
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,MAAM,oBAAoB,GAAG;IAC/B,mDAAmD;IACnD,sBAAsB,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9F,iDAAiD;IACjD,mBAAmB,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,gCAAgC;IAChC,qBAAqB,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9E,6CAA6C;IAC7C,qBAAqB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClF,0CAA0C;IAC1C,0BAA0B,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IACjG,+CAA+C;IAC/C,uBAAuB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,sEAAsE;IACtE,sBAAsB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IACxG,uFAAuF;IACvF,iCAAiC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACjH,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,MAAM,oBAAoB,GAAG;IAC/B,mDAAmD;IACnD,sBAAsB,EAAE,CAAC,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9F,iDAAiD;IACjD,mBAAmB,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,gCAAgC;IAChC,qBAAqB,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9E,6CAA6C;IAC7C,qBAAqB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAClF,0CAA0C;IAC1C,0BAA0B,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IACjG,+CAA+C;IAC/C,uBAAuB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,sEAAsE;IACtE,sBAAsB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IACxG,uFAAuF;IACvF,iCAAiC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC9G,iFAAiF;IACjF,iBAAiB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,6EAA6E;IAC7E,oBAAoB,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC3E,CAAC"}
package/dist/hitl.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /** Categories of human-in-the-loop interaction. */
2
+ export type HitlRequestKind = 'confirm' | 'select' | 'input';
3
+ /** A request for human input during workflow execution. */
4
+ export interface HitlRequest {
5
+ kind: HitlRequestKind;
6
+ prompt: string;
7
+ /** select: the choices; confirm: optional labels; input: ignored. */
8
+ options?: string[];
9
+ /** echoed back for correlation. */
10
+ runId: string;
11
+ node: string;
12
+ }
13
+ /** The user's response to a HITL request. */
14
+ export interface HitlAnswer {
15
+ /** confirm -> 'yes'|'no'|'cancel'; select -> chosen option; input -> free text. */
16
+ value: string;
17
+ /** convenience: true when the user cancelled (confirm 'cancel'). */
18
+ cancelled?: boolean;
19
+ }
20
+ /**
21
+ * Contract for resolving HITL requests. Implementations are per-host
22
+ * (spur provides CLI/headless responders in task 0035). This engine
23
+ * package ships the interface only — no implementation.
24
+ */
25
+ export interface HitlResponder {
26
+ respond(request: HitlRequest): Promise<HitlAnswer>;
27
+ }
28
+ //# sourceMappingURL=hitl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitl.d.ts","sourceRoot":"","sources":["../src/hitl.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IACvB,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACtD"}
package/dist/hitl.js ADDED
File without changes
package/dist/host.d.ts CHANGED
@@ -30,18 +30,31 @@ export declare class WorkflowEngineHost {
30
30
  export declare function createDefaultWorkflowEngineHost(options?: {
31
31
  processExecutor?: ProcessExecutor;
32
32
  }): WorkflowEngineHost;
33
- /** Built-in action that records a note in result data. */
33
+ /** Built-in action that records a note and emits a workflow.hitl.note event. */
34
34
  export declare class NoteActionRunner implements ActionRunner {
35
35
  readonly kind = "note";
36
- /** Execute a no-op note action. */
37
- execute(options: Record<string, unknown>): Promise<ActionResult>;
36
+ /** Execute a no-op note action with observable event emission. */
37
+ execute(options: Record<string, unknown>, context?: ActionRunContext): Promise<ActionResult>;
38
+ }
39
+ /** Built-in action that emits a typed `workflow.custom` event on the run's event bus. */
40
+ export declare class EventEmitActionRunner implements ActionRunner {
41
+ readonly kind = "event.emit";
42
+ execute(options: Record<string, unknown>, context?: ActionRunContext): Promise<ActionResult>;
38
43
  }
39
44
  /** Built-in shell action backed by ts-runtime ProcessExecutor. */
40
45
  export declare class ShellActionRunner implements ActionRunner {
41
46
  private readonly processExecutor;
42
47
  readonly kind = "shell";
43
48
  constructor(processExecutor: ProcessExecutor);
44
- /** Execute a shell command with optional args and cwd. */
49
+ /**
50
+ * Execute a shell command. Two forms:
51
+ * - `command` + explicit `args` → run `command` as a program with those argv (no shell).
52
+ * - `command` alone → treat it as a shell command line and run it via `sh -c`, so operators
53
+ * can use shell features (`&&`, `|`, quoting, globs) as in `bun run autofix && bun run spur-check`.
54
+ *
55
+ * The bare-`command` form is by far the common case; running it directly as a program name —
56
+ * the old behavior — fails with a null exit code for any line containing spaces.
57
+ */
45
58
  execute(options: Record<string, unknown>, context: ActionRunContext): Promise<ActionResult>;
46
59
  }
47
60
  //# sourceMappingURL=host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,iCAAiC,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEvG,sDAAsD;AACtD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2D;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyD;IAEhF,4CAA4C;IAC5C,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAKlF,0CAA0C;IAC1C,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAK/E,0DAA0D;IAC1D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,0DAA0D;IAC1D,WAAW,IAAI,MAAM,EAAE;IAIvB,yDAAyD;IACzD,UAAU,IAAI,MAAM,EAAE;IAItB,mHAAmH;IACnH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIxD,0DAA0D;IAC1D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIvD,mCAAmC;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAOjH,mCAAmC;IAC7B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;CAI/G;AAED,4FAA4F;AAC5F,wBAAgB,+BAA+B,CAC3C,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,eAAe,CAAA;CAAO,GACpD,kBAAkB,CAcpB;AAED,0DAA0D;AAC1D,qBAAa,gBAAiB,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,UAAU;IAEvB,mCAAmC;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;CAGzE;AAED,kEAAkE;AAClE,qBAAa,iBAAkB,YAAW,YAAY;IAGtC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAF5C,QAAQ,CAAC,IAAI,WAAW;gBAEK,eAAe,EAAE,eAAe;IAE7D,0DAA0D;IACpD,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAgBpG"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,KAAK,gBAAgB,EAAsB,MAAM,iCAAiC,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEvG,sDAAsD;AACtD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2D;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyD;IAEhF,4CAA4C;IAC5C,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAKlF,0CAA0C;IAC1C,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,GAAE,gBAA8B,GAAG,IAAI;IAK/E,0DAA0D;IAC1D,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIhC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,0DAA0D;IAC1D,WAAW,IAAI,MAAM,EAAE;IAIvB,yDAAyD;IACzD,UAAU,IAAI,MAAM,EAAE;IAItB,mHAAmH;IACnH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIxD,0DAA0D;IAC1D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIvD,mCAAmC;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAOjH,mCAAmC;IAC7B,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;CAI/G;AAED,4FAA4F;AAC5F,wBAAgB,+BAA+B,CAC3C,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,eAAe,CAAA;CAAO,GACpD,kBAAkB,CAepB;AAED,gFAAgF;AAChF,qBAAa,gBAAiB,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,UAAU;IAEvB,kEAAkE;IAC5D,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAKrG;AAED,yFAAyF;AACzF,qBAAa,qBAAsB,YAAW,YAAY;IACtD,QAAQ,CAAC,IAAI,gBAAgB;IAEvB,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAOrG;AAED,kEAAkE;AAClE,qBAAa,iBAAkB,YAAW,YAAY;IAGtC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAF5C,QAAQ,CAAC,IAAI,WAAW;gBAEK,eAAe,EAAE,eAAe;IAE7D;;;;;;;;OAQG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CAkBpG"}
package/dist/host.js CHANGED
@@ -59,6 +59,7 @@ export function createDefaultWorkflowEngineHost(options = {}) {
59
59
  const host = new WorkflowEngineHost();
60
60
  host.registerAction(new NoteActionRunner(), 'builtin');
61
61
  host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()), 'builtin');
62
+ host.registerAction(new EventEmitActionRunner(), 'builtin');
62
63
  host.registerGuard({ kind: 'always', evaluate: async () => true }, 'builtin');
63
64
  host.registerGuard({ kind: 'never', evaluate: async () => false }, 'builtin');
64
65
  host.registerGuard({
@@ -67,12 +68,26 @@ export function createDefaultWorkflowEngineHost(options = {}) {
67
68
  }, 'builtin');
68
69
  return host;
69
70
  }
70
- /** Built-in action that records a note in result data. */
71
+ /** Built-in action that records a note and emits a workflow.hitl.note event. */
71
72
  export class NoteActionRunner {
72
73
  kind = 'note';
73
- /** Execute a no-op note action. */
74
- async execute(options) {
75
- return { ok: true, data: { message: String(options.message ?? '') } };
74
+ /** Execute a no-op note action with observable event emission. */
75
+ async execute(options, context) {
76
+ const message = String(options.message ?? '');
77
+ void context?.events?.emit('workflow.hitl.note', { node: context.stateOrNodeId, message });
78
+ return { ok: true, data: { message } };
79
+ }
80
+ }
81
+ /** Built-in action that emits a typed `workflow.custom` event on the run's event bus. */
82
+ export class EventEmitActionRunner {
83
+ kind = 'event.emit';
84
+ async execute(options, context) {
85
+ const name = String(options.name ?? '');
86
+ if (!name)
87
+ return { ok: false, error: 'event.emit requires a non-empty "name" option' };
88
+ const payload = options.payload ?? {};
89
+ void context?.events?.emit('workflow.custom', { name, payload });
90
+ return { ok: true, data: { name, payload } };
76
91
  }
77
92
  }
78
93
  /** Built-in shell action backed by ts-runtime ProcessExecutor. */
@@ -82,13 +97,23 @@ export class ShellActionRunner {
82
97
  constructor(processExecutor) {
83
98
  this.processExecutor = processExecutor;
84
99
  }
85
- /** Execute a shell command with optional args and cwd. */
100
+ /**
101
+ * Execute a shell command. Two forms:
102
+ * - `command` + explicit `args` → run `command` as a program with those argv (no shell).
103
+ * - `command` alone → treat it as a shell command line and run it via `sh -c`, so operators
104
+ * can use shell features (`&&`, `|`, quoting, globs) as in `bun run autofix && bun run spur-check`.
105
+ *
106
+ * The bare-`command` form is by far the common case; running it directly as a program name —
107
+ * the old behavior — fails with a null exit code for any line containing spaces.
108
+ */
86
109
  async execute(options, context) {
87
110
  const command = stringOption(options, 'command');
88
- const args = arrayOption(options, 'args');
111
+ const explicitArgs = arrayOption(options, 'args');
112
+ const usesShell = explicitArgs.length === 0;
113
+ const spawn = usesShell ? { command: '/bin/sh', args: ['-c', command] } : { command, args: explicitArgs };
89
114
  const result = await this.processExecutor.run({
90
- command,
91
- args,
115
+ command: spawn.command,
116
+ args: spawn.args,
92
117
  cwd: stringOption(options, 'cwd', context.workdir),
93
118
  rejectOnError: false,
94
119
  forceBuffered: true,
package/dist/index.d.ts CHANGED
@@ -2,7 +2,8 @@ export { loadWorkflowDef, loadWorkflowDefFromText, validateWorkflowDef } from '.
2
2
  export { FSMError, RunCollisionError, WorkflowValidationError } from './errors';
3
3
  export type { WorkflowEngineEvents } from './events';
4
4
  export { type LoadWorkflowExtensionsOptions, loadWorkflowExtensionsIntoHost, type WorkflowExtensionKind, type WorkflowExtensionLogger, type WorkflowExtensionRef, } from './extensions';
5
- export { createDefaultWorkflowEngineHost, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host';
5
+ export type { HitlAnswer, HitlRequest, HitlRequestKind, HitlResponder } from './hitl';
6
+ export { createDefaultWorkflowEngineHost, EventEmitActionRunner, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host';
6
7
  export { applyWorkflowEngineSchema, DbWorkflowPersistenceAdapter, MemoryWorkflowPersistenceAdapter, } from './persistence';
7
8
  export { allowedEnv, RUNTIME_BUILTIN_KEYS, RunLifecycle, type RunLifecycleDeps, runtimeBuiltins, type WorkflowMode, } from './run-lifecycle';
8
9
  export { ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema, } from './schema';
@@ -11,5 +12,5 @@ export { WorkflowService } from './service';
11
12
  export { StateMachineDriver, type StateMachineDriverOptions } from './state-machine';
12
13
  export { TransitionFlowDriver, type TransitionFlowDriverOptions } from './transition-flow';
13
14
  export type { ActionDef, ActionResult, ActionRunContext, ActionRunner, Env, FlowEdgeDef, FlowNodeDef, GuardContext, GuardDef, GuardRunner, OnErrorPolicy, StateDef, StateMachineWorkflowDef, TransitionDef, TransitionFlowWorkflowDef, Vars, WorkflowDef, WorkflowPersistenceAdapter, WorkflowRunOptions, WorkflowRunRecord, WorkflowRunResult, WorkflowStatus, } from './types';
14
- export { mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, type VariableContext, } from './variables';
15
+ export { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, type VariableContext, } from './variables';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EACH,KAAK,6BAA6B,EAClC,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,+BAA+B,EAC/B,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACH,yBAAyB,EACzB,4BAA4B,EAC5B,gCAAgC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,UAAU,EACV,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,YAAY,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,+BAA+B,EAC/B,iBAAiB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EACR,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,WAAW,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,aAAa,EACb,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,yBAAyB,EACzB,IAAI,EACJ,WAAW,EACX,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACH,SAAS,EACT,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,eAAe,GACvB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EACH,KAAK,6BAA6B,EAClC,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACtF,OAAO,EACH,+BAA+B,EAC/B,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACrB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACH,yBAAyB,EACzB,4BAA4B,EAC5B,gCAAgC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,UAAU,EACV,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,YAAY,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,eAAe,EACf,cAAc,EACd,6BAA6B,EAC7B,+BAA+B,EAC/B,iBAAiB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EACR,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,WAAW,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,aAAa,EACb,QAAQ,EACR,uBAAuB,EACvB,aAAa,EACb,yBAAyB,EACzB,IAAI,EACJ,WAAW,EACX,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACH,YAAY,EACZ,SAAS,EACT,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,eAAe,GACvB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { loadWorkflowDef, loadWorkflowDefFromText, validateWorkflowDef } from './config.js';
2
2
  export { FSMError, RunCollisionError, WorkflowValidationError } from './errors.js';
3
3
  export { loadWorkflowExtensionsIntoHost, } from './extensions.js';
4
- export { createDefaultWorkflowEngineHost, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host.js';
4
+ export { createDefaultWorkflowEngineHost, EventEmitActionRunner, NoteActionRunner, ShellActionRunner, WorkflowEngineHost, } from './host.js';
5
5
  export { applyWorkflowEngineSchema, DbWorkflowPersistenceAdapter, MemoryWorkflowPersistenceAdapter, } from './persistence.js';
6
6
  export { allowedEnv, RUNTIME_BUILTIN_KEYS, RunLifecycle, runtimeBuiltins, } from './run-lifecycle.js';
7
7
  export { ActionDefSchema, GuardDefSchema, StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema, WorkflowDefSchema, } from './schema.js';
@@ -9,4 +9,4 @@ export { WORKFLOW_ENGINE_SCHEMA_SQL } from './schema-sql.js';
9
9
  export { WorkflowService } from './service.js';
10
10
  export { StateMachineDriver } from './state-machine.js';
11
11
  export { TransitionFlowDriver } from './transition-flow.js';
12
- export { mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, } from './variables.js';
12
+ export { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplateString, resolveTemplates, } from './variables.js';
@@ -1 +1 @@
1
- {"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../src/run-lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../src/run-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -73,14 +73,12 @@ export class RunLifecycle {
73
73
  await this.persistence.savePhase(this.runId, stateOrNodeId, 'running');
74
74
  addSpanEvent('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
75
75
  void this.events?.emit('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
76
- this.logger.debug('entered', { node: stateOrNodeId, transitionsTaken });
77
76
  }
78
77
  /** Persist a transition and emit its observability event. */
79
78
  async recordTransition(from, to, trigger) {
80
79
  await this.persistence.saveTransition(this.runId, from, to, trigger);
81
80
  addSpanEvent('workflow.node.transition', { from, to, ...(trigger === null ? {} : { trigger }) });
82
81
  void this.events?.emit('workflow.node.transition', { from, to, trigger });
83
- this.logger.debug('transition', { from, to, trigger });
84
82
  }
85
83
  /** Finalize the run as succeeded and return its result. */
86
84
  async done(finalState, transitionsTaken) {
@@ -1 +1 @@
1
- {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAIR,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,wEAAwE;AACxE,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yBAAyB;IAE/D,6DAA6D;IACvD,GAAG,CAAC,QAAQ,EAAE,uBAAuB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAU5F,IAAI;IA6FlB;;;;;OAKG;YACW,UAAU;CA0C3B"}
1
+ {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAIR,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,yDAAyD;AACzD,MAAM,WAAW,yBAAyB;IACtC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,wEAAwE;AACxE,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,yBAAyB;IAE/D,6DAA6D;IACvD,GAAG,CAAC,QAAQ,EAAE,uBAAuB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAU5F,IAAI;IA8FlB;;;;;OAKG;YACW,UAAU;CA2C3B"}
@@ -1,6 +1,6 @@
1
1
  import { FSMError } from './errors.js';
2
2
  import { allowedEnv, RunLifecycle, runtimeBuiltins } from './run-lifecycle.js';
3
- import { mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables.js';
3
+ import { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables.js';
4
4
  /** State-machine workflow driver with an R7 single control function. */
5
5
  export class StateMachineDriver {
6
6
  options;
@@ -15,7 +15,7 @@ export class StateMachineDriver {
15
15
  const runId = lifecycle.runId;
16
16
  const states = new Map(workflow.states.map((state) => [state.id, state]));
17
17
  const terminal = new Set(workflow.terminalStates ?? []);
18
- const vars = mergeVars(workflow.vars, options.vars);
18
+ let vars = mergeVars(workflow.vars, options.vars);
19
19
  const env = allowedEnv(workflow.env?.allow ?? [], options.env);
20
20
  let current = states.get(workflow.initialState);
21
21
  let transitionsTaken = 0;
@@ -35,7 +35,8 @@ export class StateMachineDriver {
35
35
  // erase the previous result.
36
36
  if (enter.result !== undefined)
37
37
  lastActionResult = enter.result;
38
- // 3. Stop immediately when an action explicitly declares terminal success.
38
+ if (enter.result?.setVars)
39
+ vars = mergeSetVars(vars, enter.result.setVars);
39
40
  if (enter.outcome === 'terminal') {
40
41
  return await lifecycle.done(current.id, transitionsTaken);
41
42
  }
@@ -61,6 +62,8 @@ export class StateMachineDriver {
61
62
  const exit = await this.runActions(current.onExit ?? [], workflow.name, current.id, runId, vars, env, options, transitionsTaken, lifecycle, defaultOnError);
62
63
  if (exit.result !== undefined)
63
64
  lastActionResult = exit.result;
65
+ if (exit.result?.setVars)
66
+ vars = mergeSetVars(vars, exit.result.setVars);
64
67
  if (exit.outcome === 'fail')
65
68
  return await lifecycle.fail(current.id, transitionsTaken, exit.result?.error);
66
69
  // 7. Persist transition and move to the target state.
@@ -99,6 +102,7 @@ export class StateMachineDriver {
99
102
  vars,
100
103
  env,
101
104
  metadata: options.metadata,
105
+ events: options.events,
102
106
  });
103
107
  }
104
108
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"transition-flow.d.ts","sourceRoot":"","sources":["../src/transition-flow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAER,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,2DAA2D;AAC3D,MAAM,WAAW,2BAA2B;IACxC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,0EAA0E;AAC1E,qBAAa,oBAAoB;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,2BAA2B;IAEjE,+DAA+D;IACzD,GAAG,CAAC,QAAQ,EAAE,yBAAyB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAU9F,IAAI;CA8FrB"}
1
+ {"version":3,"file":"transition-flow.d.ts","sourceRoot":"","sources":["../src/transition-flow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAER,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAGjB,2DAA2D;AAC3D,MAAM,WAAW,2BAA2B;IACxC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;CACpD;AAED,0EAA0E;AAC1E,qBAAa,oBAAoB;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,2BAA2B;IAEjE,+DAA+D;IACzD,GAAG,CAAC,QAAQ,EAAE,yBAAyB,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAU9F,IAAI;CAgGrB"}
@@ -1,6 +1,6 @@
1
1
  import { FSMError } from './errors.js';
2
2
  import { allowedEnv, RunLifecycle, runtimeBuiltins } from './run-lifecycle.js';
3
- import { mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables.js';
3
+ import { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables.js';
4
4
  /** Transition-flow workflow driver with an R7 single control function. */
5
5
  export class TransitionFlowDriver {
6
6
  options;
@@ -15,7 +15,7 @@ export class TransitionFlowDriver {
15
15
  const runId = lifecycle.runId;
16
16
  const nodes = new Map(workflow.nodes.map((node) => [node.id, node]));
17
17
  const terminal = new Set(workflow.terminalNodes ?? []);
18
- const vars = mergeVars(workflow.vars, options.vars);
18
+ let vars = mergeVars(workflow.vars, options.vars);
19
19
  const env = allowedEnv(workflow.env?.allow ?? [], options.env);
20
20
  let current = nodes.get(workflow.initialNode);
21
21
  let transitionsTaken = 0;
@@ -45,11 +45,14 @@ export class TransitionFlowDriver {
45
45
  vars,
46
46
  env,
47
47
  metadata: options.metadata,
48
+ events: options.events,
48
49
  });
49
50
  }
50
51
  finally {
51
52
  lifecycle.actionDone(current.id, current.action.kind, Date.now() - actionStartMs, lastActionResult?.ok ?? false);
52
53
  }
54
+ if (lastActionResult.setVars)
55
+ vars = mergeSetVars(vars, lastActionResult.setVars);
53
56
  if (!lastActionResult.ok) {
54
57
  const policy = resolveOnErrorPolicy(current.action.onError, defaultOnError, options.onError);
55
58
  if (policy === 'fail') {
package/dist/types.d.ts CHANGED
@@ -101,6 +101,8 @@ export interface ActionRunContext {
101
101
  readonly vars: Vars;
102
102
  readonly env: Record<string, string>;
103
103
  readonly metadata?: Record<string, unknown>;
104
+ /** Optional event bus for in-process run observability. Action runners can emit workflow events through this. */
105
+ readonly events?: EventBus<WorkflowEngineEvents>;
104
106
  }
105
107
  /** Result of a single action execution. */
106
108
  export interface ActionResult {
@@ -108,6 +110,8 @@ export interface ActionResult {
108
110
  readonly data?: Record<string, unknown>;
109
111
  readonly error?: string;
110
112
  readonly terminal?: boolean;
113
+ /** Variables to merge into the run's vars for subsequent steps. Shallow string→string override. */
114
+ readonly setVars?: Vars;
111
115
  }
112
116
  /** Action runner implementation registered in the workflow host. */
113
117
  export interface ActionRunner {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,12 @@ export interface VariableContext {
7
7
  }
8
8
  /** Merge workflow vars with caller overrides; caller values win. */
9
9
  export declare function mergeVars(workflowVars?: Vars, overrideVars?: Vars): Vars;
10
+ /**
11
+ * Merge action-set vars into the run-local vars map. Only string→string entries
12
+ * are accepted; non-string values are silently dropped as a defensive measure
13
+ * (the action layer should never produce them, but fail safe).
14
+ */
15
+ export declare function mergeSetVars(vars: Vars, setVars: Vars | undefined): Vars;
10
16
  /** Resolve templates inside an unknown options value. */
11
17
  export declare function resolveTemplates<T>(value: T, context: VariableContext): T;
12
18
  /** Resolve a single template string. */
@@ -1 +1 @@
1
- {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../src/variables.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAInD,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;CACnE;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,YAAY,GAAE,IAAS,EAAE,YAAY,GAAE,IAAS,GAAG,IAAI,CAEhF;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAgBzE;AAED,wCAAwC;AACxC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAmBrF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,eAAe,EAAE,aAAa,GAAG,SAAS,EAC1C,iBAAiB,EAAE,aAAa,GAAG,SAAS,GAC7C,aAAa,CAEf"}
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../src/variables.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAInD,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;CACnE;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,YAAY,GAAE,IAAS,EAAE,YAAY,GAAE,IAAS,GAAG,IAAI,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAOxE;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAgBzE;AAED,wCAAwC;AACxC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAmBrF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,aAAa,EAAE,aAAa,GAAG,SAAS,EACxC,eAAe,EAAE,aAAa,GAAG,SAAS,EAC1C,iBAAiB,EAAE,aAAa,GAAG,SAAS,GAC7C,aAAa,CAEf"}
package/dist/variables.js CHANGED
@@ -4,6 +4,21 @@ const TEMPLATE_REF = /\$\{([^}]+)\}/g;
4
4
  export function mergeVars(workflowVars = {}, overrideVars = {}) {
5
5
  return { ...workflowVars, ...overrideVars };
6
6
  }
7
+ /**
8
+ * Merge action-set vars into the run-local vars map. Only string→string entries
9
+ * are accepted; non-string values are silently dropped as a defensive measure
10
+ * (the action layer should never produce them, but fail safe).
11
+ */
12
+ export function mergeSetVars(vars, setVars) {
13
+ if (setVars === undefined)
14
+ return vars;
15
+ const filtered = {};
16
+ for (const [key, value] of Object.entries(setVars)) {
17
+ if (typeof value === 'string')
18
+ filtered[key] = value;
19
+ }
20
+ return mergeVars(vars, filtered);
21
+ }
7
22
  /** Resolve templates inside an unknown options value. */
8
23
  export function resolveTemplates(value, context) {
9
24
  if (typeof value === 'string') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/ts-dual-workflow-engine",
3
- "version": "0.3.7",
3
+ "version": "0.3.10",
4
4
  "description": "@gobing-ai/ts-dual-workflow-engine — State-machine and transition-flow workflow runtime.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -48,9 +48,9 @@
48
48
  "release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-dual-workflow-engine-v<version> && git push --tags' && exit 1"
49
49
  },
50
50
  "dependencies": {
51
- "@gobing-ai/ts-db": "^0.3.7",
52
- "@gobing-ai/ts-infra": "^0.3.7",
53
- "@gobing-ai/ts-runtime": "^0.3.7",
51
+ "@gobing-ai/ts-db": "^0.3.10",
52
+ "@gobing-ai/ts-infra": "^0.3.10",
53
+ "@gobing-ai/ts-runtime": "^0.3.10",
54
54
  "zod": "^4.1.0"
55
55
  },
56
56
  "devDependencies": {
package/src/events.ts CHANGED
@@ -16,4 +16,8 @@ export type WorkflowEngineEvents = {
16
16
  'workflow.action.done': (data: { node: string; kind: string; durationMs: number; ok: boolean }) => void;
17
17
  /** Emitted when a non-fatal action failure is continued past (onError: 'continue'). */
18
18
  'workflow.action.failed_continue': (data: { node: string; transitionsTaken: number; error?: string }) => void;
19
+ /** Emitted by the builtin `event.emit` action for custom user-defined events. */
20
+ 'workflow.custom': (data: { name: string; payload: Record<string, unknown> }) => void;
21
+ /** Emitted by the builtin `note` action for workflow-visible annotations. */
22
+ 'workflow.hitl.note': (data: { node: string; message: string }) => void;
19
23
  };
package/src/hitl.ts ADDED
@@ -0,0 +1,30 @@
1
+ /** Categories of human-in-the-loop interaction. */
2
+ export type HitlRequestKind = 'confirm' | 'select' | 'input';
3
+
4
+ /** A request for human input during workflow execution. */
5
+ export interface HitlRequest {
6
+ kind: HitlRequestKind;
7
+ prompt: string;
8
+ /** select: the choices; confirm: optional labels; input: ignored. */
9
+ options?: string[];
10
+ /** echoed back for correlation. */
11
+ runId: string;
12
+ node: string;
13
+ }
14
+
15
+ /** The user's response to a HITL request. */
16
+ export interface HitlAnswer {
17
+ /** confirm -> 'yes'|'no'|'cancel'; select -> chosen option; input -> free text. */
18
+ value: string;
19
+ /** convenience: true when the user cancelled (confirm 'cancel'). */
20
+ cancelled?: boolean;
21
+ }
22
+
23
+ /**
24
+ * Contract for resolving HITL requests. Implementations are per-host
25
+ * (spur provides CLI/headless responders in task 0035). This engine
26
+ * package ships the interface only — no implementation.
27
+ */
28
+ export interface HitlResponder {
29
+ respond(request: HitlRequest): Promise<HitlAnswer>;
30
+ }
package/src/host.ts CHANGED
@@ -72,6 +72,7 @@ export function createDefaultWorkflowEngineHost(
72
72
  const host = new WorkflowEngineHost();
73
73
  host.registerAction(new NoteActionRunner(), 'builtin');
74
74
  host.registerAction(new ShellActionRunner(options.processExecutor ?? new NodeProcessExecutor()), 'builtin');
75
+ host.registerAction(new EventEmitActionRunner(), 'builtin');
75
76
  host.registerGuard({ kind: 'always', evaluate: async () => true }, 'builtin');
76
77
  host.registerGuard({ kind: 'never', evaluate: async () => false }, 'builtin');
77
78
  host.registerGuard(
@@ -84,13 +85,28 @@ export function createDefaultWorkflowEngineHost(
84
85
  return host;
85
86
  }
86
87
 
87
- /** Built-in action that records a note in result data. */
88
+ /** Built-in action that records a note and emits a workflow.hitl.note event. */
88
89
  export class NoteActionRunner implements ActionRunner {
89
90
  readonly kind = 'note';
90
91
 
91
- /** Execute a no-op note action. */
92
- async execute(options: Record<string, unknown>): Promise<ActionResult> {
93
- return { ok: true, data: { message: String(options.message ?? '') } };
92
+ /** Execute a no-op note action with observable event emission. */
93
+ async execute(options: Record<string, unknown>, context?: ActionRunContext): Promise<ActionResult> {
94
+ const message = String(options.message ?? '');
95
+ void context?.events?.emit('workflow.hitl.note', { node: context.stateOrNodeId, message });
96
+ return { ok: true, data: { message } };
97
+ }
98
+ }
99
+
100
+ /** Built-in action that emits a typed `workflow.custom` event on the run's event bus. */
101
+ export class EventEmitActionRunner implements ActionRunner {
102
+ readonly kind = 'event.emit';
103
+
104
+ async execute(options: Record<string, unknown>, context?: ActionRunContext): Promise<ActionResult> {
105
+ const name = String(options.name ?? '');
106
+ if (!name) return { ok: false, error: 'event.emit requires a non-empty "name" option' };
107
+ const payload = (options.payload as Record<string, unknown>) ?? {};
108
+ void context?.events?.emit('workflow.custom', { name, payload });
109
+ return { ok: true, data: { name, payload } };
94
110
  }
95
111
  }
96
112
 
@@ -100,13 +116,23 @@ export class ShellActionRunner implements ActionRunner {
100
116
 
101
117
  constructor(private readonly processExecutor: ProcessExecutor) {}
102
118
 
103
- /** Execute a shell command with optional args and cwd. */
119
+ /**
120
+ * Execute a shell command. Two forms:
121
+ * - `command` + explicit `args` → run `command` as a program with those argv (no shell).
122
+ * - `command` alone → treat it as a shell command line and run it via `sh -c`, so operators
123
+ * can use shell features (`&&`, `|`, quoting, globs) as in `bun run autofix && bun run spur-check`.
124
+ *
125
+ * The bare-`command` form is by far the common case; running it directly as a program name —
126
+ * the old behavior — fails with a null exit code for any line containing spaces.
127
+ */
104
128
  async execute(options: Record<string, unknown>, context: ActionRunContext): Promise<ActionResult> {
105
129
  const command = stringOption(options, 'command');
106
- const args = arrayOption(options, 'args');
130
+ const explicitArgs = arrayOption(options, 'args');
131
+ const usesShell = explicitArgs.length === 0;
132
+ const spawn = usesShell ? { command: '/bin/sh', args: ['-c', command] } : { command, args: explicitArgs };
107
133
  const result = await this.processExecutor.run({
108
- command,
109
- args,
134
+ command: spawn.command,
135
+ args: spawn.args,
110
136
  cwd: stringOption(options, 'cwd', context.workdir),
111
137
  rejectOnError: false,
112
138
  forceBuffered: true,
package/src/index.ts CHANGED
@@ -8,8 +8,10 @@ export {
8
8
  type WorkflowExtensionLogger,
9
9
  type WorkflowExtensionRef,
10
10
  } from './extensions';
11
+ export type { HitlAnswer, HitlRequest, HitlRequestKind, HitlResponder } from './hitl';
11
12
  export {
12
13
  createDefaultWorkflowEngineHost,
14
+ EventEmitActionRunner,
13
15
  NoteActionRunner,
14
16
  ShellActionRunner,
15
17
  WorkflowEngineHost,
@@ -63,6 +65,7 @@ export type {
63
65
  WorkflowStatus,
64
66
  } from './types';
65
67
  export {
68
+ mergeSetVars,
66
69
  mergeVars,
67
70
  resolveOnErrorPolicy,
68
71
  resolveTemplateString,
@@ -122,7 +122,6 @@ export class RunLifecycle {
122
122
  await this.persistence.savePhase(this.runId, stateOrNodeId, 'running');
123
123
  addSpanEvent('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
124
124
  void this.events?.emit('workflow.node.enter', { node: stateOrNodeId, transitionsTaken });
125
- this.logger.debug('entered', { node: stateOrNodeId, transitionsTaken });
126
125
  }
127
126
 
128
127
  /** Persist a transition and emit its observability event. */
@@ -130,7 +129,6 @@ export class RunLifecycle {
130
129
  await this.persistence.saveTransition(this.runId, from, to, trigger);
131
130
  addSpanEvent('workflow.node.transition', { from, to, ...(trigger === null ? {} : { trigger }) });
132
131
  void this.events?.emit('workflow.node.transition', { from, to, trigger });
133
- this.logger.debug('transition', { from, to, trigger });
134
132
  }
135
133
 
136
134
  /** Finalize the run as succeeded and return its result. */
@@ -10,7 +10,7 @@ import type {
10
10
  WorkflowRunOptions,
11
11
  WorkflowRunResult,
12
12
  } from './types';
13
- import { mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables';
13
+ import { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables';
14
14
 
15
15
  /** Dependencies required by the state-machine driver. */
16
16
  export interface StateMachineDriverOptions {
@@ -41,7 +41,7 @@ export class StateMachineDriver {
41
41
  const runId = lifecycle.runId;
42
42
  const states = new Map(workflow.states.map((state) => [state.id, state]));
43
43
  const terminal = new Set(workflow.terminalStates ?? []);
44
- const vars = mergeVars(workflow.vars, options.vars);
44
+ let vars = mergeVars(workflow.vars, options.vars);
45
45
  const env = allowedEnv(workflow.env?.allow ?? [], options.env);
46
46
  let current = states.get(workflow.initialState);
47
47
  let transitionsTaken = 0;
@@ -73,7 +73,7 @@ export class StateMachineDriver {
73
73
  // driver's `continue` semantics. A state with no enter actions must not
74
74
  // erase the previous result.
75
75
  if (enter.result !== undefined) lastActionResult = enter.result;
76
- // 3. Stop immediately when an action explicitly declares terminal success.
76
+ if (enter.result?.setVars) vars = mergeSetVars(vars, enter.result.setVars);
77
77
  if (enter.outcome === 'terminal') {
78
78
  return await lifecycle.done(current.id, transitionsTaken);
79
79
  }
@@ -112,6 +112,7 @@ export class StateMachineDriver {
112
112
  defaultOnError,
113
113
  );
114
114
  if (exit.result !== undefined) lastActionResult = exit.result;
115
+ if (exit.result?.setVars) vars = mergeSetVars(vars, exit.result.setVars);
115
116
  if (exit.outcome === 'fail') return await lifecycle.fail(current.id, transitionsTaken, exit.result?.error);
116
117
 
117
118
  // 7. Persist transition and move to the target state.
@@ -161,6 +162,7 @@ export class StateMachineDriver {
161
162
  vars,
162
163
  env,
163
164
  metadata: options.metadata,
165
+ events: options.events,
164
166
  });
165
167
  } finally {
166
168
  lifecycle.actionDone(stateId, action.kind, Date.now() - actionStartMs, last?.ok ?? false);
@@ -8,7 +8,7 @@ import type {
8
8
  WorkflowRunOptions,
9
9
  WorkflowRunResult,
10
10
  } from './types';
11
- import { mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables';
11
+ import { mergeSetVars, mergeVars, resolveOnErrorPolicy, resolveTemplates } from './variables';
12
12
 
13
13
  /** Dependencies required by the transition-flow driver. */
14
14
  export interface TransitionFlowDriverOptions {
@@ -39,7 +39,7 @@ export class TransitionFlowDriver {
39
39
  const runId = lifecycle.runId;
40
40
  const nodes = new Map(workflow.nodes.map((node) => [node.id, node]));
41
41
  const terminal = new Set(workflow.terminalNodes ?? []);
42
- const vars = mergeVars(workflow.vars, options.vars);
42
+ let vars = mergeVars(workflow.vars, options.vars);
43
43
  const env = allowedEnv(workflow.env?.allow ?? [], options.env);
44
44
  let current = nodes.get(workflow.initialNode);
45
45
  let transitionsTaken = 0;
@@ -72,6 +72,7 @@ export class TransitionFlowDriver {
72
72
  vars,
73
73
  env,
74
74
  metadata: options.metadata,
75
+ events: options.events,
75
76
  });
76
77
  } finally {
77
78
  lifecycle.actionDone(
@@ -81,6 +82,7 @@ export class TransitionFlowDriver {
81
82
  lastActionResult?.ok ?? false,
82
83
  );
83
84
  }
85
+ if (lastActionResult.setVars) vars = mergeSetVars(vars, lastActionResult.setVars);
84
86
  if (!lastActionResult.ok) {
85
87
  const policy = resolveOnErrorPolicy(current.action.onError, defaultOnError, options.onError);
86
88
  if (policy === 'fail') {
package/src/types.ts CHANGED
@@ -115,6 +115,8 @@ export interface ActionRunContext {
115
115
  readonly vars: Vars;
116
116
  readonly env: Record<string, string>;
117
117
  readonly metadata?: Record<string, unknown>;
118
+ /** Optional event bus for in-process run observability. Action runners can emit workflow events through this. */
119
+ readonly events?: EventBus<WorkflowEngineEvents>;
118
120
  }
119
121
 
120
122
  /** Result of a single action execution. */
@@ -123,6 +125,8 @@ export interface ActionResult {
123
125
  readonly data?: Record<string, unknown>;
124
126
  readonly error?: string;
125
127
  readonly terminal?: boolean;
128
+ /** Variables to merge into the run's vars for subsequent steps. Shallow string→string override. */
129
+ readonly setVars?: Vars;
126
130
  }
127
131
 
128
132
  /** Action runner implementation registered in the workflow host. */
package/src/variables.ts CHANGED
@@ -15,6 +15,20 @@ export function mergeVars(workflowVars: Vars = {}, overrideVars: Vars = {}): Var
15
15
  return { ...workflowVars, ...overrideVars };
16
16
  }
17
17
 
18
+ /**
19
+ * Merge action-set vars into the run-local vars map. Only string→string entries
20
+ * are accepted; non-string values are silently dropped as a defensive measure
21
+ * (the action layer should never produce them, but fail safe).
22
+ */
23
+ export function mergeSetVars(vars: Vars, setVars: Vars | undefined): Vars {
24
+ if (setVars === undefined) return vars;
25
+ const filtered: Vars = {};
26
+ for (const [key, value] of Object.entries(setVars)) {
27
+ if (typeof value === 'string') filtered[key] = value;
28
+ }
29
+ return mergeVars(vars, filtered);
30
+ }
31
+
18
32
  /** Resolve templates inside an unknown options value. */
19
33
  export function resolveTemplates<T>(value: T, context: VariableContext): T {
20
34
  if (typeof value === 'string') {