@gobing-ai/ts-dual-workflow-engine 0.3.1 → 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.
- package/README.md +506 -5
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -11
- package/dist/events.d.ts +49 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +0 -0
- package/dist/extensions.d.ts +60 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +85 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/run-lifecycle.d.ts +58 -0
- package/dist/run-lifecycle.d.ts.map +1 -0
- package/dist/run-lifecycle.js +149 -0
- package/dist/schema-sql.d.ts +1 -0
- package/dist/schema-sql.d.ts.map +1 -1
- package/dist/schema-sql.js +1 -0
- package/dist/schema.d.ts +44 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +3 -0
- package/dist/state-machine.d.ts +7 -2
- package/dist/state-machine.d.ts.map +1 -1
- package/dist/state-machine.js +63 -72
- package/dist/transition-flow.d.ts +1 -2
- package/dist/transition-flow.d.ts.map +1 -1
- package/dist/transition-flow.js +35 -61
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/variables.d.ts +6 -1
- package/dist/variables.d.ts.map +1 -1
- package/dist/variables.js +7 -0
- package/package.json +4 -4
- package/src/config.ts +8 -11
- package/src/events.ts +19 -0
- package/src/extensions.ts +163 -0
- package/src/index.ts +24 -1
- package/src/run-lifecycle.ts +211 -0
- package/src/schema-sql.ts +1 -0
- package/src/schema.ts +3 -0
- package/src/state-machine.ts +78 -128
- package/src/transition-flow.ts +47 -105
- package/src/types.ts +16 -0
- package/src/variables.ts +13 -1
package/dist/state-machine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getProcessEnv } from '@gobing-ai/ts-runtime';
|
|
2
1
|
import { FSMError } from './errors.js';
|
|
3
|
-
import {
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 (
|
|
36
|
-
return await
|
|
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
|
|
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
|
|
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
|
|
55
|
-
if (
|
|
56
|
-
|
|
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
|
|
68
|
+
await lifecycle.recordTransition(current.id, nextTransition.to, nextTransition.trigger ?? null);
|
|
60
69
|
if (transitionsTaken > iterationBound) {
|
|
61
|
-
return await
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
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":"
|
|
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"}
|
package/dist/transition-flow.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getProcessEnv } from '@gobing-ai/ts-runtime';
|
|
2
1
|
import { FSMError } from './errors.js';
|
|
3
|
-
import {
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1C,8DAA8D;AAC9D,MAAM,WAAW,GAAG;IAChB,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,mEAAmE;AACnE,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/variables.d.ts
CHANGED
|
@@ -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
|
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,IAAI,EAAE,MAAM,SAAS,CAAC;
|
|
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
|
+
}
|
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.2",
|
|
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-
|
|
53
|
-
"@gobing-ai/ts-
|
|
51
|
+
"@gobing-ai/ts-db": "^0.3.2",
|
|
52
|
+
"@gobing-ai/ts-infra": "^0.3.2",
|
|
53
|
+
"@gobing-ai/ts-runtime": "^0.3.2",
|
|
54
54
|
"zod": "^4.1.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
package/src/config.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { loadStructuredConfig, parseYamlObject } from '@gobing-ai/ts-runtime';
|
|
2
2
|
import { WorkflowValidationError } from './errors';
|
|
3
|
+
import { RUNTIME_BUILTIN_KEYS } from './run-lifecycle';
|
|
3
4
|
import { StateMachineWorkflowDefSchema, TransitionFlowWorkflowDefSchema } from './schema';
|
|
4
5
|
import type { WorkflowDef } from './types';
|
|
5
6
|
|
|
7
|
+
/** Loading options for {@link loadWorkflowDef}. */
|
|
6
8
|
export interface WorkflowLoadOptions {
|
|
7
9
|
/** When true, honor a top-level `$schema` ref. Defaults to true for file loads. */
|
|
8
10
|
validateSchema?: boolean;
|
|
@@ -177,17 +179,12 @@ function collectActionOptions(workflow: WorkflowDef): Record<string, unknown>[]
|
|
|
177
179
|
return optionSets;
|
|
178
180
|
}
|
|
179
181
|
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
'node',
|
|
187
|
-
'iteration',
|
|
188
|
-
'run',
|
|
189
|
-
'runtime',
|
|
190
|
-
]);
|
|
182
|
+
/**
|
|
183
|
+
* Reserved template namespaces always available at runtime (not user-declared vars).
|
|
184
|
+
* Single-sourced from {@link RUNTIME_BUILTIN_KEYS} so the validator can never drift
|
|
185
|
+
* from the builtins the drivers actually inject at run time.
|
|
186
|
+
*/
|
|
187
|
+
const RUNTIME_TEMPLATE_NAMESPACES = new Set<string>(RUNTIME_BUILTIN_KEYS);
|
|
191
188
|
|
|
192
189
|
/**
|
|
193
190
|
* Check `${...}` template references inside action options resolve to something:
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Typed event map for workflow-engine run observability. All events prefixed `workflow.`. */
|
|
2
|
+
export type WorkflowEngineEvents = {
|
|
3
|
+
/** Emitted when a run begins (inside the span). */
|
|
4
|
+
'workflow.run.started': (data: { workflowName: string; mode: string; runId: string }) => void;
|
|
5
|
+
/** Emitted when a run completes successfully. */
|
|
6
|
+
'workflow.run.done': (data: { finalState: string; transitionsTaken: number }) => void;
|
|
7
|
+
/** Emitted when a run fails. */
|
|
8
|
+
'workflow.run.failed': (data: { finalState: string; reason: string }) => void;
|
|
9
|
+
/** Emitted when entering a state or node. */
|
|
10
|
+
'workflow.node.enter': (data: { node: string; transitionsTaken: number }) => void;
|
|
11
|
+
/** Emitted on a state/node transition. */
|
|
12
|
+
'workflow.node.transition': (data: { from: string; to: string; trigger: string | null }) => void;
|
|
13
|
+
/** Emitted when an action starts executing. */
|
|
14
|
+
'workflow.action.start': (data: { node: string; kind: string }) => void;
|
|
15
|
+
/** Emitted when an action finishes executing (success or failure). */
|
|
16
|
+
'workflow.action.done': (data: { node: string; kind: string; durationMs: number; ok: boolean }) => void;
|
|
17
|
+
/** Emitted when a non-fatal action failure is continued past (onError: 'continue'). */
|
|
18
|
+
'workflow.action.failed_continue': (data: { node: string; transitionsTaken: number; error?: string }) => void;
|
|
19
|
+
};
|