@gobing-ai/ts-dual-workflow-engine 0.3.0 → 0.3.2

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.
Files changed (49) hide show
  1. package/README.md +506 -5
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +7 -11
  5. package/dist/events.d.ts +49 -0
  6. package/dist/events.d.ts.map +1 -0
  7. package/dist/events.js +0 -0
  8. package/dist/extensions.d.ts +60 -0
  9. package/dist/extensions.d.ts.map +1 -0
  10. package/dist/extensions.js +85 -0
  11. package/dist/host.d.ts +15 -2
  12. package/dist/host.d.ts.map +1 -1
  13. package/dist/host.js +42 -17
  14. package/dist/index.d.ts +5 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -1
  17. package/dist/run-lifecycle.d.ts +58 -0
  18. package/dist/run-lifecycle.d.ts.map +1 -0
  19. package/dist/run-lifecycle.js +149 -0
  20. package/dist/schema-sql.d.ts +1 -0
  21. package/dist/schema-sql.d.ts.map +1 -1
  22. package/dist/schema-sql.js +1 -0
  23. package/dist/schema.d.ts +44 -0
  24. package/dist/schema.d.ts.map +1 -1
  25. package/dist/schema.js +3 -0
  26. package/dist/state-machine.d.ts +7 -2
  27. package/dist/state-machine.d.ts.map +1 -1
  28. package/dist/state-machine.js +63 -72
  29. package/dist/transition-flow.d.ts +1 -2
  30. package/dist/transition-flow.d.ts.map +1 -1
  31. package/dist/transition-flow.js +35 -61
  32. package/dist/types.d.ts +14 -0
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/variables.d.ts +6 -1
  35. package/dist/variables.d.ts.map +1 -1
  36. package/dist/variables.js +7 -0
  37. package/package.json +4 -4
  38. package/src/config.ts +8 -11
  39. package/src/events.ts +19 -0
  40. package/src/extensions.ts +163 -0
  41. package/src/host.ts +54 -20
  42. package/src/index.ts +24 -1
  43. package/src/run-lifecycle.ts +211 -0
  44. package/src/schema-sql.ts +1 -0
  45. package/src/schema.ts +3 -0
  46. package/src/state-machine.ts +78 -128
  47. package/src/transition-flow.ts +47 -105
  48. package/src/types.ts +16 -0
  49. package/src/variables.ts +13 -1
package/dist/schema.d.ts CHANGED
@@ -3,6 +3,10 @@ import { z } from 'zod';
3
3
  export declare const ActionDefSchema: z.ZodObject<{
4
4
  kind: z.ZodString;
5
5
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
6
+ onError: z.ZodOptional<z.ZodEnum<{
7
+ fail: "fail";
8
+ continue: "continue";
9
+ }>>;
6
10
  }, z.core.$strip>;
7
11
  /** Zod schema for workflow guard definitions. */
