@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 +2 -1
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/hitl.d.ts +28 -0
- package/dist/hitl.d.ts.map +1 -0
- package/dist/hitl.js +0 -0
- package/dist/host.d.ts +17 -4
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +33 -8
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/run-lifecycle.d.ts.map +1 -1
- package/dist/run-lifecycle.js +0 -2
- package/dist/state-machine.d.ts.map +1 -1
- package/dist/state-machine.js +7 -3
- package/dist/transition-flow.d.ts.map +1 -1
- package/dist/transition-flow.js +5 -2
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/variables.d.ts +6 -0
- package/dist/variables.d.ts.map +1 -1
- package/dist/variables.js +15 -0
- package/package.json +4 -4
- package/src/events.ts +4 -0
- package/src/hitl.ts +30 -0
- package/src/host.ts +34 -8
- package/src/index.ts +3 -0
- package/src/run-lifecycle.ts +0 -2
- package/src/state-machine.ts +5 -3
- package/src/transition-flow.ts +4 -2
- package/src/types.ts +4 -0
- package/src/variables.ts +14 -0
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
|
package/dist/events.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
package/dist/host.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
|
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 {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAa,KAAK,MAAM,EAAc,MAAM,qBAAqB,CAAC;AAEtG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EACR,0BAA0B,EAC1B,kBAAkB,EAElB,iBAAiB,EAEpB,MAAM,SAAS,CAAC;AAEjB,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAErD,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,wFASvB,CAAC;AAEX,mGAAmG;AACnG,wBAAgB,eAAe,CAC3B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,YAAY,GACnB,MAAM,CAAC,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAWhE;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CACtB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAmB,GAC7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIxB;AAED,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;CACpD;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IASjB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI;IATzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6C;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO;IAaP;;;;OAIG;WACU,GAAG,CACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,CAAC,SAAS,EAAE,YAAY,KAAK,OAAO,CAAC,iBAAiB,CAAC,GAC9D,OAAO,CAAC,iBAAiB,CAAC;IAgB7B,0EAA0E;IACpE,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../src/run-lifecycle.ts"],"names":[],"mappings":"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"}
|
package/dist/run-lifecycle.js
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/state-machine.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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;
|
|
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"}
|
package/dist/transition-flow.js
CHANGED
|
@@ -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
|
-
|
|
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 {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/variables.d.ts
CHANGED
|
@@ -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. */
|
package/dist/variables.d.ts.map
CHANGED
|
@@ -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.
|
|
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.
|
|
52
|
-
"@gobing-ai/ts-infra": "^0.3.
|
|
53
|
-
"@gobing-ai/ts-runtime": "^0.3.
|
|
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
|
|
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
|
|
93
|
-
|
|
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
|
-
/**
|
|
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
|
|
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,
|
package/src/run-lifecycle.ts
CHANGED
|
@@ -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. */
|
package/src/state-machine.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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);
|
package/src/transition-flow.ts
CHANGED
|
@@ -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
|
-
|
|
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') {
|