@bratsos/workflow-engine 0.5.0 → 0.6.0
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 +67 -13
- package/dist/{chunk-RZY5YRGL.js → chunk-2MWO6UVR.js} +2 -2
- package/dist/chunk-2MWO6UVR.js.map +1 -0
- package/dist/{chunk-PHLNTR5Z.js → chunk-DIADEUGZ.js} +21 -3
- package/dist/chunk-DIADEUGZ.js.map +1 -0
- package/dist/{chunk-ZYMT2PAO.js → chunk-HKGZ2WHJ.js} +2 -30
- package/dist/chunk-HKGZ2WHJ.js.map +1 -0
- package/dist/{chunk-3NEGRI4M.js → chunk-HOGDFLCG.js} +342 -114
- package/dist/chunk-HOGDFLCG.js.map +1 -0
- package/dist/{client-oLD5ilXp.d.ts → client-llB6XpHS.d.ts} +10 -81
- package/dist/client.d.ts +4 -3
- package/dist/client.js +1 -1
- package/dist/events-D_P24UaY.d.ts +105 -0
- package/dist/{index-CVkkGnxx.d.ts → index-sGgV8JNu.d.ts} +5 -1
- package/dist/index.d.ts +184 -32
- package/dist/index.js +41 -9
- package/dist/index.js.map +1 -1
- package/dist/{interface-TsryH4d7.d.ts → interface-DCdddCe0.d.ts} +7 -2
- package/dist/kernel/index.d.ts +6 -5
- package/dist/kernel/index.js +2 -1
- package/dist/kernel/testing/index.d.ts +3 -2
- package/dist/persistence/index.d.ts +2 -2
- package/dist/persistence/index.js +2 -2
- package/dist/persistence/prisma/index.d.ts +2 -2
- package/dist/persistence/prisma/index.js +2 -2
- package/dist/{plugins-DW266bhT.d.ts → plugins-Oyo_iu0l.d.ts} +16 -10
- package/dist/{ports-855bktyD.d.ts → ports-ChGnJcn2.d.ts} +5 -106
- package/dist/{stage-BPw7m9Wx.d.ts → stage-_7BKqqUG.d.ts} +2 -2
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.js +23 -5
- package/dist/testing/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/workflow-engine/SKILL.md +31 -12
- package/skills/workflow-engine/references/02-workflow-builder.md +2 -0
- package/skills/workflow-engine/references/03-runtime-setup.md +1 -1
- package/skills/workflow-engine/references/08-common-patterns.md +17 -3
- package/skills/workflow-engine/references/09-troubleshooting.md +12 -3
- package/dist/chunk-3NEGRI4M.js.map +0 -1
- package/dist/chunk-PHLNTR5Z.js.map +0 -1
- package/dist/chunk-RZY5YRGL.js.map +0 -1
- package/dist/chunk-ZYMT2PAO.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bratsos/workflow-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Type-safe, distributed workflow engine for AI-orchestrated processes with suspend/resume, parallel execution, and cost tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -4,7 +4,7 @@ description: Guide for @bratsos/workflow-engine - a type-safe workflow engine wi
|
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: bratsos
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.3.0"
|
|
8
8
|
repository: https://github.com/bratsos/workflow-engine
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -109,6 +109,10 @@ await kernel.dispatch({
|
|
|
109
109
|
| `createServerlessHost` | Function | `@bratsos/workflow-engine-host-serverless` | Create serverless host |
|
|
110
110
|
| `createAIHelper` | Function | `@bratsos/workflow-engine` | AI operations (text, object, embed, batch) |
|
|
111
111
|
| `registerEmbeddingProvider` | Function | `@bratsos/workflow-engine` | Register custom embedding providers (Voyage, Cohere, etc.) |
|
|
112
|
+
| `createStageIds` | Function | `@bratsos/workflow-engine` | Create stage ID constants from a workflow |
|
|
113
|
+
| `defineStageIds` | Function | `@bratsos/workflow-engine` | Define stage ID constants from a tuple |
|
|
114
|
+
| `isValidStageId` | Function | `@bratsos/workflow-engine` | Runtime stage ID validation |
|
|
115
|
+
| `assertValidStageId` | Function | `@bratsos/workflow-engine` | Assert stage ID validity (throws) |
|
|
112
116
|
| `definePlugin` | Function | `@bratsos/workflow-engine/kernel` | Define kernel plugins |
|
|
113
117
|
| `createPluginRunner` | Function | `@bratsos/workflow-engine/kernel` | Create plugin event processor |
|
|
114
118
|
|
|
@@ -121,10 +125,10 @@ All operations go through `kernel.dispatch(command)`:
|
|
|
121
125
|
| `run.create` | Create a new workflow run |
|
|
122
126
|
| `run.claimPending` | Claim pending runs, enqueue first-stage jobs |
|
|
123
127
|
| `run.transition` | Advance to next stage group or complete |
|
|
124
|
-
| `run.cancel` | Cancel a running workflow |
|
|
125
|
-
| `run.rerunFrom` | Rerun from a specific stage |
|
|
128
|
+
| `run.cancel` | Cancel a running workflow (authoritative: cascades to stages + jobs) |
|
|
129
|
+
| `run.rerunFrom` | Rerun from a specific stage (cleans up blob artifacts by prefix) |
|
|
126
130
|
| `job.execute` | Execute a single stage (uses multi-phase transactions; see 08-common-patterns.md) |
|
|
127
|
-
| `stage.pollSuspended` | Poll suspended stages for readiness (
|
|
131
|
+
| `stage.pollSuspended` | Poll suspended stages for readiness (skips cancelled runs; per-stage transactions) |
|
|
128
132
|
| `lease.reapStale` | Release stale job leases |
|
|
129
133
|
| `run.reapStuck` | Detect and fail RUNNING runs with no recent activity |
|
|
130
134
|
| `outbox.flush` | Publish pending outbox events |
|
|
@@ -179,7 +183,12 @@ const batchStage = defineAsyncBatchStage({
|
|
|
179
183
|
const batchId = await submitBatchJob(ctx.input);
|
|
180
184
|
return {
|
|
181
185
|
suspended: true,
|
|
182
|
-
state: {
|
|
186
|
+
state: {
|
|
187
|
+
batchId,
|
|
188
|
+
submittedAt: new Date().toISOString(),
|
|
189
|
+
pollInterval: 60000,
|
|
190
|
+
maxWaitTime: 3600000,
|
|
191
|
+
},
|
|
183
192
|
pollConfig: { pollInterval: 60000, maxWaitTime: 3600000, nextPollAt: new Date(Date.now() + 60000) },
|
|
184
193
|
};
|
|
185
194
|
},
|
|
@@ -195,23 +204,31 @@ const batchStage = defineAsyncBatchStage({
|
|
|
195
204
|
|
|
196
205
|
## WorkflowBuilder
|
|
197
206
|
|
|
207
|
+
Workflows are linear pipelines of **execution groups**. `.pipe()` creates single-stage groups; `.parallel()` creates multi-stage groups. Parallel group outputs are keyed by stage ID in the workflow context.
|
|
208
|
+
|
|
198
209
|
```typescript
|
|
199
210
|
const workflow = new WorkflowBuilder(
|
|
200
211
|
"workflow-id", "Workflow Name", "Description",
|
|
201
212
|
InputSchema, OutputSchema
|
|
202
213
|
)
|
|
203
|
-
.pipe(stage1)
|
|
204
|
-
.pipe(stage2)
|
|
205
|
-
.parallel([stage3a, stage3b])
|
|
206
|
-
.pipe(stage4)
|
|
214
|
+
.pipe(stage1) // Group 0
|
|
215
|
+
.pipe(stage2) // Group 1
|
|
216
|
+
.parallel([stage3a, stage3b]) // Group 2 (concurrent, output: { "stage3a-id": ..., "stage3b-id": ... })
|
|
217
|
+
.pipe(stage4) // Group 3
|
|
207
218
|
.build();
|
|
208
219
|
|
|
220
|
+
// In stage4, access parallel outputs by stage ID:
|
|
221
|
+
ctx.require("stage3a-id") // output of stage3a
|
|
222
|
+
ctx.require("stage3b-id") // output of stage3b
|
|
223
|
+
|
|
209
224
|
workflow.getStageIds();
|
|
210
225
|
workflow.getExecutionPlan();
|
|
211
226
|
workflow.getDefaultConfig();
|
|
212
227
|
workflow.validateConfig(config);
|
|
213
228
|
```
|
|
214
229
|
|
|
230
|
+
When a workflow completes, the final execution group's output is persisted in `WorkflowRun.output` and included in the `workflow:completed` event.
|
|
231
|
+
|
|
215
232
|
## Kernel Setup
|
|
216
233
|
|
|
217
234
|
```typescript
|
|
@@ -436,7 +453,9 @@ await kernel.dispatch({ type: "run.transition", workflowRunId: job.workflowRunId
|
|
|
436
453
|
2. **Command Kernel**: All operations are typed commands dispatched through `kernel.dispatch()`
|
|
437
454
|
3. **Environment-Agnostic**: Kernel has no timers, no signals, no global state
|
|
438
455
|
4. **Context Access**: Use `ctx.require()` and `ctx.optional()` for type-safe stage output access
|
|
439
|
-
5. **Transactional Outbox**: Events written to outbox, published via `outbox.flush` command. `job.execute`
|
|
456
|
+
5. **Transactional Outbox**: Events written to outbox, published via `outbox.flush` command. `job.execute` and `stage.pollSuspended` use multi-phase transactions to avoid holding connections during external I/O
|
|
440
457
|
6. **Idempotency**: `run.create` and `job.execute` replay cached results by key; concurrent same-key dispatch throws `IdempotencyInProgressError`
|
|
441
|
-
7. **
|
|
442
|
-
8. **
|
|
458
|
+
7. **Authoritative Cancellation**: `run.cancel` cascades to stages + jobs. Ghost jobs (running against non-RUNNING runs) are detected via `ghost: true` flag and not retried
|
|
459
|
+
8. **Self-Healing**: Stage creation is idempotent (upsert), orchestration steps are isolated, stuck runs are automatically reaped
|
|
460
|
+
9. **Cost Tracking**: All AI calls automatically track tokens and costs
|
|
461
|
+
10. **BlobStore-Only Artifacts**: All artifact storage goes through the BlobStore port. `run.rerunFrom` cleans up artifacts by key prefix
|
|
@@ -55,6 +55,8 @@ Parallel stages:
|
|
|
55
55
|
- Run in the same execution group
|
|
56
56
|
- Receive the same input (output from previous group)
|
|
57
57
|
- Must not depend on each other
|
|
58
|
+
- Their outputs are merged into the workflow context keyed by stage ID (e.g., `{ "classify": classifyOutput, "summarize": summarizeOutput }`)
|
|
59
|
+
- Subsequent stages access each parallel stage's output via `ctx.require("classify")`, `ctx.require("summarize")`, etc.
|
|
58
60
|
|
|
59
61
|
### build()
|
|
60
62
|
|
|
@@ -58,7 +58,7 @@ const kernel = createKernel({
|
|
|
58
58
|
|------|-----------|---------|
|
|
59
59
|
| `persistence` | `Persistence` | CRUD for runs, stages, logs, outbox events, idempotency keys |
|
|
60
60
|
| `blobStore` | `BlobStore` | `put(key, data)`, `get(key)`, `has(key)`, `delete(key)`, `list(prefix)` |
|
|
61
|
-
| `jobTransport` | `JobTransport` | `enqueue`, `enqueueParallel`, `dequeue`, `complete`, `suspend`, `fail` |
|
|
61
|
+
| `jobTransport` | `JobTransport` | `enqueue`, `enqueueParallel`, `dequeue`, `complete`, `suspend`, `fail`, `cancelByRun` |
|
|
62
62
|
| `eventSink` | `EventSink` | `emit(event)` - async event publishing |
|
|
63
63
|
| `scheduler` | `Scheduler` | `schedule(type, payload, runAt)`, `cancel(type, correlationId)` |
|
|
64
64
|
| `clock` | `Clock` | `now()` - returns `Date` |
|
|
@@ -41,9 +41,13 @@ await kernel.dispatch({ type: "outbox.flush", maxEvents: 100 });
|
|
|
41
41
|
|
|
42
42
|
This ensures events are only published after the underlying database transaction succeeds, preventing lost or phantom events.
|
|
43
43
|
|
|
44
|
-
### Multi-phase transactions
|
|
44
|
+
### Multi-phase transactions
|
|
45
45
|
|
|
46
|
-
Most commands execute inside a single database transaction (handler logic + outbox event writes).
|
|
46
|
+
Most commands execute inside a single database transaction (handler logic + outbox event writes). Two commands manage their own transactions to avoid holding connections during external I/O:
|
|
47
|
+
|
|
48
|
+
#### `job.execute`
|
|
49
|
+
|
|
50
|
+
Uses a 3-phase pattern so that long-running stage execution doesn't hold a DB connection:
|
|
47
51
|
|
|
48
52
|
1. **Phase 1 (Start):** Upsert stage to `RUNNING` + write `stage:started` outbox event in one transaction. Commits immediately so `RUNNING` status is visible to observers.
|
|
49
53
|
2. **Phase 2 (Execute):** `stageDef.execute()` runs outside any database transaction. Progress events are collected in memory.
|
|
@@ -51,6 +55,15 @@ Most commands execute inside a single database transaction (handler logic + outb
|
|
|
51
55
|
|
|
52
56
|
If the process crashes between Phase 1 and Phase 3, the stage stays in `RUNNING` and `lease.reapStale` will eventually retry the job.
|
|
53
57
|
|
|
58
|
+
#### `stage.pollSuspended`
|
|
59
|
+
|
|
60
|
+
Uses per-stage transactions so that `checkCompletion()` — which makes external HTTP calls to batch providers (Google Batch, OpenAI Batch, etc.) — runs outside any database transaction:
|
|
61
|
+
|
|
62
|
+
1. **Phase 1 (Check):** `stageDef.checkCompletion()` runs outside any transaction. External API calls happen here.
|
|
63
|
+
2. **Phase 2 (Persist):** Update stage status + append outbox events in one short transaction per stage.
|
|
64
|
+
|
|
65
|
+
Without this, slow batch provider responses would exceed Prisma's interactive transaction timeout (default 5s), causing P2028 errors and leaving stages permanently stuck in `SUSPENDED`.
|
|
66
|
+
|
|
54
67
|
The outbox includes retry logic with a dead-letter queue (DLQ). Events that fail to publish are retried up to 3 times before being moved to the DLQ. Use `plugin.replayDLQ` to reprocess them:
|
|
55
68
|
|
|
56
69
|
```typescript
|
|
@@ -83,6 +96,7 @@ const { deletedStages } = await kernel.dispatch({
|
|
|
83
96
|
|
|
84
97
|
// Stages from "summarize" onward are deleted and re-queued
|
|
85
98
|
// Earlier stages (e.g., "extract") keep their outputs
|
|
99
|
+
// Blob artifacts for deleted stages are cleaned up by key prefix
|
|
86
100
|
```
|
|
87
101
|
|
|
88
102
|
## Plugin System
|
|
@@ -200,7 +214,7 @@ If claiming a specific run fails (e.g., workflow not found, database error), tha
|
|
|
200
214
|
|
|
201
215
|
### Ghost Job Guard
|
|
202
216
|
|
|
203
|
-
`job.execute` verifies the run is in `RUNNING` status before executing. Jobs for `
|
|
217
|
+
`job.execute` verifies the run is in `RUNNING` status both before and after executing the stage. Jobs for non-`RUNNING` runs are discarded with `outcome: "failed"` and a `ghost: true` flag in the result. Hosts check this flag to disable retries (`canRetry = false`). This prevents ghost jobs from rolled-back transactions or concurrent cancellations from resurrecting invalid state.
|
|
204
218
|
|
|
205
219
|
### Orchestration Tick Isolation
|
|
206
220
|
|
|
@@ -48,15 +48,24 @@ await kernel.dispatch({ type: "run.transition", workflowRunId: runId });
|
|
|
48
48
|
|
|
49
49
|
**If you still see P2002 errors:** They should only come from other parts of the system (e.g., idempotency key conflicts, which are expected and handled). Check the error's `meta.target` field to see which constraint was violated.
|
|
50
50
|
|
|
51
|
+
## P2028 Transaction Timeout on Suspended Stage Polling
|
|
52
|
+
|
|
53
|
+
**Symptom:** Logs show `P2028: Transaction API error: A query cannot be executed on an expired transaction` during `stage.pollSuspended`. Suspended stages never transition to `COMPLETED` even when the batch provider reports completion.
|
|
54
|
+
|
|
55
|
+
**What it was:** `checkCompletion()` was running inside the kernel's global Prisma interactive transaction. Batch provider API calls (Google Batch, OpenAI Batch, etc.) that took longer than the default 5s timeout would expire the transaction, and the subsequent `updateStage()` call would fail.
|
|
56
|
+
|
|
57
|
+
**How it's fixed:** `stage.pollSuspended` now manages its own per-stage transactions (same pattern as `job.execute`). `checkCompletion()` runs outside any transaction, and only the DB state update + outbox writes are wrapped in a short transaction afterward.
|
|
58
|
+
|
|
51
59
|
## Ghost Jobs
|
|
52
60
|
|
|
53
61
|
**Symptom:** Jobs execute against runs that aren't `RUNNING`, or stages get upserted to `RUNNING` for runs that should be `FAILED`/`CANCELLED`.
|
|
54
62
|
|
|
55
63
|
**What it was:** If the kernel transaction rolled back after `jobTransport.enqueueParallel` committed (separate transaction), ghost jobs would exist in the queue pointing to runs/stages that were rolled back.
|
|
56
64
|
|
|
57
|
-
**How it's fixed (
|
|
58
|
-
1. **
|
|
59
|
-
2. **
|
|
65
|
+
**How it's fixed (three layers):**
|
|
66
|
+
1. **Authoritative cancellation:** `run.cancel` cancels all queued/suspended jobs via `jobTransport.cancelByRun()`, preventing most ghost jobs before dequeue.
|
|
67
|
+
2. **Kernel guard:** `job.execute` checks `workflowRun.status === "RUNNING"` both before AND after stage execution. Ghost jobs are discarded with `outcome: "failed"` and a typed `ghost: true` flag in the result.
|
|
68
|
+
3. **Host no-retry:** Both Node and Serverless hosts detect ghost jobs via the `ghost: true` flag (not string matching) and set `canRetry = false`, preventing infinite retry loops.
|
|
60
69
|
|
|
61
70
|
## One Bad Run Blocks Everything
|
|
62
71
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/kernel/errors.ts","../src/kernel/helpers/load-workflow-context.ts","../src/kernel/helpers/save-stage-output.ts","../src/kernel/helpers/create-storage-shim.ts","../src/kernel/handlers/job-execute.ts","../src/kernel/handlers/lease-reap-stale.ts","../src/kernel/handlers/outbox-flush.ts","../src/kernel/handlers/plugin-replay-dlq.ts","../src/kernel/handlers/run-cancel.ts","../src/kernel/handlers/run-claim-pending.ts","../src/kernel/handlers/run-create.ts","../src/kernel/handlers/run-reap-stuck.ts","../src/kernel/handlers/run-rerun-from.ts","../src/kernel/handlers/run-transition.ts","../src/kernel/handlers/stage-poll-suspended.ts","../src/kernel/kernel.ts","../src/kernel/plugins.ts"],"names":["TERMINAL_STATUSES"],"mappings":"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","file":"chunk-3NEGRI4M.js","sourcesContent":["/**\n * Core type definitions for Workflow System v2\n *\n * See WORKFLOW_SYSTEM_PROPOSAL.md for full architectural details\n */\n\nimport { z } from \"zod\";\n\n// ============================================================================\n// Progress & Metrics\n// ============================================================================\n\nexport interface ProgressUpdate {\n stageId: string;\n stageName: string;\n progress: number; // 0-100\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport interface StageMetrics {\n startTime: number;\n endTime: number;\n duration: number;\n itemsProcessed?: number;\n itemsProduced?: number;\n aiCalls?: number;\n totalTokens?: number;\n totalCost?: number;\n}\n\n// ============================================================================\n// Embedding Support\n// ============================================================================\n\nexport interface EmbeddingResult {\n id: string;\n content: string;\n embedding: number[];\n similarity?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport interface EmbeddingInfo {\n model: string;\n dimensions: number;\n results: EmbeddingResult[];\n totalProcessed?: number;\n averageSimilarity?: number;\n}\n\n// ============================================================================\n// Stage Results\n// ============================================================================\n\nexport interface StageResult<TOutput> {\n output: TOutput;\n metrics: StageMetrics;\n artifacts?: Record<string, unknown>;\n embeddings?: EmbeddingInfo;\n}\n\n// ============================================================================\n// Suspended State (for async-batch operations)\n// ============================================================================\n\nexport const SuspendedStateSchema = z.object({\n batchId: z.string(),\n statusUrl: z.string().optional(),\n apiKey: z.string().optional(),\n submittedAt: z.string(), // ISO date string\n pollInterval: z.number(), // milliseconds\n maxWaitTime: z.number(), // milliseconds\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport interface SuspendedResult {\n suspended: true;\n state: z.infer<typeof SuspendedStateSchema>;\n pollConfig: {\n pollInterval: number;\n maxWaitTime: number;\n nextPollAt: Date;\n };\n metrics: StageMetrics;\n}\n\n// ============================================================================\n// Completion Check Result (for orchestrator polling)\n// ============================================================================\n\nexport interface CompletionCheckResult<TOutput> {\n ready: boolean;\n output?: TOutput;\n error?: string;\n nextCheckIn?: number; // Optional: override next poll interval\n metrics?: StageMetrics;\n embeddings?: EmbeddingInfo;\n}\n\n// ============================================================================\n// Log Levels\n// ============================================================================\n\nexport type LogLevel = \"DEBUG\" | \"INFO\" | \"WARN\" | \"ERROR\";\n\n// ============================================================================\n// Stage Mode\n// ============================================================================\n\nexport type StageMode =\n | \"sync\" // Execute and return immediately\n | \"async-batch\"; // Start batch job, return suspended state (separate poller handles completion)\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\nexport function isSuspendedResult<T>(\n result: StageResult<T> | SuspendedResult,\n): result is SuspendedResult {\n return \"suspended\" in result && result.suspended === true;\n}\n\nexport function isStageResult<T>(\n result: StageResult<T> | SuspendedResult,\n): result is StageResult<T> {\n return !isSuspendedResult(result);\n}\n","export class IdempotencyInProgressError extends Error {\n constructor(\n public readonly key: string,\n public readonly commandType: string,\n ) {\n super(\n `Command \"${commandType}\" with idempotency key \"${key}\" is already in progress`,\n );\n this.name = \"IdempotencyInProgressError\";\n }\n}\n","/**\n * Load workflow context from completed stages.\n *\n * For each completed stage, loads the output from BlobStore using\n * the _artifactKey stored in stage.outputData.\n */\n\nimport type { KernelDeps } from \"../kernel.js\";\n\nexport async function loadWorkflowContext(\n workflowRunId: string,\n deps: KernelDeps,\n): Promise<Record<string, unknown>> {\n const completedStages = await deps.persistence.getStagesByRun(workflowRunId, {\n status: \"COMPLETED\",\n orderBy: \"asc\",\n });\n\n const context: Record<string, unknown> = {};\n\n for (const stage of completedStages) {\n const outputData = stage.outputData as any;\n if (outputData?._artifactKey) {\n context[stage.stageId] = await deps.blobStore.get(\n outputData._artifactKey,\n );\n } else if (outputData && typeof outputData === \"object\") {\n context[stage.stageId] = outputData;\n }\n }\n\n return context;\n}\n","/**\n * Save stage output to BlobStore and return the blob key.\n *\n * The key is stored in stage.outputData._artifactKey so that\n * loadWorkflowContext() can retrieve it later.\n */\n\nimport type { KernelDeps } from \"../kernel.js\";\n\nexport async function saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n deps: KernelDeps,\n): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n await deps.blobStore.put(key, output);\n return key;\n}\n","/**\n * Shared StageStorage implementation backed by BlobStore.\n *\n * Used by both job-execute and stage-poll-suspended handlers.\n */\n\nimport type { StageStorage } from \"../../core/stage.js\";\nimport type { KernelDeps } from \"../kernel.js\";\n\nexport function createStorageShim(\n workflowRunId: string,\n workflowType: string,\n deps: KernelDeps,\n): StageStorage {\n return {\n async save<T>(key: string, data: T): Promise<void> {\n await deps.blobStore.put(key, data);\n },\n\n async load<T>(key: string): Promise<T> {\n return deps.blobStore.get(key) as Promise<T>;\n },\n\n async exists(key: string): Promise<boolean> {\n return deps.blobStore.has(key);\n },\n\n async delete(key: string): Promise<void> {\n return deps.blobStore.delete(key);\n },\n\n getStageKey(stageId: string, suffix?: string): string {\n const base = `workflow-v2/${workflowType}/${workflowRunId}/${stageId}`;\n return suffix ? `${base}/${suffix}` : `${base}/output.json`;\n },\n };\n}\n","/**\n * Handler: job.execute\n *\n * Executes a single stage within a workflow run using a multi-phase\n * transaction pattern:\n *\n * Phase 1 (Start): upsert stage to RUNNING + write stage:started\n * outbox event in one transaction. Commits\n * immediately so RUNNING is visible.\n *\n * Phase 2 (Execute): run stageDef.execute() outside any database\n * transaction. Progress events are collected\n * in memory.\n *\n * Phase 3 (Complete): update stage to COMPLETED/SUSPENDED/FAILED +\n * write completion outbox event (and progress\n * events) in one transaction.\n *\n * This avoids holding a database transaction open for the duration of\n * potentially long-running stage execution (AI calls, HTTP requests,\n * etc.). If the process crashes between Phase 1 and Phase 3, the\n * stage stays RUNNING and lease.reapStale will retry the job.\n */\n\nimport type { StageContext } from \"../../core/stage\";\nimport type { ProgressUpdate } from \"../../core/types\";\nimport { isSuspendedResult } from \"../../core/types\";\nimport type { Workflow } from \"../../core/workflow\";\nimport type { CreateOutboxEventInput } from \"../../persistence/interface\";\nimport type { JobExecuteCommand, JobExecuteResult } from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport {\n createStorageShim,\n loadWorkflowContext,\n saveStageOutput,\n} from \"../helpers/index.js\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\n// ---------------------------------------------------------------------------\n// Helper: resolve stage input\n// ---------------------------------------------------------------------------\n\nfunction resolveStageInput(\n workflow: Workflow<any, any>,\n stageId: string,\n workflowRun: { input: any },\n workflowContext: Record<string, unknown>,\n): unknown {\n const groupIndex = workflow.getExecutionGroupIndex(stageId);\n\n if (groupIndex === 0) return workflowRun.input;\n\n const prevStageId = workflow.getPreviousStageId(stageId);\n if (prevStageId && workflowContext[prevStageId] !== undefined) {\n return workflowContext[prevStageId];\n }\n\n return workflowRun.input;\n}\n\n// ---------------------------------------------------------------------------\n// Helper: build outbox event inputs from kernel events\n// ---------------------------------------------------------------------------\n\nfunction toOutboxEvents(\n workflowRunId: string,\n causationId: string,\n events: KernelEvent[],\n): CreateOutboxEventInput[] {\n return events.map((event) => ({\n workflowRunId,\n eventType: event.type,\n payload: event,\n causationId,\n occurredAt: event.timestamp,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleJobExecute(\n command: JobExecuteCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<JobExecuteResult>> {\n const { workflowRunId, workflowId, stageId, config } = command;\n const startTime = deps.clock.now().getTime();\n const causationId = command.idempotencyKey ?? crypto.randomUUID();\n\n // ── Pre-flight (no transaction) ──────────────────────────────────\n // Read-only lookups: workflow def, stage def, run record, context.\n\n const workflow = deps.registry.getWorkflow(workflowId);\n if (!workflow)\n throw new Error(`Workflow ${workflowId} not found in registry`);\n\n const stageDef = workflow.getStage(stageId);\n if (!stageDef)\n throw new Error(`Stage ${stageId} not found in workflow ${workflowId}`);\n\n const workflowRun = await deps.persistence.getRun(workflowRunId);\n if (!workflowRun) throw new Error(`WorkflowRun ${workflowRunId} not found`);\n\n // Guard against ghost jobs — only execute if run is actively RUNNING\n if (workflowRun.status !== \"RUNNING\") {\n return {\n outcome: \"failed\" as const,\n error: `Run ${workflowRunId} is ${workflowRun.status}, expected RUNNING — ghost job discarded`,\n _events: [],\n };\n }\n\n const workflowContext = await loadWorkflowContext(workflowRunId, deps);\n\n // ── Phase 1: Start transaction ───────────────────────────────────\n // Upsert stage to RUNNING and write stage:started outbox event.\n // Commits immediately so RUNNING status is visible to observers.\n\n const stageRecord = await deps.persistence.withTransaction(async (tx) => {\n const record = await tx.upsertStage({\n workflowRunId,\n stageId,\n create: {\n workflowRunId,\n stageId,\n stageName: stageDef.name,\n stageNumber: workflow.getStageIndex(stageId) + 1,\n executionGroup: workflow.getExecutionGroupIndex(stageId),\n status: \"RUNNING\",\n startedAt: deps.clock.now(),\n config: config as any,\n },\n update: {\n status: \"RUNNING\",\n startedAt: deps.clock.now(),\n },\n });\n\n await tx.appendOutboxEvents(\n toOutboxEvents(workflowRunId, causationId, [\n {\n type: \"stage:started\",\n timestamp: deps.clock.now(),\n workflowRunId,\n stageId,\n stageName: stageDef.name,\n stageNumber: record.stageNumber,\n },\n ]),\n );\n\n return record;\n });\n\n // ── Phase 2: Execute (no transaction) ────────────────────────────\n // The stage's execute() function runs outside any database\n // transaction. Progress events are collected in memory and\n // written to the outbox in Phase 3.\n\n const progressEvents: KernelEvent[] = [];\n\n try {\n // Resolve and validate input\n const rawInput = resolveStageInput(\n workflow,\n stageId,\n workflowRun,\n workflowContext,\n );\n const validatedInput = stageDef.inputSchema.parse(rawInput);\n\n // Parse config\n let stageConfig = (config as any)[stageId] || {};\n try {\n if (stageDef.configSchema) {\n stageConfig = stageDef.configSchema.parse(stageConfig);\n }\n } catch {\n // Fall back to raw config on parse failure\n }\n\n // Build log function (fire-and-forget, no transaction needed)\n const logFn = async (\n level: any,\n message: string,\n meta?: Record<string, unknown>,\n ) => {\n await deps.persistence\n .createLog({\n workflowRunId,\n workflowStageId: stageRecord.id,\n level: level as any,\n message,\n metadata: meta,\n })\n .catch(() => {});\n };\n\n // Build context\n const context: StageContext<any, any, any> = {\n workflowRunId,\n stageId,\n stageNumber: stageRecord.stageNumber,\n stageName: stageDef.name,\n stageRecordId: stageRecord.id,\n input: validatedInput,\n config: stageConfig,\n resumeState: stageRecord.suspendedState as any,\n onProgress: (update: ProgressUpdate) => {\n progressEvents.push({\n type: \"stage:progress\",\n timestamp: deps.clock.now(),\n workflowRunId,\n stageId,\n progress: update.progress,\n message: update.message,\n details: update.details,\n });\n },\n onLog: logFn,\n log: logFn,\n storage: createStorageShim(workflowRunId, workflowRun.workflowType, deps),\n workflowContext,\n };\n\n // Execute the stage — this is the potentially long-running part\n const result = await stageDef.execute(context);\n\n // ── Phase 3a: Complete transaction (success) ─────────────────\n if (isSuspendedResult(result)) {\n const { state, pollConfig, metrics } = result;\n const nextPollAt = new Date(\n pollConfig.nextPollAt?.getTime() ??\n deps.clock.now().getTime() + (pollConfig.pollInterval || 60000),\n );\n\n await deps.persistence.withTransaction(async (tx) => {\n await tx.updateStage(stageRecord.id, {\n status: \"SUSPENDED\",\n suspendedState: state as any,\n nextPollAt,\n pollInterval: pollConfig.pollInterval,\n maxWaitUntil: pollConfig.maxWaitTime\n ? new Date(deps.clock.now().getTime() + pollConfig.maxWaitTime)\n : undefined,\n metrics: metrics as any,\n });\n\n const suspendedEvent: KernelEvent = {\n type: \"stage:suspended\",\n timestamp: deps.clock.now(),\n workflowRunId,\n stageId,\n stageName: stageDef.name,\n nextPollAt,\n };\n\n await tx.appendOutboxEvents(\n toOutboxEvents(workflowRunId, causationId, [\n ...progressEvents,\n suspendedEvent,\n ]),\n );\n });\n\n return { outcome: \"suspended\" as const, nextPollAt, _events: [] };\n } else {\n const duration = deps.clock.now().getTime() - startTime;\n\n // Save output to blob store (not a DB operation)\n const outputKey = await saveStageOutput(\n workflowRunId,\n workflowRun.workflowType,\n stageId,\n result.output,\n deps,\n );\n\n await deps.persistence.withTransaction(async (tx) => {\n await tx.updateStage(stageRecord.id, {\n status: \"COMPLETED\",\n completedAt: deps.clock.now(),\n duration,\n outputData: { _artifactKey: outputKey } as any,\n metrics: result.metrics as any,\n embeddingInfo: result.embeddings as any,\n });\n\n const completedEvent: KernelEvent = {\n type: \"stage:completed\",\n timestamp: deps.clock.now(),\n workflowRunId,\n stageId,\n stageName: stageDef.name,\n duration,\n };\n\n await tx.appendOutboxEvents(\n toOutboxEvents(workflowRunId, causationId, [\n ...progressEvents,\n completedEvent,\n ]),\n );\n });\n\n return {\n outcome: \"completed\" as const,\n output: result.output,\n _events: [],\n };\n }\n } catch (error) {\n // ── Phase 3b: Complete transaction (failure) ─────────────────\n // The stage's execute() threw. Write FAILED status + outbox\n // event. If Phase 3 itself fails, re-throw the original error\n // so the idempotency key is released and the job can be retried.\n const errorMessage = error instanceof Error ? error.message : String(error);\n const duration = deps.clock.now().getTime() - startTime;\n\n try {\n await deps.persistence.withTransaction(async (tx) => {\n await tx.updateStage(stageRecord.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n duration,\n errorMessage,\n });\n\n const failedEvent: KernelEvent = {\n type: \"stage:failed\",\n timestamp: deps.clock.now(),\n workflowRunId,\n stageId,\n stageName: stageDef.name,\n error: errorMessage,\n };\n\n await tx.appendOutboxEvents(\n toOutboxEvents(workflowRunId, causationId, [\n ...progressEvents,\n failedEvent,\n ]),\n );\n });\n } catch {\n // Phase 3 itself failed. Stage stays RUNNING.\n // Re-throw the original error so the idempotency key is\n // released and lease.reapStale can retry the job.\n throw error;\n }\n\n await deps.persistence\n .createLog({\n workflowRunId,\n workflowStageId: stageRecord.id,\n level: \"ERROR\",\n message: errorMessage,\n })\n .catch(() => {});\n\n return { outcome: \"failed\" as const, error: errorMessage, _events: [] };\n }\n}\n","/**\n * Handler: lease.reapStale\n *\n * Releases stale job leases that have exceeded the threshold.\n */\n\nimport type { LeaseReapStaleCommand, LeaseReapStaleResult } from \"../commands\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handleLeaseReapStale(\n command: LeaseReapStaleCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<LeaseReapStaleResult>> {\n const released = await deps.jobTransport.releaseStaleJobs(\n command.staleThresholdMs,\n );\n\n return { released, _events: [] };\n}\n","/**\n * Handler: outbox.flush\n *\n * Reads unpublished outbox events and publishes them through EventSink.\n * Events are emitted in order (workflowRunId, sequence) and marked as\n * published after successful emission.\n *\n * On handler failure:\n * - Increments retryCount on the outbox event\n * - If retryCount >= maxRetries, moves event to DLQ\n * - Event is NOT marked as published (will retry on next flush)\n *\n * This handler returns _events: [] — it does NOT produce new outbox events.\n */\n\nimport type { OutboxFlushCommand, OutboxFlushResult } from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\nimport type { PluginRunner } from \"../plugins\";\n\nexport async function handleOutboxFlush(\n command: OutboxFlushCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<OutboxFlushResult>> {\n const limit = command.maxEvents ?? 100;\n const events = await deps.persistence.getUnpublishedOutboxEvents(limit);\n\n // Determine maxRetries from EventSink (if it's a PluginRunner)\n const maxRetries = (deps.eventSink as Partial<PluginRunner>).maxRetries ?? 3;\n\n const publishedIds: string[] = [];\n\n for (const outboxEvent of events) {\n try {\n await deps.eventSink.emit(outboxEvent.payload as KernelEvent);\n publishedIds.push(outboxEvent.id);\n } catch {\n const newCount = await deps.persistence.incrementOutboxRetryCount(\n outboxEvent.id,\n );\n if (newCount >= maxRetries) {\n await deps.persistence.moveOutboxEventToDLQ(outboxEvent.id);\n }\n // Event stays unpublished — will retry on next flush (unless DLQ'd)\n }\n }\n\n if (publishedIds.length > 0) {\n await deps.persistence.markOutboxEventsPublished(publishedIds);\n }\n\n return { published: publishedIds.length, _events: [] };\n}\n","/**\n * Handler: plugin.replayDLQ\n *\n * Resets DLQ outbox events (dlqAt and retryCount) so they are\n * picked up by the next outbox.flush invocation.\n *\n * This handler returns _events: [] — it does NOT produce new outbox events.\n */\n\nimport type {\n PluginReplayDLQCommand,\n PluginReplayDLQResult,\n} from \"../commands\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handlePluginReplayDLQ(\n command: PluginReplayDLQCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<PluginReplayDLQResult>> {\n const maxEvents = command.maxEvents ?? 100;\n const replayed = await deps.persistence.replayDLQEvents(maxEvents);\n return { replayed, _events: [] };\n}\n","/**\n * Handler: run.cancel\n *\n * Cancels a running workflow if it is not already in a terminal state.\n */\n\nimport type { RunCancelCommand, RunCancelResult } from \"../commands\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nconst TERMINAL_STATUSES = new Set([\"COMPLETED\", \"FAILED\", \"CANCELLED\"]);\n\nexport async function handleRunCancel(\n command: RunCancelCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunCancelResult>> {\n const run = await deps.persistence.getRun(command.workflowRunId);\n\n if (!run || TERMINAL_STATUSES.has(run.status)) {\n return { cancelled: false, _events: [] };\n }\n\n await deps.persistence.updateRun(command.workflowRunId, {\n status: \"CANCELLED\",\n completedAt: deps.clock.now(),\n });\n\n return {\n cancelled: true,\n _events: [\n {\n type: \"workflow:cancelled\",\n timestamp: deps.clock.now(),\n workflowRunId: command.workflowRunId,\n reason: command.reason,\n },\n ],\n };\n}\n","/**\n * Handler: run.claimPending\n *\n * Claims pending workflow runs, creates first-stage records, and enqueues\n * their jobs for processing.\n */\n\nimport type {\n RunClaimPendingCommand,\n RunClaimPendingResult,\n} from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handleRunClaimPending(\n command: RunClaimPendingCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunClaimPendingResult>> {\n const maxClaims = command.maxClaims ?? 10;\n const claimed: Array<{\n workflowRunId: string;\n workflowId: string;\n jobIds: string[];\n }> = [];\n const events: KernelEvent[] = [];\n\n for (let i = 0; i < maxClaims; i++) {\n const run = await deps.persistence.claimNextPendingRun();\n if (!run) break;\n\n try {\n const workflow = deps.registry.getWorkflow(run.workflowId);\n if (!workflow) {\n const error = `Workflow ${run.workflowId} not found in registry`;\n const failedAt = deps.clock.now();\n await deps.persistence.updateRun(run.id, {\n status: \"FAILED\",\n completedAt: failedAt,\n output: {\n error: {\n code: \"WORKFLOW_NOT_FOUND\",\n message: error,\n workerId: command.workerId,\n },\n },\n });\n await deps.persistence\n .createLog({\n workflowRunId: run.id,\n level: \"ERROR\",\n message: error,\n metadata: {\n workerId: command.workerId,\n code: \"WORKFLOW_NOT_FOUND\",\n },\n })\n .catch(() => {});\n events.push({\n type: \"workflow:failed\",\n timestamp: failedAt,\n workflowRunId: run.id,\n error,\n });\n continue;\n }\n\n const stages = workflow.getStagesInExecutionGroup(1);\n if (stages.length === 0) {\n const error = `Workflow ${run.workflowId} has no stages in execution group 1`;\n const failedAt = deps.clock.now();\n await deps.persistence.updateRun(run.id, {\n status: \"FAILED\",\n completedAt: failedAt,\n output: {\n error: {\n code: \"EMPTY_STAGE_GRAPH\",\n message: error,\n workerId: command.workerId,\n },\n },\n });\n await deps.persistence\n .createLog({\n workflowRunId: run.id,\n level: \"ERROR\",\n message: error,\n metadata: {\n workerId: command.workerId,\n code: \"EMPTY_STAGE_GRAPH\",\n },\n })\n .catch(() => {});\n events.push({\n type: \"workflow:failed\",\n timestamp: failedAt,\n workflowRunId: run.id,\n error,\n });\n continue;\n }\n\n // Upsert stage records (idempotent — handles orphaned stages from previous failed claims)\n const stagesToEnqueue: typeof stages = [];\n for (const stage of stages) {\n const record = await deps.persistence.upsertStage({\n workflowRunId: run.id,\n stageId: stage.id,\n create: {\n workflowRunId: run.id,\n stageId: stage.id,\n stageName: stage.name,\n stageNumber: workflow.getStageIndex(stage.id) + 1,\n executionGroup: 1,\n status: \"PENDING\",\n config: (run.config as any)?.[stage.id] || {},\n },\n update: {},\n });\n if (record.status === \"PENDING\") {\n stagesToEnqueue.push(stage);\n }\n }\n\n // Enqueue jobs only for stages that are PENDING (skip RUNNING/COMPLETED/SUSPENDED)\n const jobIds =\n stagesToEnqueue.length > 0\n ? await deps.jobTransport.enqueueParallel(\n stagesToEnqueue.map((stage) => ({\n workflowRunId: run.id,\n workflowId: run.workflowId,\n stageId: stage.id,\n priority: run.priority,\n payload: { config: run.config || {} },\n })),\n )\n : [];\n\n events.push({\n type: \"workflow:started\",\n timestamp: deps.clock.now(),\n workflowRunId: run.id,\n });\n\n claimed.push({\n workflowRunId: run.id,\n workflowId: run.workflowId,\n jobIds,\n });\n } catch (err) {\n const error =\n err instanceof Error ? err.message : \"Unknown error during claim\";\n const failedAt = deps.clock.now();\n await deps.persistence\n .updateRun(run.id, {\n status: \"FAILED\",\n completedAt: failedAt,\n output: {\n error: {\n code: \"CLAIM_FAILED\",\n message: error,\n workerId: command.workerId,\n },\n },\n })\n .catch(() => {});\n await deps.persistence\n .createLog({\n workflowRunId: run.id,\n level: \"ERROR\",\n message: error,\n metadata: {\n workerId: command.workerId,\n code: \"CLAIM_FAILED\",\n },\n })\n .catch(() => {});\n events.push({\n type: \"workflow:failed\",\n timestamp: failedAt,\n workflowRunId: run.id,\n error,\n });\n continue;\n }\n }\n\n return { claimed, _events: events };\n}\n","/**\n * Handler: run.create\n *\n * Creates a new workflow run record after validating input and config.\n */\n\nimport type { RunCreateCommand, RunCreateResult } from \"../commands\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handleRunCreate(\n command: RunCreateCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunCreateResult>> {\n // 1. Get workflow from registry\n const workflow = deps.registry.getWorkflow(command.workflowId);\n if (!workflow) {\n throw new Error(`Workflow ${command.workflowId} not found in registry`);\n }\n\n // 2. Validate input against workflow's input schema\n try {\n workflow.inputSchema.parse(command.input);\n } catch (error) {\n throw new Error(`Invalid workflow input: ${error}`);\n }\n\n // 3. Get default config and merge with provided config\n const defaultConfig = workflow.getDefaultConfig?.() ?? {};\n const mergedConfig = { ...defaultConfig, ...command.config };\n\n // 4. Validate merged config\n const configValidation = workflow.validateConfig(mergedConfig);\n if (!configValidation.valid) {\n const errors = configValidation.errors\n .map((e) => `${e.stageId}: ${e.error}`)\n .join(\", \");\n throw new Error(`Invalid workflow config: ${errors}`);\n }\n\n // 5. Calculate priority\n const priority = command.priority ?? 5;\n\n // 6. Create the run record\n const run = await deps.persistence.createRun({\n workflowId: command.workflowId,\n workflowName: workflow.name,\n workflowType: command.workflowId,\n input: command.input,\n config: mergedConfig,\n priority,\n metadata: command.metadata,\n });\n\n return {\n workflowRunId: run.id,\n status: \"PENDING\" as const,\n _events: [\n {\n type: \"workflow:created\",\n timestamp: deps.clock.now(),\n workflowRunId: run.id,\n workflowId: command.workflowId,\n },\n ],\n };\n}\n","import type { RunReapStuckCommand, RunReapStuckResult } from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handleRunReapStuck(\n command: RunReapStuckCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunReapStuckResult>> {\n const events: KernelEvent[] = [];\n const stuckSince = new Date(\n deps.clock.now().getTime() - command.stuckThresholdMs,\n );\n\n const stuckRuns = await deps.persistence.getStuckRuns(stuckSince);\n let failed = 0;\n\n for (const run of stuckRuns) {\n const stages = await deps.persistence.getStagesByRun(run.id);\n\n // Status guard: only update if run is still RUNNING to avoid\n // overwriting a run that recovered between query and update.\n const currentStatus = await deps.persistence.getRunStatus(run.id);\n if (currentStatus !== \"RUNNING\") {\n continue;\n }\n\n await deps.persistence.updateRun(run.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n output: {\n error: {\n code: \"STUCK_RUN_REAPED\",\n message: `Run stuck for >${command.stuckThresholdMs}ms with no activity`,\n stageStatuses: stages.map((s) => ({\n stageId: s.stageId,\n status: s.status,\n })),\n },\n },\n });\n\n events.push({\n type: \"workflow:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: run.id,\n error: `Stuck run reaped after ${command.stuckThresholdMs}ms inactivity`,\n });\n\n failed++;\n }\n\n return { transitioned: 0, failed, _events: events };\n}\n","/**\n * Handler: run.rerunFrom\n *\n * Reruns a workflow from a specific stage. Deletes stage records and\n * blob artifacts at/after the target execution group, resets the run\n * to RUNNING, creates new stage records, and enqueues jobs.\n *\n * Works for both COMPLETED runs (rerun from any stage) and FAILED runs\n * (retry from the failed stage).\n */\n\nimport type { RunRerunFromCommand, RunRerunFromResult } from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\nexport async function handleRunRerunFrom(\n command: RunRerunFromCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunRerunFromResult>> {\n const { workflowRunId, fromStageId } = command;\n const events: KernelEvent[] = [];\n\n // 1. Load run\n const run = await deps.persistence.getRun(workflowRunId);\n if (!run) throw new Error(`WorkflowRun ${workflowRunId} not found`);\n\n // 2. Validate run is in a rerunnable state\n if (run.status !== \"COMPLETED\" && run.status !== \"FAILED\") {\n throw new Error(\n `Cannot rerun workflow in ${run.status} state. Must be COMPLETED or FAILED.`,\n );\n }\n\n // 3. Load workflow definition\n const workflow = deps.registry.getWorkflow(run.workflowId);\n if (!workflow)\n throw new Error(`Workflow ${run.workflowId} not found in registry`);\n\n // 4. Validate stage exists in workflow\n const stageDef = workflow.getStage(fromStageId);\n if (!stageDef) {\n throw new Error(\n `Stage ${fromStageId} not found in workflow ${run.workflowId}`,\n );\n }\n\n // 5. Get the execution group of the target stage\n const targetGroup = workflow.getExecutionGroupIndex(fromStageId);\n\n // 6. Get all existing stage records\n const existingStages = await deps.persistence.getStagesByRun(workflowRunId);\n\n // 7. Validate: stages before the target group must have been executed\n if (targetGroup > 1) {\n const priorStages = existingStages.filter(\n (s) => s.executionGroup < targetGroup,\n );\n if (priorStages.length === 0) {\n throw new Error(\n `Cannot rerun from stage ${fromStageId}: previous stages have not been executed`,\n );\n }\n }\n\n // 8. Find stages to delete (at or after the target group)\n const stagesToDelete = existingStages.filter(\n (s) => s.executionGroup >= targetGroup,\n );\n const deletedStageIds = stagesToDelete.map((s) => s.stageId);\n\n // 9. Delete blob artifacts for stages being removed\n for (const stage of stagesToDelete) {\n const outputRef = stage.outputData as { _artifactKey?: string } | null;\n if (outputRef?._artifactKey) {\n await deps.blobStore.delete(outputRef._artifactKey).catch(() => {});\n }\n }\n\n // 10. Delete stage records\n for (const stage of stagesToDelete) {\n await deps.persistence.deleteStage(stage.id);\n }\n\n // 11. Reset run to RUNNING\n await deps.persistence.updateRun(workflowRunId, {\n status: \"RUNNING\",\n completedAt: null,\n });\n\n // 12. Create new stage records for the target execution group\n const targetStages = workflow.getStagesInExecutionGroup(targetGroup);\n for (const stage of targetStages) {\n await deps.persistence.createStage({\n workflowRunId,\n stageId: stage.id,\n stageName: stage.name,\n stageNumber: workflow.getStageIndex(stage.id) + 1,\n executionGroup: targetGroup,\n status: \"PENDING\",\n config: (run.config as any)?.[stage.id] || {},\n });\n }\n\n // 13. Enqueue jobs\n await deps.jobTransport.enqueueParallel(\n targetStages.map((stage) => ({\n workflowRunId,\n workflowId: run.workflowId,\n stageId: stage.id,\n priority: run.priority,\n payload: { config: run.config || {} },\n })),\n );\n\n // 14. Emit workflow:started event (restarted)\n events.push({\n type: \"workflow:started\",\n timestamp: deps.clock.now(),\n workflowRunId,\n });\n\n return {\n workflowRunId,\n fromStageId,\n deletedStages: deletedStageIds,\n _events: events,\n };\n}\n","/**\n * Handler: run.transition\n *\n * Advances a workflow run to its next execution group, or marks it as\n * completed/failed depending on the current state of its stages.\n *\n * Extracted from WorkflowRuntime.transitionWorkflow() and completeWorkflow().\n */\n\nimport type { Workflow } from \"../../core/workflow\";\nimport type { RunTransitionCommand, RunTransitionResult } from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\nimport type { WorkflowRunRecord } from \"../ports\";\n\n// ---------------------------------------------------------------------------\n// Terminal statuses -- a run in one of these states cannot be transitioned.\n// ---------------------------------------------------------------------------\n\nconst TERMINAL_STATUSES = new Set([\"COMPLETED\", \"FAILED\", \"CANCELLED\"]);\n\n// ---------------------------------------------------------------------------\n// Active statuses -- if any stage is in one of these states the run is still\n// in-flight and should not be transitioned yet.\n// ---------------------------------------------------------------------------\n\nconst ACTIVE_STATUSES = new Set([\"RUNNING\", \"PENDING\", \"SUSPENDED\"]);\n\n// ---------------------------------------------------------------------------\n// Helper: enqueue an execution group\n// ---------------------------------------------------------------------------\n\nasync function enqueueExecutionGroup(\n run: WorkflowRunRecord,\n workflow: Workflow<any, any>,\n groupIndex: number,\n deps: KernelDeps,\n): Promise<string[]> {\n const stages = workflow.getStagesInExecutionGroup(groupIndex);\n\n const stagesToEnqueue: typeof stages = [];\n for (const stage of stages) {\n const record = await deps.persistence.upsertStage({\n workflowRunId: run.id,\n stageId: stage.id,\n create: {\n workflowRunId: run.id,\n stageId: stage.id,\n stageName: stage.name,\n stageNumber: workflow.getStageIndex(stage.id) + 1,\n executionGroup: groupIndex,\n status: \"PENDING\",\n config: (run.config as any)?.[stage.id] || {},\n },\n update: {},\n });\n if (record.status === \"PENDING\") {\n stagesToEnqueue.push(stage);\n }\n }\n\n if (stagesToEnqueue.length === 0) return [];\n\n return deps.jobTransport.enqueueParallel(\n stagesToEnqueue.map((stage) => ({\n workflowRunId: run.id,\n workflowId: run.workflowId,\n stageId: stage.id,\n priority: run.priority,\n payload: { config: run.config || {} },\n })),\n );\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleRunTransition(\n command: RunTransitionCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<RunTransitionResult>> {\n const events: KernelEvent[] = [];\n\n // 1. Get run from persistence\n const run = await deps.persistence.getRun(command.workflowRunId);\n if (!run) {\n return { action: \"noop\" as const, _events: [] };\n }\n\n // 2. If run is already in a terminal state, nothing to do\n if (TERMINAL_STATUSES.has(run.status)) {\n return { action: \"noop\" as const, _events: [] };\n }\n\n // 3. Get workflow definition from registry\n const workflow = deps.registry.getWorkflow(run.workflowId);\n if (!workflow) {\n return { action: \"noop\" as const, _events: [] };\n }\n\n // 4. Get all stages for this run\n const stages = await deps.persistence.getStagesByRun(command.workflowRunId);\n\n // 5. If no stages exist, this is the first transition -- enqueue group 1\n if (stages.length === 0) {\n await enqueueExecutionGroup(run, workflow, 1, deps);\n\n events.push({\n type: \"workflow:started\",\n timestamp: deps.clock.now(),\n workflowRunId: run.id,\n });\n\n return { action: \"advanced\" as const, nextGroup: 1, _events: events };\n }\n\n // 6. If any stage is still active, the run is in-flight -- noop\n const hasActive = stages.some((s) => ACTIVE_STATUSES.has(s.status));\n if (hasActive) {\n return { action: \"noop\" as const, _events: [] };\n }\n\n // 7. If any stage has failed, mark the entire run as failed\n const failedStage = stages.find((s) => s.status === \"FAILED\");\n if (failedStage) {\n await deps.persistence.updateRun(command.workflowRunId, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n });\n\n events.push({\n type: \"workflow:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: command.workflowRunId,\n error: failedStage.errorMessage || \"Stage failed\",\n });\n\n return { action: \"failed\" as const, _events: events };\n }\n\n // 8. Find the maximum execution group among completed stages\n const maxGroup = stages.reduce(\n (max, s) => (s.executionGroup > max ? s.executionGroup : max),\n 0,\n );\n\n // 9. Get stages in the next execution group\n const nextGroupStages = workflow.getStagesInExecutionGroup(maxGroup + 1);\n\n // 10. If there are stages in the next group, enqueue them\n if (nextGroupStages.length > 0) {\n await enqueueExecutionGroup(run, workflow, maxGroup + 1, deps);\n return {\n action: \"advanced\" as const,\n nextGroup: maxGroup + 1,\n _events: events,\n };\n }\n\n // 11. No next group -- the workflow is complete\n let totalCost = 0;\n let totalTokens = 0;\n\n for (const stage of stages) {\n const metrics = stage.metrics as any;\n if (metrics) {\n totalCost += metrics.totalCost ?? 0;\n totalTokens += metrics.totalTokens ?? 0;\n }\n }\n\n const duration = deps.clock.now().getTime() - run.createdAt.getTime();\n\n await deps.persistence.updateRun(command.workflowRunId, {\n status: \"COMPLETED\",\n completedAt: deps.clock.now(),\n duration,\n totalCost,\n totalTokens,\n });\n\n events.push({\n type: \"workflow:completed\",\n timestamp: deps.clock.now(),\n workflowRunId: command.workflowRunId,\n duration,\n totalCost,\n totalTokens,\n });\n\n return { action: \"completed\" as const, _events: events };\n}\n","/**\n * Handler: stage.pollSuspended\n *\n * Polls suspended stages whose nextPollAt has passed, calls each stage's\n * checkCompletion() method, and either resumes (completes) or re-schedules\n * them for a future poll.\n *\n * Extracted from WorkflowRuntime.pollSuspendedStages() + checkAndResume().\n */\n\nimport type {\n StagePollSuspendedCommand,\n StagePollSuspendedResult,\n} from \"../commands\";\nimport type { KernelEvent } from \"../events\";\nimport { createStorageShim, saveStageOutput } from \"../helpers/index.js\";\nimport type { HandlerResult, KernelDeps } from \"../kernel\";\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function handleStagePollSuspended(\n command: StagePollSuspendedCommand,\n deps: KernelDeps,\n): Promise<HandlerResult<StagePollSuspendedResult>> {\n const events: KernelEvent[] = [];\n const maxChecks = command.maxChecks ?? 50;\n\n // 1. Get suspended stages that are ready to be polled\n const suspendedStages = await deps.persistence.getSuspendedStages(\n deps.clock.now(),\n );\n\n // 2. Limit to maxChecks\n const stagesToCheck = suspendedStages.slice(0, maxChecks);\n\n let checked = 0;\n let resumed = 0;\n let failed = 0;\n const resumedWorkflowRunIds = new Set<string>();\n\n // 3. Process each suspended stage\n for (const stageRecord of stagesToCheck) {\n checked++;\n\n // 3a. Get workflow run\n const run = await deps.persistence.getRun(stageRecord.workflowRunId);\n if (!run) continue;\n\n // 3b. Get workflow from registry\n const workflow = deps.registry.getWorkflow(run.workflowId);\n if (!workflow) {\n await deps.persistence.updateStage(stageRecord.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n errorMessage: `Workflow ${run.workflowId} not found in registry`,\n });\n failed++;\n\n events.push({\n type: \"stage:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n stageId: stageRecord.stageId,\n stageName: stageRecord.stageName,\n error: `Workflow ${run.workflowId} not found in registry`,\n });\n continue;\n }\n\n // 3c. Get stage definition\n const stageDef = workflow.getStage(stageRecord.stageId);\n if (!stageDef || !stageDef.checkCompletion) {\n const errorMsg = !stageDef\n ? `Stage ${stageRecord.stageId} not found in workflow ${run.workflowId}`\n : `Stage ${stageRecord.stageId} does not support checkCompletion`;\n\n await deps.persistence.updateStage(stageRecord.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n errorMessage: errorMsg,\n });\n failed++;\n\n events.push({\n type: \"stage:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n stageId: stageRecord.stageId,\n stageName: stageRecord.stageName,\n error: errorMsg,\n });\n continue;\n }\n\n // 3d. Create storage shim\n const storage = createStorageShim(\n stageRecord.workflowRunId,\n run.workflowType,\n deps,\n );\n\n // 3e. Create log function\n const logFn = async (\n level: any,\n message: string,\n meta?: Record<string, unknown>,\n ) => {\n await deps.persistence\n .createLog({\n workflowRunId: stageRecord.workflowRunId,\n workflowStageId: stageRecord.id,\n level: level as any,\n message,\n metadata: meta,\n })\n .catch(() => {});\n };\n\n // 3f. Build check context\n const checkContext = {\n workflowRunId: run.id,\n stageId: stageRecord.stageId,\n stageRecordId: stageRecord.id,\n config: stageRecord.config || {},\n log: logFn,\n onLog: logFn,\n storage,\n };\n\n try {\n // 3g. Call checkCompletion\n const checkResult = await stageDef.checkCompletion(\n stageRecord.suspendedState as any,\n checkContext,\n );\n\n if (checkResult.error) {\n // Error during check -- fail the stage and the run\n await deps.persistence.updateStage(stageRecord.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n errorMessage: checkResult.error,\n nextPollAt: null,\n });\n\n await deps.persistence.updateRun(stageRecord.workflowRunId, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n });\n\n failed++;\n\n events.push({\n type: \"stage:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n stageId: stageRecord.stageId,\n stageName: stageRecord.stageName,\n error: checkResult.error,\n });\n\n events.push({\n type: \"workflow:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n error: checkResult.error,\n });\n } else if (checkResult.ready) {\n // Ready -- complete the stage (output is optional)\n let outputRef: { _artifactKey: string } | undefined;\n if (checkResult.output !== undefined) {\n let validatedOutput = checkResult.output;\n try {\n validatedOutput = stageDef.outputSchema.parse(checkResult.output);\n } catch {\n // Fall back to raw output on validation failure\n }\n\n const outputKey = await saveStageOutput(\n stageRecord.workflowRunId,\n run.workflowType,\n stageRecord.stageId,\n validatedOutput,\n deps,\n );\n outputRef = { _artifactKey: outputKey };\n }\n\n const duration =\n deps.clock.now().getTime() -\n (stageRecord.startedAt?.getTime() ?? deps.clock.now().getTime());\n\n await deps.persistence.updateStage(stageRecord.id, {\n status: \"COMPLETED\",\n completedAt: deps.clock.now(),\n duration,\n outputData: outputRef as any,\n nextPollAt: null,\n metrics: checkResult.metrics as any,\n embeddingInfo: checkResult.embeddings as any,\n });\n\n resumed++;\n resumedWorkflowRunIds.add(stageRecord.workflowRunId);\n\n events.push({\n type: \"stage:completed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n stageId: stageRecord.stageId,\n stageName: stageRecord.stageName,\n duration,\n });\n } else {\n // Not ready -- update nextPollAt for next check\n const pollInterval =\n checkResult.nextCheckIn ?? stageRecord.pollInterval ?? 60000;\n\n const nextPollAt = new Date(deps.clock.now().getTime() + pollInterval);\n\n await deps.persistence.updateStage(stageRecord.id, {\n nextPollAt,\n });\n }\n } catch (error) {\n // Unexpected error during checkCompletion\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n await deps.persistence.updateStage(stageRecord.id, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n errorMessage,\n nextPollAt: null,\n });\n\n await deps.persistence.updateRun(stageRecord.workflowRunId, {\n status: \"FAILED\",\n completedAt: deps.clock.now(),\n });\n\n failed++;\n\n events.push({\n type: \"stage:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n stageId: stageRecord.stageId,\n stageName: stageRecord.stageName,\n error: errorMessage,\n });\n\n events.push({\n type: \"workflow:failed\",\n timestamp: deps.clock.now(),\n workflowRunId: stageRecord.workflowRunId,\n error: errorMessage,\n });\n }\n }\n\n return {\n checked,\n resumed,\n failed,\n resumedWorkflowRunIds: [...resumedWorkflowRunIds],\n _events: events,\n };\n}\n","/**\n * Kernel Factory\n *\n * Creates a Kernel instance with a typed `dispatch` method that routes\n * commands to their corresponding handlers. Events are written to a\n * transactional outbox (not emitted directly). Use the `outbox.flush`\n * command to publish pending outbox events through EventSink.\n *\n * Most commands execute inside a single database transaction (handler\n * logic + outbox event writes). `job.execute` is the exception — it\n * uses a multi-phase transaction pattern so that long-running stage\n * execution does not hold a database connection open. See the handler\n * in `handlers/job-execute.ts` for details.\n *\n * Commands with idempotency keys are deduplicated: a replay returns the\n * cached result without re-executing the handler.\n */\n\nimport type { Workflow } from \"../core/workflow\";\nimport type { CreateOutboxEventInput } from \"../persistence/interface\";\nimport type {\n CommandResult,\n JobExecuteCommand,\n KernelCommand,\n LeaseReapStaleCommand,\n OutboxFlushCommand,\n PluginReplayDLQCommand,\n RunCancelCommand,\n RunClaimPendingCommand,\n RunCreateCommand,\n RunReapStuckCommand,\n RunRerunFromCommand,\n RunTransitionCommand,\n StagePollSuspendedCommand,\n} from \"./commands\";\nimport { IdempotencyInProgressError } from \"./errors\";\nimport type { KernelEvent } from \"./events\";\nimport { handleJobExecute } from \"./handlers/job-execute\";\nimport { handleLeaseReapStale } from \"./handlers/lease-reap-stale\";\nimport { handleOutboxFlush } from \"./handlers/outbox-flush\";\nimport { handlePluginReplayDLQ } from \"./handlers/plugin-replay-dlq\";\nimport { handleRunCancel } from \"./handlers/run-cancel\";\nimport { handleRunClaimPending } from \"./handlers/run-claim-pending\";\nimport { handleRunCreate } from \"./handlers/run-create\";\nimport { handleRunReapStuck } from \"./handlers/run-reap-stuck\";\nimport { handleRunRerunFrom } from \"./handlers/run-rerun-from\";\nimport { handleRunTransition } from \"./handlers/run-transition\";\nimport { handleStagePollSuspended } from \"./handlers/stage-poll-suspended\";\nimport type {\n BlobStore,\n Clock,\n EventSink,\n JobTransport,\n Persistence,\n Scheduler,\n} from \"./ports\";\n\n// ============================================================================\n// Public interfaces\n// ============================================================================\n\nexport interface WorkflowRegistry {\n getWorkflow(id: string): Workflow<any, any> | undefined;\n}\n\nexport interface KernelConfig {\n persistence: Persistence;\n blobStore: BlobStore;\n jobTransport: JobTransport;\n eventSink: EventSink;\n scheduler: Scheduler;\n clock: Clock;\n registry: WorkflowRegistry;\n}\n\nexport interface Kernel {\n dispatch<T extends KernelCommand>(command: T): Promise<CommandResult<T>>;\n}\n\n// ============================================================================\n// Shared dependency bundle passed to every handler\n// ============================================================================\n\nexport interface KernelDeps {\n persistence: Persistence;\n blobStore: BlobStore;\n jobTransport: JobTransport;\n eventSink: EventSink;\n scheduler: Scheduler;\n clock: Clock;\n registry: WorkflowRegistry;\n}\n\n// ============================================================================\n// Internal handler result type (includes _events for central emission)\n// ============================================================================\n\nexport type HandlerResult<T> = T & { _events: KernelEvent[] };\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Extract idempotency key from commands that carry one. */\nfunction getIdempotencyKey(command: KernelCommand): string | undefined {\n if (command.type === \"run.create\") return command.idempotencyKey;\n if (command.type === \"job.execute\") return command.idempotencyKey;\n return undefined;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport function createKernel(config: KernelConfig): Kernel {\n const {\n persistence,\n blobStore,\n jobTransport,\n eventSink,\n scheduler,\n clock,\n registry,\n } = config;\n\n const deps: KernelDeps = {\n persistence,\n blobStore,\n jobTransport,\n eventSink,\n scheduler,\n clock,\n registry,\n };\n\n async function dispatch<T extends KernelCommand>(\n command: T,\n ): Promise<CommandResult<T>> {\n // -----------------------------------------------------------------\n // outbox.flush routes directly — no outbox write, no idempotency\n // -----------------------------------------------------------------\n if (command.type === \"outbox.flush\") {\n const result = await handleOutboxFlush(\n command as OutboxFlushCommand,\n deps,\n );\n const { _events: _, ...publicResult } = result;\n return publicResult as CommandResult<T>;\n }\n\n // -----------------------------------------------------------------\n // plugin.replayDLQ routes directly — no outbox write, no idempotency\n // -----------------------------------------------------------------\n if (command.type === \"plugin.replayDLQ\") {\n const result = await handlePluginReplayDLQ(\n command as PluginReplayDLQCommand,\n deps,\n );\n const { _events: _, ...publicResult } = result;\n return publicResult as CommandResult<T>;\n }\n\n // -----------------------------------------------------------------\n // job.execute manages its own multi-phase transactions so that\n // RUNNING status is visible immediately and long-running stage\n // execution does not hold a database transaction open.\n // -----------------------------------------------------------------\n if (command.type === \"job.execute\") {\n const jobCommand = command as JobExecuteCommand;\n const jobIdempotencyKey = jobCommand.idempotencyKey;\n let jobIdempotencyAcquired = false;\n\n if (jobIdempotencyKey) {\n const acquired = await persistence.acquireIdempotencyKey(\n jobIdempotencyKey,\n command.type,\n );\n if (acquired.status === \"replay\") {\n return acquired.result as CommandResult<T>;\n }\n if (acquired.status === \"in_progress\") {\n throw new IdempotencyInProgressError(jobIdempotencyKey, command.type);\n }\n jobIdempotencyAcquired = true;\n }\n\n try {\n const result = await handleJobExecute(jobCommand, deps);\n const { _events: _, ...publicResult } = result;\n\n if (jobIdempotencyKey && jobIdempotencyAcquired) {\n await persistence.completeIdempotencyKey(\n jobIdempotencyKey,\n command.type,\n publicResult,\n );\n }\n\n return publicResult as CommandResult<T>;\n } catch (error) {\n if (jobIdempotencyKey && jobIdempotencyAcquired) {\n await persistence\n .releaseIdempotencyKey(jobIdempotencyKey, command.type)\n .catch(() => {});\n }\n throw error;\n }\n }\n\n // -----------------------------------------------------------------\n // Idempotency acquisition\n // -----------------------------------------------------------------\n const idempotencyKey = getIdempotencyKey(command);\n let idempotencyAcquired = false;\n\n if (idempotencyKey) {\n const acquired = await persistence.acquireIdempotencyKey(\n idempotencyKey,\n command.type,\n );\n\n if (acquired.status === \"replay\") {\n return acquired.result as CommandResult<T>;\n }\n if (acquired.status === \"in_progress\") {\n throw new IdempotencyInProgressError(idempotencyKey, command.type);\n }\n idempotencyAcquired = true;\n }\n\n try {\n // ---------------------------------------------------------------\n // Route to handler + append outbox events in one transaction\n // ---------------------------------------------------------------\n const publicResult = await persistence.withTransaction(async (tx) => {\n const txDeps: KernelDeps = { ...deps, persistence: tx };\n let result: HandlerResult<any>;\n\n switch (command.type) {\n case \"run.create\":\n result = await handleRunCreate(command as RunCreateCommand, txDeps);\n break;\n case \"run.claimPending\":\n result = await handleRunClaimPending(\n command as RunClaimPendingCommand,\n txDeps,\n );\n break;\n case \"run.transition\":\n result = await handleRunTransition(\n command as RunTransitionCommand,\n txDeps,\n );\n break;\n case \"run.cancel\":\n result = await handleRunCancel(command as RunCancelCommand, txDeps);\n break;\n case \"run.rerunFrom\":\n result = await handleRunRerunFrom(\n command as RunRerunFromCommand,\n txDeps,\n );\n break;\n case \"stage.pollSuspended\":\n result = await handleStagePollSuspended(\n command as StagePollSuspendedCommand,\n txDeps,\n );\n break;\n case \"lease.reapStale\":\n result = await handleLeaseReapStale(\n command as LeaseReapStaleCommand,\n txDeps,\n );\n break;\n case \"run.reapStuck\":\n result = await handleRunReapStuck(\n command as RunReapStuckCommand,\n txDeps,\n );\n break;\n default: {\n const _exhaustive: never = command;\n throw new Error(\n `Unknown command type: ${(_exhaustive as KernelCommand).type}`,\n );\n }\n }\n\n const events = result._events as KernelEvent[];\n if (events.length > 0) {\n const causationId = idempotencyKey ?? crypto.randomUUID();\n const outboxEvents: CreateOutboxEventInput[] = events.map(\n (event) => ({\n workflowRunId: event.workflowRunId,\n eventType: event.type,\n payload: event,\n causationId,\n occurredAt: event.timestamp,\n }),\n );\n await tx.appendOutboxEvents(outboxEvents);\n }\n\n const { _events: _, ...stripped } = result;\n return stripped as CommandResult<T>;\n });\n\n if (idempotencyKey && idempotencyAcquired) {\n await persistence.completeIdempotencyKey(\n idempotencyKey,\n command.type,\n publicResult,\n );\n }\n\n return publicResult;\n } catch (error) {\n if (idempotencyKey && idempotencyAcquired) {\n await persistence\n .releaseIdempotencyKey(idempotencyKey, command.type)\n .catch(() => {});\n }\n throw error;\n }\n }\n\n return { dispatch };\n}\n","/**\n * Plugin Runner\n *\n * A concrete EventSink implementation that routes kernel events\n * to registered plugin handlers. Used as the eventSink when the\n * consumer wants domain side-effects on workflow events.\n */\n\nimport type { KernelEvent, KernelEventType } from \"./events.js\";\nimport type { EventSink } from \"./ports.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PluginDefinition<T extends KernelEventType = KernelEventType> {\n readonly id: string;\n readonly name: string;\n readonly on: readonly T[];\n handle(event: Extract<KernelEvent, { type: T }>): Promise<void>;\n}\n\nexport interface PluginRunnerConfig {\n plugins: PluginDefinition[];\n /** Max retries before an event moves to DLQ (default: 3). */\n maxRetries?: number;\n}\n\nexport interface PluginRunner extends EventSink {\n /** Max retries before DLQ. Exposed so outbox.flush can read it. */\n readonly maxRetries: number;\n}\n\n// ============================================================================\n// definePlugin\n// ============================================================================\n\nexport function definePlugin<T extends KernelEventType>(\n definition: PluginDefinition<T>,\n): PluginDefinition<T> {\n return definition;\n}\n\n// ============================================================================\n// createPluginRunner\n// ============================================================================\n\nexport function createPluginRunner(config: PluginRunnerConfig): PluginRunner {\n const { plugins, maxRetries = 3 } = config;\n\n // Pre-index plugins by event type for O(1) lookup\n const handlersByType = new Map<string, PluginDefinition[]>();\n for (const plugin of plugins) {\n for (const eventType of plugin.on) {\n const existing = handlersByType.get(eventType) ?? [];\n existing.push(plugin as PluginDefinition);\n handlersByType.set(eventType, existing);\n }\n }\n\n return {\n maxRetries,\n\n async emit(event: KernelEvent): Promise<void> {\n const matching = handlersByType.get(event.type);\n if (!matching || matching.length === 0) return;\n\n for (const plugin of matching) {\n await plugin.handle(event as any);\n }\n },\n };\n}\n"]}
|