8
12
  export declare const GuardDefSchema: z.ZodObject<{
@@ -19,6 +23,10 @@ export declare const StateMachineWorkflowDefSchema: z.ZodObject<{
19
23
  initialState: z.ZodString;
20
24
  terminalStates: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
25
  iterationBound: z.ZodOptional<z.ZodNumber>;
26
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
27
+ fail: "fail";
28
+ continue: "continue";
29
+ }>>;
22
30
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
31
  env: z.ZodOptional<z.ZodObject<{
24
32
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -29,10 +37,18 @@ export declare const StateMachineWorkflowDefSchema: z.ZodObject<{
29
37
  onEnter: z.ZodOptional<z.ZodArray<z.ZodObject<{
30
38
  kind: z.ZodString;
31
39
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
40
+ onError: z.ZodOptional<z.ZodEnum<{
41
+ fail: "fail";
42
+ continue: "continue";
43
+ }>>;
32
44
  }, z.core.$strip>>>;
33
45
  onExit: z.ZodOptional<z.ZodArray<z.ZodObject<{
34
46
  kind: z.ZodString;
35
47
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
48
+ onError: z.ZodOptional<z.ZodEnum<{
49
+ fail: "fail";
50
+ continue: "continue";
51
+ }>>;
36
52
  }, z.core.$strip>>>;
37
53
  }, z.core.$strict>>;
38
54
  transitions: z.ZodArray<z.ZodObject<{
@@ -56,6 +72,10 @@ export declare const TransitionFlowWorkflowDefSchema: z.ZodObject<{
56
72
  initialNode: z.ZodString;
57
73
  terminalNodes: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
74
  iterationBound: z.ZodOptional<z.ZodNumber>;
75
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
76
+ fail: "fail";
77
+ continue: "continue";
78
+ }>>;
59
79
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
60
80
  env: z.ZodOptional<z.ZodObject<{
61
81
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -72,6 +92,10 @@ export declare const TransitionFlowWorkflowDefSchema: z.ZodObject<{
72
92
  action: z.ZodOptional<z.ZodObject<{
73
93
  kind: z.ZodString;
74
94
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
95
+ onError: z.ZodOptional<z.ZodEnum<{
96
+ fail: "fail";
97
+ continue: "continue";
98
+ }>>;
75
99
  }, z.core.$strip>>;
76
100
  }, z.core.$strict>>;
77
101
  edges: z.ZodArray<z.ZodObject<{
@@ -94,6 +118,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
94
118
  initialState: z.ZodString;
95
119
  terminalStates: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
120
  iterationBound: z.ZodOptional<z.ZodNumber>;
121
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
122
+ fail: "fail";
123
+ continue: "continue";
124
+ }>>;
97
125
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
98
126
  env: z.ZodOptional<z.ZodObject<{
99
127
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -104,10 +132,18 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
104
132
  onEnter: z.ZodOptional<z.ZodArray<z.ZodObject<{
105
133
  kind: z.ZodString;
106
134
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
135
+ onError: z.ZodOptional<z.ZodEnum<{
136
+ fail: "fail";
137
+ continue: "continue";
138
+ }>>;
107
139
  }, z.core.$strip>>>;
108
140
  onExit: z.ZodOptional<z.ZodArray<z.ZodObject<{
109
141
  kind: z.ZodString;
110
142
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
143
+ onError: z.ZodOptional<z.ZodEnum<{
144
+ fail: "fail";
145
+ continue: "continue";
146
+ }>>;
111
147
  }, z.core.$strip>>>;
112
148
  }, z.core.$strict>>;
113
149
  transitions: z.ZodArray<z.ZodObject<{
@@ -129,6 +165,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
129
165
  initialNode: z.ZodString;
130
166
  terminalNodes: z.ZodOptional<z.ZodArray<z.ZodString>>;
131
167
  iterationBound: z.ZodOptional<z.ZodNumber>;
168
+ defaultOnError: z.ZodOptional<z.ZodEnum<{
169
+ fail: "fail";
170
+ continue: "continue";
171
+ }>>;
132
172
  vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
133
173
  env: z.ZodOptional<z.ZodObject<{
134
174
  allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -145,6 +185,10 @@ export declare const WorkflowDefSchema: z.ZodUnion<readonly [z.ZodObject<{
145
185
  action: z.ZodOptional<z.ZodObject<{
146
186
  kind: z.ZodString;
147
187
  options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
188
+ onError: z.ZodOptional<z.ZodEnum<{
189
+ fail: "fail";
190
+ continue: "continue";
191
+ }>>;
148
192
  }, z.core.$strip>>;
149
193
  }, z.core.$strict>>;
150
194
  edges: z.ZodArray<z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,kDAAkD;AAClD,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAEH,yDAAyD;AACzD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmC7B,CAAC;AAEd,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkC/B,CAAC;AAEd,iEAAiE;AACjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAA4E,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,kDAAkD;AAClD,eAAO,MAAM,eAAe;;;;;;;iBAI1B,CAAC;AAEH,iDAAiD;AACjD,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AAEH,yDAAyD;AACzD,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAoC7B,CAAC;AAEd,2DAA2D;AAC3D,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmC/B,CAAC;AAEd,iEAAiE;AACjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAA4E,CAAC"}
package/dist/schema.js CHANGED
@@ -22,6 +22,7 @@ const EnvSchema = z.object({
22
22
  export const ActionDefSchema = z.object({
23
23
  kind: z.string().min(1),
24
24
  options: z.record(z.string(), z.unknown()).optional(),
25
+ onError: z.enum(['fail', 'continue']).optional(),
25
26
  });
26
27
  /** Zod schema for workflow guard definitions. */
27
28
  export const GuardDefSchema = z.object({
@@ -40,6 +41,7 @@ export const StateMachineWorkflowDefSchema = z
40
41
  initialState: z.string().min(1),
41
42
  terminalStates: z.array(z.string().min(1)).optional(),
42
43
  iterationBound: z.number().int().positive().optional(),
44
+ defaultOnError: z.enum(['fail', 'continue']).optional(),
43
45
  vars: VarsSchema.optional(),
44
46
  env: EnvSchema.optional(),
45
47
  states: z.array(z
@@ -73,6 +75,7 @@ export const TransitionFlowWorkflowDefSchema = z
73
75
  initialNode: z.string().min(1),
74
76
  terminalNodes: z.array(z.string().min(1)).optional(),
75
77
  iterationBound: z.number().int().positive().optional(),
78
+ defaultOnError: z.enum(['fail', 'continue']).optional(),
76
79
  vars: VarsSchema.optional(),
77
80
  env: EnvSchema.optional(),
78
81
  nodes: z.array(z
@@ -11,8 +11,13 @@ export declare class StateMachineDriver {
11
11
  constructor(options: StateMachineDriverOptions);
12
12
  /** Run a state-machine workflow to completion or failure. */
13
13
  run(workflow: StateMachineWorkflowDef, options?: WorkflowRunOptions): Promise<WorkflowRunResult>;
14
+ private loop;
15
+ /**
16
+ * Run a state's actions in order. Returns the last action result (retained even
17
+ * when a failure was continued past, so downstream guards can inspect it) plus an
18
+ * `outcome` discriminator: `terminal` (an action declared terminal success),
19
+ * `fail` (a failure under a 'fail' policy — caller must halt), or `completed`.
20
+ */
14
21
  private runActions;
15
- private done;
16
- private fail;
17
22
  }
18
23
  //# sourceMappingURL=state-machine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../src/state-machine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAGR,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAElB,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;YA8G5F,UAAU;YA8BV,IAAI;YAYJ,IAAI;CAYrB"}
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,6 +1,6 @@
1
- import { getProcessEnv } from '@gobing-ai/ts-runtime';
2
1
  import { FSMError } from './errors.js';
3
- import { mergeVars, resolveTemplates } from './variables.js';
2
+ import { allowedEnv, RunLifecycle, runtimeBuiltins } from './run-lifecycle.js';
3
+ import { 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;
@@ -9,36 +9,43 @@ export class StateMachineDriver {
9
9
  }
10
10
  /** Run a state-machine workflow to completion or failure. */
11
11
  async run(workflow, options = {}) {
12
- const runId = options.runId ?? crypto.randomUUID();
13
- const startedAt = new Date().toISOString();
14
- const mode = 'state-machine';
15
- await this.options.persistence.createRun(runRecord(runId, workflow.name, mode, startedAt, options.metadata));
12
+ return await RunLifecycle.run(workflow.name, 'state-machine', { persistence: this.options.persistence, events: options.events }, options, (lifecycle) => this.loop(workflow, options, lifecycle));
13
+ }
14
+ async loop(workflow, options, lifecycle) {
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
  const vars = mergeVars(workflow.vars, options.vars);
19
- const env = allowedEnv(workflow.env?.allow ?? [], options.env ?? getProcessEnv());
19
+ const env = allowedEnv(workflow.env?.allow ?? [], options.env);
20
20
  let current = states.get(workflow.initialState);
21
21
  let transitionsTaken = 0;
22
22
  let lastActionResult;
23
23
  const iterationBound = workflow.iterationBound ?? 50;
24
+ const defaultOnError = workflow.defaultOnError;
24
25
  if (current === undefined)
25
26
  throw new FSMError(`Initial state "${workflow.initialState}" is not declared`);
26
27
  while (true) {
27
28
  // 1. Persist current state snapshot before work starts.
28
- await this.options.persistence.saveWorkflowState(runId, current.id, { transitionsTaken });
29
- await this.options.persistence.savePhase(runId, current.id, 'running');
29
+ await lifecycle.enter(current.id, transitionsTaken);
30
30
  // 2. Execute this state's on-enter actions in declaration order.
31
- lastActionResult = await this.runActions(current.onEnter ?? [], workflow.name, current.id, runId, vars, env, options, transitionsTaken);
32
- if (lastActionResult?.ok === false)
33
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, lastActionResult.error);
31
+ const enter = await this.runActions(current.onEnter ?? [], workflow.name, current.id, runId, vars, env, options, transitionsTaken, lifecycle, defaultOnError);
32
+ // Retain the last action result (including failures the policy continued
33
+ // past) so downstream guards can inspect it — matching the transition-flow
34
+ // driver's `continue` semantics. A state with no enter actions must not
35
+ // erase the previous result.
36
+ if (enter.result !== undefined)
37
+ lastActionResult = enter.result;
34
38
  // 3. Stop immediately when an action explicitly declares terminal success.
35
- if (lastActionResult?.terminal === true) {
36
- return await this.done(runId, workflow.name, mode, current.id, transitionsTaken);
39
+ if (enter.outcome === 'terminal') {
40
+ return await lifecycle.done(current.id, transitionsTaken);
41
+ }
42
+ // 4. Halt only when an action failed under a 'fail' policy.
43
+ if (enter.outcome === 'fail') {
44
+ return await lifecycle.fail(current.id, transitionsTaken, lastActionResult?.error);
37
45
  }
38
- // 4. Stop when the current state is terminal or has no outbound transitions.
39
46
  const outbound = workflow.transitions.filter((transition) => transition.from === current?.id);
40
47
  if (terminal.has(current.id) || outbound.length === 0) {
41
- return await this.done(runId, workflow.name, mode, current.id, transitionsTaken);
48
+ return await lifecycle.done(current.id, transitionsTaken);
42
49
  }
43
50
  // 5. Evaluate transition guards in declaration order and pick the first passing transition.
44
51
  const nextTransition = await firstPassingTransition(outbound, this.options.host, {
@@ -48,17 +55,19 @@ export class StateMachineDriver {
48
55
  lastActionResult,
49
56
  });
50
57
  if (nextTransition === undefined) {
51
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, 'no-passing-transition');
58
+ return await lifecycle.fail(current.id, transitionsTaken, 'no-passing-transition');
52
59
  }
53
60
  // 6. Execute this state's on-exit actions before changing state.
54
- const exitResult = await this.runActions(current.onExit ?? [], workflow.name, current.id, runId, vars, env, options, transitionsTaken);
55
- if (exitResult?.ok === false)
56
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, exitResult.error);
61
+ const exit = await this.runActions(current.onExit ?? [], workflow.name, current.id, runId, vars, env, options, transitionsTaken, lifecycle, defaultOnError);
62
+ if (exit.result !== undefined)
63
+ lastActionResult = exit.result;
64
+ if (exit.outcome === 'fail')
65
+ return await lifecycle.fail(current.id, transitionsTaken, exit.result?.error);
57
66
  // 7. Persist transition and move to the target state.
58
67
  transitionsTaken += 1;
59
- await this.options.persistence.saveTransition(runId, current.id, nextTransition.to, nextTransition.trigger ?? null);
68
+ await lifecycle.recordTransition(current.id, nextTransition.to, nextTransition.trigger ?? null);
60
69
  if (transitionsTaken > iterationBound) {
61
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, 'iteration-bound-exceeded');
70
+ return await lifecycle.fail(current.id, transitionsTaken, 'iteration-bound-exceeded');
62
71
  }
63
72
  const nextState = states.get(nextTransition.to);
64
73
  if (nextState === undefined)
@@ -66,51 +75,47 @@ export class StateMachineDriver {
66
75
  current = nextState;
67
76
  }
68
77
  }
69
- async runActions(actions, workflowName, stateId, runId, vars, env, options, transitionsTaken) {
78
+ /**
79
+ * Run a state's actions in order. Returns the last action result (retained even
80
+ * when a failure was continued past, so downstream guards can inspect it) plus an
81
+ * `outcome` discriminator: `terminal` (an action declared terminal success),
82
+ * `fail` (a failure under a 'fail' policy — caller must halt), or `completed`.
83
+ */
84
+ async runActions(actions, workflowName, stateId, runId, vars, env, options, transitionsTaken, lifecycle, defaultOnError) {
70
85
  let last;
71
86
  for (const action of actions) {
72
87
  const resolved = resolveTemplates(action.options ?? {}, {
73
88
  vars,
74
89
  env,
75
- builtins: runtimeBuiltins(workflowName, stateId, runId, transitionsTaken),
90
+ builtins: runtimeBuiltins(workflowName, stateId, runId, transitionsTaken, 'state-machine'),
76
91
  });
77
- last = await this.options.host.runAction(action.kind, resolved, {
78
- runId,
79
- workdir: options.workdir,
80
- stateOrNodeId: stateId,
81
- vars,
82
- env,
83
- metadata: options.metadata,
84
- });
85
- if (!last.ok || last.terminal === true)
86
- return last;
92
+ const actionStartMs = Date.now();
93
+ lifecycle.actionStart(stateId, action.kind);
94
+ try {
95
+ last = await this.options.host.runAction(action.kind, resolved, {
96
+ runId,
97
+ workdir: options.workdir,
98
+ stateOrNodeId: stateId,
99
+ vars,
100
+ env,
101
+ metadata: options.metadata,
102
+ });
103
+ }
104
+ finally {
105
+ lifecycle.actionDone(stateId, action.kind, Date.now() - actionStartMs, last?.ok ?? false);
106
+ }
107
+ if (last.terminal === true)
108
+ return { outcome: 'terminal', result: last };
109
+ if (!last.ok) {
110
+ const policy = resolveOnErrorPolicy(action.onError, defaultOnError, options.onError);
111
+ if (policy === 'fail')
112
+ return { outcome: 'fail', result: last };
113
+ lifecycle.warnActionFailed(stateId, transitionsTaken, last.error);
114
+ }
87
115
  }
88
- return last;
89
- }
90
- async done(runId, workflowName, mode, finalState, transitionsTaken) {
91
- await this.options.persistence.savePhase(runId, finalState, 'done');
92
- await this.options.persistence.finalizeRun(runId, 'done', new Date().toISOString());
93
- return { runId, workflowName, mode, status: 'done', finalState, transitionsTaken };
94
- }
95
- async fail(runId, workflowName, mode, finalState, transitionsTaken, reason = 'failed') {
96
- await this.options.persistence.savePhase(runId, finalState, 'failed');
97
- await this.options.persistence.finalizeRun(runId, 'failed', new Date().toISOString());
98
- return { runId, workflowName, mode, status: 'failed', finalState, transitionsTaken, reason };
116
+ return { outcome: 'completed', result: last };
99
117
  }
100
118
  }
101
- /** Built-in bare template values available to state-machine action options. */
102
- function runtimeBuiltins(workflowName, stateId, runId, transitionsTaken) {
103
- return {
104
- workflow: workflowName,
105
- runId,
106
- task: workflowName,
107
- state: stateId,
108
- node: stateId,
109
- iteration: transitionsTaken,
110
- run: runId,
111
- runtime: 'state-machine',
112
- };
113
- }
114
119
  async function firstPassingTransition(transitions, host, context) {
115
120
  for (const transition of transitions) {
116
121
  if (transition.guard === undefined)
@@ -120,17 +125,3 @@ async function firstPassingTransition(transitions, host, context) {
120
125
  }
121
126
  return undefined;
122
127
  }
123
- function allowedEnv(names, source) {
124
- return Object.fromEntries(names.flatMap((name) => (source[name] === undefined ? [] : [[name, source[name]]])));
125
- }
126
- function runRecord(runId, workflowName, mode, startedAt, metadata) {
127
- return {
128
- id: runId,
129
- workflow_name: workflowName,
130
- mode,
131
- status: 'running',
132
- started_at: startedAt,
133
- completed_at: null,
134
- metadata_json: JSON.stringify(metadata ?? {}),
135
- };
136
- }
@@ -11,7 +11,6 @@ export declare class TransitionFlowDriver {
11
11
  constructor(options: TransitionFlowDriverOptions);
12
12
  /** Run a transition-flow workflow to completion or failure. */
13
13
  run(workflow: TransitionFlowWorkflowDef, options?: WorkflowRunOptions): Promise<WorkflowRunResult>;
14
- private done;
15
- private fail;
14
+ private loop;
16
15
  }
17
16
  //# sourceMappingURL=transition-flow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transition-flow.d.ts","sourceRoot":"","sources":["../src/transition-flow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAER,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAElB,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;YA8F9F,IAAI;YAYJ,IAAI;CAYrB"}
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,6 +1,6 @@
1
- import { getProcessEnv } from '@gobing-ai/ts-runtime';
2
1
  import { FSMError } from './errors.js';
3
- import { mergeVars, resolveTemplates } from './variables.js';
2
+ import { allowedEnv, RunLifecycle, runtimeBuiltins } from './run-lifecycle.js';
3
+ import { 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;
@@ -9,51 +9,62 @@ export class TransitionFlowDriver {
9
9
  }
10
10
  /** Run a transition-flow workflow to completion or failure. */
11
11
  async run(workflow, options = {}) {
12
- const runId = options.runId ?? crypto.randomUUID();
13
- const startedAt = new Date().toISOString();
14
- const mode = 'transition-flow';
15
- await this.options.persistence.createRun(runRecord(runId, workflow.name, mode, startedAt, options.metadata));
12
+ return await RunLifecycle.run(workflow.name, 'transition-flow', { persistence: this.options.persistence, events: options.events }, options, (lifecycle) => this.loop(workflow, options, lifecycle));
13
+ }
14
+ async loop(workflow, options, lifecycle) {
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
  const vars = mergeVars(workflow.vars, options.vars);
19
- const env = allowedEnv(workflow.env?.allow ?? [], options.env ?? getProcessEnv());
19
+ const env = allowedEnv(workflow.env?.allow ?? [], options.env);
20
20
  let current = nodes.get(workflow.initialNode);
21
21
  let transitionsTaken = 0;
22
22
  let lastActionResult;
23
23
  const iterationBound = workflow.iterationBound ?? 50;
24
+ const defaultOnError = workflow.defaultOnError;
24
25
  if (current === undefined) {
25
26
  throw new FSMError(`Initial node "${workflow.initialNode}" is not declared`);
26
27
  }
27
28
  while (true) {
28
29
  // 1. Persist current node snapshot before action execution.
29
- await this.options.persistence.saveWorkflowState(runId, current.id, { transitionsTaken });
30
- await this.options.persistence.savePhase(runId, current.id, 'running');
30
+ await lifecycle.enter(current.id, transitionsTaken);
31
31
  // 2. Execute the node action when one is configured.
32
32
  if (current.action !== undefined) {
33
33
  const resolved = resolveTemplates(current.action.options ?? {}, {
34
34
  vars,
35
35
  env,
36
- builtins: runtimeBuiltins(workflow.name, current.id, runId, transitionsTaken),
37
- });
38
- lastActionResult = await this.options.host.runAction(current.action.kind, resolved, {
39
- runId,
40
- workdir: options.workdir,
41
- stateOrNodeId: current.id,
42
- vars,
43
- env,
44
- metadata: options.metadata,
36
+ builtins: runtimeBuiltins(workflow.name, current.id, runId, transitionsTaken, 'transition-flow'),
45
37
  });
38
+ const actionStartMs = Date.now();
39
+ lifecycle.actionStart(current.id, current.action.kind);
40
+ try {
41
+ lastActionResult = await this.options.host.runAction(current.action.kind, resolved, {
42
+ runId,
43
+ workdir: options.workdir,
44
+ stateOrNodeId: current.id,
45
+ vars,
46
+ env,
47
+ metadata: options.metadata,
48
+ });
49
+ }
50
+ finally {
51
+ lifecycle.actionDone(current.id, current.action.kind, Date.now() - actionStartMs, lastActionResult?.ok ?? false);
52
+ }
46
53
  if (!lastActionResult.ok) {
47
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, lastActionResult.error);
54
+ const policy = resolveOnErrorPolicy(current.action.onError, defaultOnError, options.onError);
55
+ if (policy === 'fail') {
56
+ return await lifecycle.fail(current.id, transitionsTaken, lastActionResult.error);
57
+ }
58
+ lifecycle.warnActionFailed(current.id, transitionsTaken, lastActionResult.error);
48
59
  }
49
60
  if (lastActionResult.terminal === true) {
50
- return await this.done(runId, workflow.name, mode, current.id, transitionsTaken);
61
+ return await lifecycle.done(current.id, transitionsTaken);
51
62
  }
52
63
  }
53
64
  // 3. Stop when the node is terminal or no outgoing edge exists.
54
65
  const outbound = workflow.edges.filter((edge) => edge.from === current?.id);
55
66
  if (terminal.has(current.id) || outbound.length === 0) {
56
- return await this.done(runId, workflow.name, mode, current.id, transitionsTaken);
67
+ return await lifecycle.done(current.id, transitionsTaken);
57
68
  }
58
69
  // 4. Evaluate edge conditions in declaration order and pick the first passing edge.
59
70
  const edge = await firstPassingEdge(outbound, this.options.host, {
@@ -63,14 +74,14 @@ export class TransitionFlowDriver {
63
74
  lastActionResult,
64
75
  });
65
76
  if (edge === undefined) {
66
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, 'no-passing-edge');
77
+ return await lifecycle.fail(current.id, transitionsTaken, 'no-passing-edge');
67
78
  }
68
79
  // 5. Persist the edge transition.
69
80
  transitionsTaken += 1;
70
- await this.options.persistence.saveTransition(runId, current.id, edge.to, edge.condition?.kind ?? null);
81
+ await lifecycle.recordTransition(current.id, edge.to, edge.condition?.kind ?? null);
71
82
  // 6. Enforce the iteration bound after taking the transition.
72
83
  if (transitionsTaken > iterationBound) {
73
- return await this.fail(runId, workflow.name, mode, current.id, transitionsTaken, 'iteration-bound-exceeded');
84
+ return await lifecycle.fail(current.id, transitionsTaken, 'iteration-bound-exceeded');
74
85
  }
75
86
  // 7. Move to the target node and repeat.
76
87
  const nextNode = nodes.get(edge.to);
@@ -79,29 +90,6 @@ export class TransitionFlowDriver {
79
90
  current = nextNode;
80
91
  }
81
92
  }
82
- async done(runId, workflowName, mode, finalState, transitionsTaken) {
83
- await this.options.persistence.savePhase(runId, finalState, 'done');
84
- await this.options.persistence.finalizeRun(runId, 'done', new Date().toISOString());
85
- return { runId, workflowName, mode, status: 'done', finalState, transitionsTaken };
86
- }
87
- async fail(runId, workflowName, mode, finalState, transitionsTaken, reason = 'failed') {
88
- await this.options.persistence.savePhase(runId, finalState, 'failed');
89
- await this.options.persistence.finalizeRun(runId, 'failed', new Date().toISOString());
90
- return { runId, workflowName, mode, status: 'failed', finalState, transitionsTaken, reason };
91
- }
92
- }
93
- /** Built-in bare template values available to transition-flow action options. */
94
- function runtimeBuiltins(workflowName, nodeId, runId, transitionsTaken) {
95
- return {
96
- workflow: workflowName,
97
- runId,
98
- task: workflowName,
99
- state: nodeId,
100
- node: nodeId,
101
- iteration: transitionsTaken,
102
- run: runId,
103
- runtime: 'transition-flow',
104
- };
105
93
  }
106
94
  async function firstPassingEdge(edges, host, context) {
107
95
  for (const edge of edges) {
@@ -112,17 +100,3 @@ async function firstPassingEdge(edges, host, context) {
112
100
  }
113
101
  return undefined;
114
102
  }
115
- function allowedEnv(names, source) {
116
- return Object.fromEntries(names.flatMap((name) => (source[name] === undefined ? [] : [[name, source[name]]])));
117
- }
118
- function runRecord(runId, workflowName, mode, startedAt, metadata) {
119
- return {
120
- id: runId,
121
- workflow_name: workflowName,
122
- mode,
123
- status: 'running',
124
- started_at: startedAt,
125
- completed_at: null,
126
- metadata_json: JSON.stringify(metadata ?? {}),
127
- };
128
- }
package/dist/types.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ /** Action error handling policy: fail-fast or log-and-continue. */
2
+ export type OnErrorPolicy = 'fail' | 'continue';
3
+ import type { EventBus } from '@gobing-ai/ts-infra';
4
+ import type { WorkflowEngineEvents } from './events';
1
5
  /** Workflow execution status persisted for runs and phases. */
2
6
  export type WorkflowStatus = 'running' | 'done' | 'failed';
3
7
  /** Runtime variables and user variables available to workflow definitions. */
@@ -10,6 +14,8 @@ export interface Env {
10
14
  export interface ActionDef {
11
15
  readonly kind: string;
12
16
  readonly options?: Record<string, unknown>;
17
+ /** Per-action error policy override. Falls back to workflow default then run-option then 'fail'. */
18
+ readonly onError?: OnErrorPolicy;
13
19
  }
14
20
  /** Guard predicate definition used by state-machine transitions and transition-flow edges. */
15
21
  export interface GuardDef {
@@ -44,6 +50,8 @@ export interface StateMachineWorkflowDef {
44
50
  readonly initialState: string;
45
51
  readonly terminalStates?: readonly string[];
46
52
  readonly iterationBound?: number;
53
+ /** Default error policy applied to actions that don't specify their own. Defaults to 'fail'. */
54
+ readonly defaultOnError?: OnErrorPolicy;
47
55
  readonly vars?: Vars;
48
56
  readonly env?: Env;
49
57
  readonly states: readonly StateDef[];
@@ -76,6 +84,8 @@ export interface TransitionFlowWorkflowDef {
76
84
  readonly initialNode: string;
77
85
  readonly terminalNodes?: readonly string[];
78
86
  readonly iterationBound?: number;
87
+ /** Default error policy applied to actions that don't specify their own. Defaults to 'fail'. */
88
+ readonly defaultOnError?: OnErrorPolicy;
79
89
  readonly vars?: Vars;
80
90
  readonly env?: Env;
81
91
  readonly nodes: readonly FlowNodeDef[];
@@ -123,6 +133,10 @@ export interface WorkflowRunOptions {
123
133
  readonly vars?: Vars;
124
134
  readonly env?: Record<string, string | undefined>;
125
135
  readonly metadata?: Record<string, unknown>;
136
+ /** Optional event bus for structured run observability. */
137
+ readonly events?: EventBus<WorkflowEngineEvents>;
138
+ /** Run-level error policy override. Lowest precedence; action-level wins. */
139
+ readonly onError?: OnErrorPolicy;
126
140
  }
127
141
  /** Result returned by both driver loops. */
128
142
  export interface WorkflowRunResult {
@@ -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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"}
@@ -1,4 +1,4 @@
1
- import type { Vars } from './types';
1
+ import type { OnErrorPolicy, Vars } from './types';
2
2
  /** Runtime context used for workflow variable interpolation. */
3
3
  export interface VariableContext {
4
4
  readonly vars: Vars;
@@ -11,4 +11,9 @@ export declare function mergeVars(workflowVars?: Vars, overrideVars?: Vars): Var
11
11
  export declare function resolveTemplates<T>(value: T, context: VariableContext): T;
12
12
  /** Resolve a single template string. */
13
13
  export declare function resolveTemplateString(value: string, context: VariableContext): string;
14
+ /**
15
+ * Resolve the effective error policy via fixed precedence:
16
+ * `action.onError ?? workflow.defaultOnError ?? runOptions.onError ?? 'fail'`.
17
+ */
18
+ export declare function resolveOnErrorPolicy(actionOnError: OnErrorPolicy | undefined, workflowDefault: OnErrorPolicy | undefined, runOptionOverride: OnErrorPolicy | undefined): OnErrorPolicy;
14
19
  //# sourceMappingURL=variables.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../src/variables.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAIpC,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"}
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"}
package/dist/variables.js CHANGED
@@ -43,3 +43,10 @@ export function resolveTemplateString(value, context) {
43
43
  return String(resolved);
44
44
  });
45
45
  }
46
+ /**
47
+ * Resolve the effective error policy via fixed precedence:
48
+ * `action.onError ?? workflow.defaultOnError ?? runOptions.onError ?? 'fail'`.
49
+ */
50
+ export function resolveOnErrorPolicy(actionOnError, workflowDefault, runOptionOverride) {
51
+ return actionOnError ?? workflowDefault ?? runOptionOverride ?? 'fail';
52
+ }