@hardlydifficult/workflow-engine 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -104,3 +104,125 @@ await engine.transition("running", (draft) => {
104
104
  draft.result = computeResult();
105
105
  });
106
106
  ```
107
+
108
+ ---
109
+
110
+ ## Pipeline
111
+
112
+ A higher-level abstraction that manages a linear sequence of steps, wrapping `WorkflowEngine` internally. Supports gates (pause for external input), retries with recovery, cancellation via `AbortSignal`, and automatic lifecycle logging.
113
+
114
+ ### Installation
115
+
116
+ Requires `@hardlydifficult/logger` as a peer dependency:
117
+
118
+ ```bash
119
+ npm install @hardlydifficult/workflow-engine @hardlydifficult/state-tracker @hardlydifficult/logger
120
+ ```
121
+
122
+ ### Usage
123
+
124
+ ```typescript
125
+ import { Pipeline } from "@hardlydifficult/workflow-engine";
126
+ import { createLogger } from "@hardlydifficult/logger";
127
+
128
+ interface Data { prompt: string; plan?: string; approved?: boolean; result?: string; }
129
+
130
+ const logger = createLogger("my-pipeline");
131
+
132
+ const pipeline = new Pipeline<Data>({
133
+ key: "my-pipeline",
134
+ steps: [
135
+ { name: "create_plan", execute: async ({ data }) => {
136
+ const plan = await generatePlan(data.prompt);
137
+ return { plan };
138
+ }},
139
+ { name: "approve", gate: true, execute: async ({ data }) => {
140
+ await postForApproval(data.plan);
141
+ return {};
142
+ }},
143
+ { name: "implement", retries: 2, execute: async ({ data, signal }) => {
144
+ const result = await implement(data.plan!, signal);
145
+ return { result };
146
+ }, recover: async (error) => {
147
+ await fixIssue(error);
148
+ return {};
149
+ }},
150
+ ],
151
+ initialData: { prompt: "Build a feature" },
152
+ logger,
153
+ stateDirectory: "/var/data",
154
+ hooks: {
155
+ onStepComplete: (name) => console.log(`${name} done`),
156
+ onGateReached: (name) => console.log(`Waiting at ${name}`),
157
+ },
158
+ });
159
+
160
+ await pipeline.run();
161
+ // Pipeline pauses at "approve" gate...
162
+
163
+ // Later, on approval:
164
+ await pipeline.resume({ approved: true });
165
+ // Pipeline continues through "implement" and completes
166
+ ```
167
+
168
+ ### Step Types
169
+
170
+ | Type | Definition | Behavior |
171
+ |------|-----------|----------|
172
+ | Regular | `{ name, execute }` | Runs immediately, merges returned data |
173
+ | Gate | `{ name, gate: true, execute? }` | Runs optional execute, then pauses until `resume()` is called |
174
+ | Retryable | `{ name, execute, retries, recover? }` | On failure, calls `recover()` then re-runs `execute`, up to N times |
175
+
176
+ ### `new Pipeline<TData>(options)`
177
+
178
+ | Option | Type | Description |
179
+ |--------|------|-------------|
180
+ | `key` | `string` | Unique persistence key |
181
+ | `steps` | `StepDefinition<TData>[]` | Ordered list of step definitions |
182
+ | `initialData` | `TData` | Initial accumulated data |
183
+ | `logger` | `Logger` | Logger instance (all lifecycle events logged automatically) |
184
+ | `stateDirectory` | `string?` | Persistence directory |
185
+ | `autoSaveMs` | `number?` | Auto-save interval (default 5000) |
186
+ | `hooks` | `PipelineHooks<TData>?` | Lifecycle hooks for external integrations |
187
+ | `signal` | `AbortSignal?` | Abort signal for cancellation |
188
+
189
+ ### Properties
190
+
191
+ | Property | Type | Description |
192
+ |----------|------|-------------|
193
+ | `status` | `string` | e.g. `"running:create_plan"`, `"gate:approve"`, `"completed"`, `"failed"` |
194
+ | `data` | `Readonly<TData>` | Accumulated output data |
195
+ | `steps` | `StepState[]` | Per-step runtime state |
196
+ | `currentStep` | `string?` | Name of current step, or `undefined` if terminal |
197
+ | `isTerminal` | `boolean` | Whether pipeline is in a terminal state |
198
+ | `isWaitingAtGate` | `boolean` | Whether pipeline is paused at a gate |
199
+
200
+ ### Methods
201
+
202
+ | Method | Description |
203
+ |--------|-------------|
204
+ | `run()` | Start or resume from crash. Loads persisted state, re-executes interrupted steps. |
205
+ | `resume(data?)` | Continue past a gate, optionally merging partial data. |
206
+ | `cancel()` | Transition to cancelled, abort signal fires. |
207
+ | `on(listener)` | Subscribe to changes. Returns unsubscribe function. |
208
+ | `toSnapshot()` | Return a read-only snapshot of `{ status, data, steps, isTerminal }`. |
209
+
210
+ ### Hooks
211
+
212
+ All hooks are optional. Hook errors are swallowed to avoid breaking pipeline execution.
213
+
214
+ | Hook | Arguments | When |
215
+ |------|-----------|------|
216
+ | `onStepStart` | `(name, data)` | Before a step executes |
217
+ | `onStepComplete` | `(name, data)` | After a step succeeds |
218
+ | `onStepFailed` | `(name, error, data)` | When a step fails (after all retries) |
219
+ | `onGateReached` | `(name, data)` | When a gate step pauses |
220
+ | `onComplete` | `(data)` | When all steps finish |
221
+ | `onFailed` | `(name, error, data)` | When pipeline enters failed state |
222
+
223
+ ### Crash Recovery
224
+
225
+ Pipeline state is persisted automatically. On restart, `run()` detects the interrupted state:
226
+ - **Mid-step**: re-executes the step (steps should be idempotent)
227
+ - **At gate**: stays at gate, waiting for `resume()`
228
+ - **Terminal**: no-op
@@ -0,0 +1,69 @@
1
+ import type { PipelineOptions, PipelineSnapshot, StepState } from "./pipelineTypes.js";
2
+ /**
3
+ * A linear sequence of steps with automatic state management, persistence,
4
+ * and lifecycle logging.
5
+ *
6
+ * Wraps WorkflowEngine internally. Steps execute sequentially, each receiving
7
+ * accumulated data from prior steps. Gate steps pause until resume() is called.
8
+ * Retryable steps call an optional recovery function between attempts.
9
+ *
10
+ * Step execute functions should be idempotent — on crash recovery the
11
+ * interrupted step is re-executed.
12
+ */
13
+ export declare class Pipeline<TData extends Record<string, unknown>> {
14
+ private readonly engine;
15
+ private readonly stepDefs;
16
+ private readonly hooks;
17
+ private readonly logger;
18
+ private abortController;
19
+ private gateResolver;
20
+ private gatePromise;
21
+ constructor(options: PipelineOptions<TData>);
22
+ /** Current pipeline status string (e.g. "running:step_name", "gate:step_name", "completed") */
23
+ get status(): string;
24
+ /** Accumulated output data (read-only) */
25
+ get data(): Readonly<TData>;
26
+ /** Per-step runtime states */
27
+ get steps(): readonly StepState[];
28
+ /** Name of the currently executing or waiting step, or undefined if terminal */
29
+ get currentStep(): string | undefined;
30
+ /** Whether the pipeline has reached a terminal state */
31
+ get isTerminal(): boolean;
32
+ /** Whether the pipeline is paused at a gate */
33
+ get isWaitingAtGate(): boolean;
34
+ /**
35
+ * Load persisted state and execute.
36
+ *
37
+ * - Fresh pipeline: executes from step 0
38
+ * - Interrupted mid-step: re-executes that step
39
+ * - Waiting at gate: stays at gate (call resume() to continue)
40
+ * - Terminal: no-op
41
+ */
42
+ run(): Promise<void>;
43
+ /**
44
+ * Resume from a gate step. Merges the provided partial data and
45
+ * continues execution from the next step.
46
+ *
47
+ * @throws If the pipeline is not currently at a gate
48
+ */
49
+ resume(data?: Partial<TData>): Promise<void>;
50
+ /**
51
+ * Cancel the pipeline. Transitions to "cancelled" status.
52
+ */
53
+ cancel(): Promise<void>;
54
+ /**
55
+ * Subscribe to engine change events. Returns an unsubscribe function.
56
+ */
57
+ on(listener: (event: {
58
+ status: string;
59
+ data: Readonly<TData>;
60
+ }) => void): () => void;
61
+ /**
62
+ * Return a read-only snapshot of the pipeline state.
63
+ */
64
+ toSnapshot(): PipelineSnapshot<TData>;
65
+ /** Assemble dependencies for step runner functions. */
66
+ private get runnerDeps();
67
+ private executeFrom;
68
+ }
69
+ //# sourceMappingURL=Pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pipeline.d.ts","sourceRoot":"","sources":["../src/Pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,eAAe,EACf,gBAAgB,EAEhB,SAAS,EACV,MAAM,oBAAoB,CAAC;AAS5B;;;;;;;;;;GAUG;AACH,qBAAa,QAAQ,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8C;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAA8B;gBAErC,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC;IAiE3C,+FAA+F;IAC/F,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,0CAA0C;IAC1C,IAAI,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,CAE1B;IAED,8BAA8B;IAC9B,IAAI,KAAK,IAAI,SAAS,SAAS,EAAE,CAEhC;IAED,gFAAgF;IAChF,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAKpC;IAED,wDAAwD;IACxD,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,+CAA+C;IAC/C,IAAI,eAAe,IAAI,OAAO,CAE7B;IAID;;;;;;;OAOG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB1B;;;;;OAKG;IACG,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA+ClD;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB7B;;OAEG;IACH,EAAE,CACA,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;KAAE,KAAK,IAAI,GACnE,MAAM,IAAI;IAMb;;OAEG;IACH,UAAU,IAAI,gBAAgB,CAAC,KAAK,CAAC;IAWrC,uDAAuD;IACvD,OAAO,KAAK,UAAU,GAQrB;YAEa,WAAW;CAgC1B"}
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Pipeline = void 0;
4
+ const buildTransitions_js_1 = require("./buildTransitions.js");
5
+ const stepRunner_js_1 = require("./stepRunner.js");
6
+ const WorkflowEngine_js_1 = require("./WorkflowEngine.js");
7
+ /**
8
+ * A linear sequence of steps with automatic state management, persistence,
9
+ * and lifecycle logging.
10
+ *
11
+ * Wraps WorkflowEngine internally. Steps execute sequentially, each receiving
12
+ * accumulated data from prior steps. Gate steps pause until resume() is called.
13
+ * Retryable steps call an optional recovery function between attempts.
14
+ *
15
+ * Step execute functions should be idempotent — on crash recovery the
16
+ * interrupted step is re-executed.
17
+ */
18
+ class Pipeline {
19
+ engine;
20
+ stepDefs;
21
+ hooks;
22
+ logger;
23
+ abortController;
24
+ gateResolver = null;
25
+ gatePromise = null;
26
+ constructor(options) {
27
+ const { steps, initialData, logger, hooks } = options;
28
+ if (steps.length === 0) {
29
+ throw new Error("Pipeline requires at least one step");
30
+ }
31
+ const names = new Set();
32
+ for (const step of steps) {
33
+ if (names.has(step.name)) {
34
+ throw new Error(`Duplicate step name: "${step.name}"`);
35
+ }
36
+ names.add(step.name);
37
+ }
38
+ this.stepDefs = steps;
39
+ this.hooks = hooks ?? {};
40
+ this.logger = logger;
41
+ // Wire external signal to internal abort controller
42
+ this.abortController = new AbortController();
43
+ if (options.signal) {
44
+ const externalSignal = options.signal;
45
+ if (externalSignal.aborted) {
46
+ this.abortController.abort();
47
+ }
48
+ else {
49
+ externalSignal.addEventListener("abort", () => {
50
+ this.abortController.abort();
51
+ });
52
+ }
53
+ }
54
+ const transitions = (0, buildTransitions_js_1.buildTransitions)(steps);
55
+ const initialStatus = steps[0].gate === true
56
+ ? `gate:${steps[0].name}`
57
+ : `running:${steps[0].name}`;
58
+ logger.debug("Pipeline created", {
59
+ pipeline: options.key,
60
+ steps: steps.map((s) => s.name),
61
+ initialStatus,
62
+ });
63
+ this.engine = new WorkflowEngine_js_1.WorkflowEngine({
64
+ key: options.key,
65
+ initialStatus,
66
+ initialData: {
67
+ currentStepIndex: 0,
68
+ steps: steps.map((s) => ({
69
+ name: s.name,
70
+ status: "pending",
71
+ attempts: 0,
72
+ })),
73
+ output: initialData,
74
+ createdAt: new Date().toISOString(),
75
+ },
76
+ transitions,
77
+ stateDirectory: options.stateDirectory,
78
+ autoSaveMs: options.autoSaveMs,
79
+ });
80
+ }
81
+ // ── Read-Only Accessors ──────────────────────────────────────────
82
+ /** Current pipeline status string (e.g. "running:step_name", "gate:step_name", "completed") */
83
+ get status() {
84
+ return this.engine.status;
85
+ }
86
+ /** Accumulated output data (read-only) */
87
+ get data() {
88
+ return this.engine.data.output;
89
+ }
90
+ /** Per-step runtime states */
91
+ get steps() {
92
+ return this.engine.data.steps;
93
+ }
94
+ /** Name of the currently executing or waiting step, or undefined if terminal */
95
+ get currentStep() {
96
+ if (this.engine.isTerminal) {
97
+ return undefined;
98
+ }
99
+ return this.stepDefs[this.engine.data.currentStepIndex]?.name;
100
+ }
101
+ /** Whether the pipeline has reached a terminal state */
102
+ get isTerminal() {
103
+ return this.engine.isTerminal;
104
+ }
105
+ /** Whether the pipeline is paused at a gate */
106
+ get isWaitingAtGate() {
107
+ return this.engine.status.startsWith("gate:");
108
+ }
109
+ // ── Lifecycle Methods ────────────────────────────────────────────
110
+ /**
111
+ * Load persisted state and execute.
112
+ *
113
+ * - Fresh pipeline: executes from step 0
114
+ * - Interrupted mid-step: re-executes that step
115
+ * - Waiting at gate: stays at gate (call resume() to continue)
116
+ * - Terminal: no-op
117
+ */
118
+ async run() {
119
+ await this.engine.load();
120
+ if (this.engine.isTerminal) {
121
+ return;
122
+ }
123
+ if (this.isWaitingAtGate) {
124
+ // Check if this is a fresh gate (not yet entered)
125
+ const currentIndex = this.engine.data.currentStepIndex;
126
+ const stepState = this.engine.data.steps[currentIndex];
127
+ if (stepState.status === "pending") {
128
+ // Fresh gate — enter it (run execute if present, fire hooks)
129
+ await (0, stepRunner_js_1.enterGate)(this.runnerDeps, currentIndex);
130
+ }
131
+ return;
132
+ }
133
+ await this.executeFrom(this.engine.data.currentStepIndex);
134
+ }
135
+ /**
136
+ * Resume from a gate step. Merges the provided partial data and
137
+ * continues execution from the next step.
138
+ *
139
+ * @throws If the pipeline is not currently at a gate
140
+ */
141
+ async resume(data) {
142
+ if (!this.isWaitingAtGate) {
143
+ throw new Error(`Cannot resume: pipeline is not at a gate (status: "${this.status}")`);
144
+ }
145
+ const index = this.engine.data.currentStepIndex;
146
+ const stepDef = this.stepDefs[index];
147
+ this.logger.info("Pipeline gate resumed", {
148
+ pipeline: this.engine.data.steps[0]?.name,
149
+ step: stepDef.name,
150
+ hasData: data !== undefined,
151
+ });
152
+ // Merge data and mark gate step completed
153
+ await this.engine.update((d) => {
154
+ if (data) {
155
+ Object.assign(d.output, data);
156
+ }
157
+ d.steps[index].status = "completed";
158
+ d.steps[index].completedAt = new Date().toISOString();
159
+ d.currentStepIndex = index + 1;
160
+ });
161
+ // Transition to next step's status
162
+ const nextStatus = (0, buildTransitions_js_1.statusForStep)(this.stepDefs, index + 1);
163
+ await this.engine.transition(nextStatus);
164
+ // Resolve any waiting gate promise (for in-process resumption)
165
+ const resolver = this.gateResolver;
166
+ this.gateResolver = null;
167
+ this.gatePromise = null;
168
+ resolver?.();
169
+ // Continue execution if not completed
170
+ if (nextStatus !== "completed") {
171
+ await this.executeFrom(index + 1);
172
+ }
173
+ else {
174
+ this.logger.info("Pipeline completed", {
175
+ pipeline: this.engine.data.steps[0]?.name,
176
+ });
177
+ (0, stepRunner_js_1.fireHook)(this.hooks, "onComplete", this.data);
178
+ }
179
+ }
180
+ /**
181
+ * Cancel the pipeline. Transitions to "cancelled" status.
182
+ */
183
+ async cancel() {
184
+ if (this.engine.isTerminal) {
185
+ return;
186
+ }
187
+ this.abortController.abort();
188
+ await this.engine.transition("cancelled");
189
+ this.logger.info("Pipeline cancelled", {
190
+ pipeline: this.engine.data.steps[0]?.name,
191
+ step: this.currentStep,
192
+ });
193
+ // Resolve any waiting gate promise to unblock
194
+ const resolver = this.gateResolver;
195
+ this.gateResolver = null;
196
+ this.gatePromise = null;
197
+ resolver?.();
198
+ }
199
+ /**
200
+ * Subscribe to engine change events. Returns an unsubscribe function.
201
+ */
202
+ on(listener) {
203
+ return this.engine.on((event) => {
204
+ listener({ status: event.status, data: event.data.output });
205
+ });
206
+ }
207
+ /**
208
+ * Return a read-only snapshot of the pipeline state.
209
+ */
210
+ toSnapshot() {
211
+ return {
212
+ status: this.status,
213
+ data: structuredClone(this.data),
214
+ steps: structuredClone(this.engine.data.steps),
215
+ isTerminal: this.isTerminal,
216
+ };
217
+ }
218
+ // ── Private ────────────────────────────────────────────────────────
219
+ /** Assemble dependencies for step runner functions. */
220
+ get runnerDeps() {
221
+ return {
222
+ engine: this.engine,
223
+ stepDefs: this.stepDefs,
224
+ hooks: this.hooks,
225
+ logger: this.logger,
226
+ signal: this.abortController.signal,
227
+ };
228
+ }
229
+ async executeFrom(startIndex) {
230
+ for (let i = startIndex; i < this.stepDefs.length; i++) {
231
+ // Check cancellation between steps
232
+ if (this.abortController.signal.aborted) {
233
+ if (!this.engine.isTerminal) {
234
+ await this.engine.transition("cancelled");
235
+ }
236
+ return;
237
+ }
238
+ const stepDef = this.stepDefs[i];
239
+ // Gate step
240
+ if (stepDef.gate === true) {
241
+ await (0, stepRunner_js_1.enterGate)(this.runnerDeps, i);
242
+ return; // Execution pauses here — resume() continues
243
+ }
244
+ // Regular or retryable step
245
+ const succeeded = await (0, stepRunner_js_1.runStep)(this.runnerDeps, i);
246
+ if (!succeeded) {
247
+ return;
248
+ } // Failed — pipeline is in "failed" state
249
+ }
250
+ // All steps complete
251
+ await this.engine.transition("completed");
252
+ this.logger.info("Pipeline completed", {
253
+ pipeline: this.engine.data.steps[0]?.name,
254
+ });
255
+ (0, stepRunner_js_1.fireHook)(this.hooks, "onComplete", this.data);
256
+ }
257
+ }
258
+ exports.Pipeline = Pipeline;
259
+ //# sourceMappingURL=Pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pipeline.js","sourceRoot":"","sources":["../src/Pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Pure functions for computing Pipeline transition maps from step definitions.
3
+ */
4
+ import type { StepDefinition } from "./pipelineTypes.js";
5
+ import type { TransitionMap } from "./types.js";
6
+ /**
7
+ * Compute the status string for a step at the given index.
8
+ * Returns "completed" if the index is past the end.
9
+ */
10
+ export declare function statusForStep<T>(steps: readonly StepDefinition<T>[], index: number): string;
11
+ /** Build a TransitionMap from step definitions. */
12
+ export declare function buildTransitions<T>(steps: readonly StepDefinition<T>[]): TransitionMap<string>;
13
+ //# sourceMappingURL=buildTransitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildTransitions.d.ts","sourceRoot":"","sources":["../src/buildTransitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,EACnC,KAAK,EAAE,MAAM,GACZ,MAAM,CAMR;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,GAClC,aAAa,CAAC,MAAM,CAAC,CAqBvB"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /**
3
+ * Pure functions for computing Pipeline transition maps from step definitions.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.statusForStep = statusForStep;
7
+ exports.buildTransitions = buildTransitions;
8
+ /**
9
+ * Compute the status string for a step at the given index.
10
+ * Returns "completed" if the index is past the end.
11
+ */
12
+ function statusForStep(steps, index) {
13
+ if (index >= steps.length) {
14
+ return "completed";
15
+ }
16
+ const step = steps[index];
17
+ return step.gate === true ? `gate:${step.name}` : `running:${step.name}`;
18
+ }
19
+ /** Build a TransitionMap from step definitions. */
20
+ function buildTransitions(steps) {
21
+ const map = {};
22
+ for (let i = 0; i < steps.length; i++) {
23
+ const step = steps[i];
24
+ const isGate = step.gate === true;
25
+ const nextStatus = statusForStep(steps, i + 1);
26
+ if (isGate) {
27
+ map[`gate:${step.name}`] = [nextStatus, "failed", "cancelled"];
28
+ }
29
+ else {
30
+ map[`running:${step.name}`] = [nextStatus, "failed", "cancelled"];
31
+ }
32
+ }
33
+ // Terminal states
34
+ map.completed = [];
35
+ map.failed = [];
36
+ map.cancelled = [];
37
+ return map;
38
+ }
39
+ //# sourceMappingURL=buildTransitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildTransitions.js","sourceRoot":"","sources":["../src/buildTransitions.ts"],"names":[],"mappings":";AAAA;;GAEG;;AASH,sCASC;AAGD,4CAuBC;AAvCD;;;GAGG;AACH,SAAgB,aAAa,CAC3B,KAAmC,EACnC,KAAa;IAEb,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED,mDAAmD;AACnD,SAAgB,gBAAgB,CAC9B,KAAmC;IAEnC,MAAM,GAAG,GAAsC,EAAE,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QAClC,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAE/C,IAAI,MAAM,EAAE,CAAC;YACX,GAAG,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC;IACnB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAChB,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC;IAEnB,OAAO,GAA4B,CAAC;AACtC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { DataCursor } from "./DataCursor.js";
2
+ export { Pipeline } from "./Pipeline.js";
2
3
  export { WorkflowEngine } from "./WorkflowEngine.js";
3
4
  export type { ChangeListener, WorkflowEngineOptions, WorkflowSnapshot, TransitionEvent, TransitionMap, DataUpdater, } from "./types.js";
5
+ export type { PipelineHooks, PipelineOptions, PipelineSnapshot, RecoveryFn, StepContext, StepDefinition, StepExecutor, StepState, } from "./pipelineTypes.js";
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WorkflowEngine = exports.DataCursor = void 0;
3
+ exports.WorkflowEngine = exports.Pipeline = exports.DataCursor = void 0;
4
4
  var DataCursor_js_1 = require("./DataCursor.js");
5
5
  Object.defineProperty(exports, "DataCursor", { enumerable: true, get: function () { return DataCursor_js_1.DataCursor; } });
6
+ var Pipeline_js_1 = require("./Pipeline.js");
7
+ Object.defineProperty(exports, "Pipeline", { enumerable: true, get: function () { return Pipeline_js_1.Pipeline; } });
6
8
  var WorkflowEngine_js_1 = require("./WorkflowEngine.js");
7
9
  Object.defineProperty(exports, "WorkflowEngine", { enumerable: true, get: function () { return WorkflowEngine_js_1.WorkflowEngine; } });
8
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA6C;AAApC,2GAAA,UAAU,OAAA;AACnB,6CAAyC;AAAhC,uGAAA,QAAQ,OAAA;AACjB,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
@@ -0,0 +1,110 @@
1
+ import type { Logger } from "@hardlydifficult/logger";
2
+ /**
3
+ * Step execution context passed to every step's execute function.
4
+ */
5
+ export interface StepContext<TData> {
6
+ /** Accumulated data from all prior steps (read-only) */
7
+ readonly data: Readonly<TData>;
8
+ /** Abort signal — steps should check this and bail early */
9
+ readonly signal: AbortSignal;
10
+ }
11
+ /**
12
+ * The execute function for a step.
13
+ * Returns a partial data update to merge into accumulated data.
14
+ */
15
+ export type StepExecutor<TData> = (ctx: StepContext<TData>) => Promise<Partial<TData>>;
16
+ /**
17
+ * Recovery function invoked when a retryable step fails.
18
+ * Called between retries. Returns a partial data update
19
+ * that is merged before the step re-executes.
20
+ */
21
+ export type RecoveryFn<TData> = (error: Error, ctx: StepContext<TData>) => Promise<Partial<TData>>;
22
+ /**
23
+ * Step definition — one entry in the pipeline's step list.
24
+ *
25
+ * Three kinds:
26
+ * - Regular step: has `execute`, runs immediately
27
+ * - Gate step: has `gate: true`, pauses until `resume()` is called.
28
+ * May also have `execute` which runs before pausing.
29
+ * - Retryable step: has `execute` + `retries` (and optionally `recover`)
30
+ */
31
+ export interface StepDefinition<TData> {
32
+ /** Unique step name — becomes part of the pipeline status (e.g. "running:create_plan") */
33
+ name: string;
34
+ /** Execute function. For gate steps, runs before pausing. */
35
+ execute?: StepExecutor<TData>;
36
+ /** If true, pipeline pauses after execute until resume() is called */
37
+ gate?: boolean;
38
+ /** Number of retry attempts on failure (default 0 = no retries) */
39
+ retries?: number;
40
+ /** Recovery function called between retries. Only meaningful if retries > 0. */
41
+ recover?: RecoveryFn<TData>;
42
+ }
43
+ /**
44
+ * Runtime state of a single step, persisted inside PipelineData.
45
+ */
46
+ export interface StepState {
47
+ name: string;
48
+ status: "pending" | "running" | "completed" | "failed" | "gate_waiting";
49
+ startedAt?: string;
50
+ completedAt?: string;
51
+ error?: string;
52
+ attempts: number;
53
+ }
54
+ /**
55
+ * Internal persisted data shape for Pipeline.
56
+ * TData is the user's accumulated output data.
57
+ */
58
+ export interface PipelineData<TData> {
59
+ /** Index of the current step (0-based) */
60
+ currentStepIndex: number;
61
+ /** Per-step runtime state */
62
+ steps: StepState[];
63
+ /** Accumulated output data from completed steps */
64
+ output: TData;
65
+ /** ISO timestamp of pipeline creation */
66
+ createdAt: string;
67
+ }
68
+ /**
69
+ * Lifecycle hooks — all optional.
70
+ * Hook errors are swallowed to avoid breaking pipeline execution.
71
+ */
72
+ export interface PipelineHooks<TData> {
73
+ onStepStart?: (name: string, data: Readonly<TData>) => void;
74
+ onStepComplete?: (name: string, data: Readonly<TData>) => void;
75
+ onStepFailed?: (name: string, error: string, data: Readonly<TData>) => void;
76
+ onGateReached?: (name: string, data: Readonly<TData>) => void;
77
+ onComplete?: (data: Readonly<TData>) => void;
78
+ onFailed?: (name: string, error: string, data: Readonly<TData>) => void;
79
+ }
80
+ /**
81
+ * Options for creating a Pipeline.
82
+ */
83
+ export interface PipelineOptions<TData> {
84
+ /** Unique key for persistence (passed to WorkflowEngine) */
85
+ key: string;
86
+ /** Ordered list of step definitions */
87
+ steps: readonly StepDefinition<TData>[];
88
+ /** Initial value for the accumulated output data */
89
+ initialData: TData;
90
+ /** Logger — all step lifecycle events are logged automatically */
91
+ logger: Logger;
92
+ /** Directory for state persistence */
93
+ stateDirectory?: string;
94
+ /** Auto-save interval in ms (default 5000) */
95
+ autoSaveMs?: number;
96
+ /** Lifecycle hooks for external integrations (Discord, dashboard, etc.) */
97
+ hooks?: PipelineHooks<TData>;
98
+ /** Abort signal for cancellation */
99
+ signal?: AbortSignal;
100
+ }
101
+ /**
102
+ * Read-only snapshot of the pipeline state.
103
+ */
104
+ export interface PipelineSnapshot<TData> {
105
+ status: string;
106
+ data: Readonly<TData>;
107
+ steps: readonly StepState[];
108
+ isTerminal: boolean;
109
+ }
110
+ //# sourceMappingURL=pipelineTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipelineTypes.d.ts","sourceRoot":"","sources":["../src/pipelineTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=pipelineTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipelineTypes.js","sourceRoot":"","sources":["../src/pipelineTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Step execution functions for Pipeline.
3
+ *
4
+ * Extracted from Pipeline to keep each module focused:
5
+ * - runStep: retry loop, recovery, error handling
6
+ * - enterGate: gate transitions, optional pre-execute
7
+ * - fireHook: lifecycle hook dispatch with error swallowing
8
+ */
9
+ import type { Logger } from "@hardlydifficult/logger";
10
+ import type { PipelineData, PipelineHooks, StepDefinition } from "./pipelineTypes.js";
11
+ import type { WorkflowEngine } from "./WorkflowEngine.js";
12
+ /**
13
+ * Dependencies passed from Pipeline to step execution functions.
14
+ */
15
+ export interface StepRunnerDeps<TData extends Record<string, unknown>> {
16
+ engine: WorkflowEngine<string, PipelineData<TData>>;
17
+ stepDefs: readonly StepDefinition<TData>[];
18
+ hooks: PipelineHooks<TData>;
19
+ logger: Logger;
20
+ signal: AbortSignal;
21
+ }
22
+ /** Fire a lifecycle hook, swallowing any errors. */
23
+ export declare function fireHook<TData extends Record<string, unknown>, K extends keyof PipelineHooks<TData>>(hooks: PipelineHooks<TData>, name: K, ...args: Parameters<NonNullable<PipelineHooks<TData>[K]>>): void;
24
+ /**
25
+ * Enter a gate step: transition to gate status, run optional execute, fire hooks.
26
+ * On execute failure, transitions pipeline to "failed".
27
+ */
28
+ export declare function enterGate<TData extends Record<string, unknown>>(deps: StepRunnerDeps<TData>, index: number): Promise<void>;
29
+ /**
30
+ * Execute a single step with retry logic.
31
+ * Returns true on success, false on failure (pipeline transitions to "failed").
32
+ */
33
+ export declare function runStep<TData extends Record<string, unknown>>(deps: StepRunnerDeps<TData>, index: number): Promise<boolean>;
34
+ //# sourceMappingURL=stepRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepRunner.d.ts","sourceRoot":"","sources":["../src/stepRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EAEb,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,QAAQ,EAAE,SAAS,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;IAC3C,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;CACrB;AAmBD,oDAAoD;AACpD,wBAAgB,QAAQ,CACtB,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,CAAC,SAAS,MAAM,aAAa,CAAC,KAAK,CAAC,EAEpC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAC3B,IAAI,EAAE,CAAC,EACP,GAAG,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACxD,IAAI,CAWN;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAC3B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,EAC3B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CA+IlB"}
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ /**
3
+ * Step execution functions for Pipeline.
4
+ *
5
+ * Extracted from Pipeline to keep each module focused:
6
+ * - runStep: retry loop, recovery, error handling
7
+ * - enterGate: gate transitions, optional pre-execute
8
+ * - fireHook: lifecycle hook dispatch with error swallowing
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.fireHook = fireHook;
12
+ exports.enterGate = enterGate;
13
+ exports.runStep = runStep;
14
+ /** Build a StepContext for a step's execute function. */
15
+ function createStepContext(deps) {
16
+ return {
17
+ data: deps.engine.data.output,
18
+ signal: deps.signal,
19
+ };
20
+ }
21
+ /** Pipeline key for log context (uses first step name as identifier). */
22
+ function pipelineKey(deps) {
23
+ return deps.engine.data.steps[0]?.name;
24
+ }
25
+ /** Fire a lifecycle hook, swallowing any errors. */
26
+ function fireHook(hooks, name, ...args) {
27
+ const fn = hooks[name];
28
+ if (!fn) {
29
+ return;
30
+ }
31
+ try {
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic hook dispatch
33
+ fn(...args);
34
+ }
35
+ catch {
36
+ // Hooks must not break pipeline execution
37
+ }
38
+ }
39
+ /**
40
+ * Enter a gate step: transition to gate status, run optional execute, fire hooks.
41
+ * On execute failure, transitions pipeline to "failed".
42
+ */
43
+ async function enterGate(deps, index) {
44
+ const stepDef = deps.stepDefs[index];
45
+ // Transition to gate status
46
+ const gateStatus = `gate:${stepDef.name}`;
47
+ if (deps.engine.status !== gateStatus) {
48
+ await deps.engine.transition(gateStatus, (d) => {
49
+ d.currentStepIndex = index;
50
+ d.steps[index].status = "gate_waiting";
51
+ d.steps[index].startedAt = new Date().toISOString();
52
+ });
53
+ }
54
+ // Run optional execute before pausing
55
+ if (stepDef.execute) {
56
+ try {
57
+ const ctx = createStepContext(deps);
58
+ const result = await stepDef.execute(ctx);
59
+ await deps.engine.update((d) => {
60
+ Object.assign(d.output, result);
61
+ });
62
+ }
63
+ catch (err) {
64
+ const error = err instanceof Error ? err : new Error(String(err));
65
+ deps.logger.error("Pipeline gate execute failed", {
66
+ pipeline: pipelineKey(deps),
67
+ step: stepDef.name,
68
+ error: error.message,
69
+ });
70
+ await deps.engine.update((d) => {
71
+ d.steps[index].status = "failed";
72
+ d.steps[index].completedAt = new Date().toISOString();
73
+ d.steps[index].error = error.message;
74
+ });
75
+ await deps.engine.transition("failed");
76
+ fireHook(deps.hooks, "onStepFailed", stepDef.name, error.message, deps.engine.data.output);
77
+ fireHook(deps.hooks, "onFailed", stepDef.name, error.message, deps.engine.data.output);
78
+ return;
79
+ }
80
+ }
81
+ deps.logger.info("Pipeline gate reached", {
82
+ pipeline: pipelineKey(deps),
83
+ step: stepDef.name,
84
+ });
85
+ fireHook(deps.hooks, "onGateReached", stepDef.name, deps.engine.data.output);
86
+ }
87
+ /**
88
+ * Execute a single step with retry logic.
89
+ * Returns true on success, false on failure (pipeline transitions to "failed").
90
+ */
91
+ async function runStep(deps, index) {
92
+ const stepDef = deps.stepDefs[index];
93
+ const maxAttempts = (stepDef.retries ?? 0) + 1;
94
+ if (!stepDef.execute) {
95
+ throw new Error(`Step "${stepDef.name}" has no execute function and is not a gate`);
96
+ }
97
+ // Transition to running status
98
+ const runningStatus = `running:${stepDef.name}`;
99
+ if (deps.engine.status !== runningStatus) {
100
+ await deps.engine.transition(runningStatus, (d) => {
101
+ d.currentStepIndex = index;
102
+ d.steps[index].status = "running";
103
+ d.steps[index].startedAt = new Date().toISOString();
104
+ });
105
+ }
106
+ else {
107
+ // Crash recovery — already in running status, just update step state
108
+ await deps.engine.update((d) => {
109
+ d.steps[index].status = "running";
110
+ d.steps[index].startedAt ??= new Date().toISOString();
111
+ });
112
+ }
113
+ deps.logger.info("Pipeline step started", {
114
+ pipeline: pipelineKey(deps),
115
+ step: stepDef.name,
116
+ });
117
+ fireHook(deps.hooks, "onStepStart", stepDef.name, deps.engine.data.output);
118
+ const startMs = Date.now();
119
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
120
+ try {
121
+ const ctx = createStepContext(deps);
122
+ const result = await stepDef.execute(ctx);
123
+ const durationMs = Date.now() - startMs;
124
+ // Success — merge result and mark completed
125
+ await deps.engine.update((d) => {
126
+ Object.assign(d.output, result);
127
+ d.steps[index].status = "completed";
128
+ d.steps[index].completedAt = new Date().toISOString();
129
+ d.steps[index].attempts = attempt;
130
+ d.steps[index].error = undefined;
131
+ d.currentStepIndex = index + 1;
132
+ });
133
+ deps.logger.info("Pipeline step completed", {
134
+ pipeline: pipelineKey(deps),
135
+ step: stepDef.name,
136
+ attempt,
137
+ durationMs,
138
+ });
139
+ fireHook(deps.hooks, "onStepComplete", stepDef.name, deps.engine.data.output);
140
+ return true;
141
+ }
142
+ catch (err) {
143
+ const error = err instanceof Error ? err : new Error(String(err));
144
+ await deps.engine.update((d) => {
145
+ d.steps[index].attempts = attempt;
146
+ d.steps[index].error = error.message;
147
+ });
148
+ if (attempt < maxAttempts) {
149
+ deps.logger.warn("Pipeline step retry", {
150
+ pipeline: pipelineKey(deps),
151
+ step: stepDef.name,
152
+ attempt,
153
+ maxAttempts,
154
+ error: error.message,
155
+ });
156
+ // Recovery before retry
157
+ if (stepDef.recover) {
158
+ try {
159
+ const ctx = createStepContext(deps);
160
+ const recoveryResult = await stepDef.recover(error, ctx);
161
+ await deps.engine.update((d) => {
162
+ Object.assign(d.output, recoveryResult);
163
+ });
164
+ }
165
+ catch (recoverErr) {
166
+ const recoverError = recoverErr instanceof Error
167
+ ? recoverErr
168
+ : new Error(String(recoverErr));
169
+ deps.logger.error("Pipeline recovery failed", {
170
+ pipeline: pipelineKey(deps),
171
+ step: stepDef.name,
172
+ attempt,
173
+ error: recoverError.message,
174
+ });
175
+ // Recovery failed — continue to next attempt anyway
176
+ }
177
+ }
178
+ continue;
179
+ }
180
+ const durationMs = Date.now() - startMs;
181
+ // All attempts exhausted — fail
182
+ await deps.engine.update((d) => {
183
+ d.steps[index].status = "failed";
184
+ d.steps[index].completedAt = new Date().toISOString();
185
+ });
186
+ deps.logger.error("Pipeline step failed", {
187
+ pipeline: pipelineKey(deps),
188
+ step: stepDef.name,
189
+ attempt,
190
+ durationMs,
191
+ error: error.message,
192
+ });
193
+ fireHook(deps.hooks, "onStepFailed", stepDef.name, error.message, deps.engine.data.output);
194
+ await deps.engine.transition("failed");
195
+ fireHook(deps.hooks, "onFailed", stepDef.name, error.message, deps.engine.data.output);
196
+ return false;
197
+ }
198
+ }
199
+ return false; // unreachable, but satisfies TS
200
+ }
201
+ //# sourceMappingURL=stepRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stepRunner.js","sourceRoot":"","sources":["../src/stepRunner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/workflow-engine",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -18,11 +18,13 @@
18
18
  "@hardlydifficult/state-tracker": "file:../state-tracker"
19
19
  },
20
20
  "devDependencies": {
21
- "@types/node": "20.19.31",
22
- "typescript": "5.8.3",
23
- "vitest": "1.6.1"
21
+ "@hardlydifficult/logger": "file:../logger",
22
+ "@types/node": "25.2.3",
23
+ "typescript": "5.9.3",
24
+ "vitest": "4.0.18"
24
25
  },
25
26
  "peerDependencies": {
27
+ "@hardlydifficult/logger": ">=1.0.0",
26
28
  "@hardlydifficult/state-tracker": ">=2.0.0"
27
29
  },
28
30
  "engines": {