@bratsos/workflow-engine 0.5.1 → 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.
Files changed (41) hide show
  1. package/README.md +65 -12
  2. package/dist/{chunk-RZY5YRGL.js → chunk-2MWO6UVR.js} +2 -2
  3. package/dist/chunk-2MWO6UVR.js.map +1 -0
  4. package/dist/{chunk-PHLNTR5Z.js → chunk-DIADEUGZ.js} +21 -3
  5. package/dist/chunk-DIADEUGZ.js.map +1 -0
  6. package/dist/{chunk-ZYMT2PAO.js → chunk-HKGZ2WHJ.js} +2 -30
  7. package/dist/chunk-HKGZ2WHJ.js.map +1 -0
  8. package/dist/{chunk-WQPZ6KON.js → chunk-HOGDFLCG.js} +280 -93
  9. package/dist/chunk-HOGDFLCG.js.map +1 -0
  10. package/dist/{client-oLD5ilXp.d.ts → client-llB6XpHS.d.ts} +10 -81
  11. package/dist/client.d.ts +4 -3
  12. package/dist/client.js +1 -1
  13. package/dist/events-D_P24UaY.d.ts +105 -0
  14. package/dist/{index-CVkkGnxx.d.ts → index-sGgV8JNu.d.ts} +5 -1
  15. package/dist/index.d.ts +184 -32
  16. package/dist/index.js +41 -9
  17. package/dist/index.js.map +1 -1
  18. package/dist/{interface-TsryH4d7.d.ts → interface-DCdddCe0.d.ts} +7 -2
  19. package/dist/kernel/index.d.ts +6 -5
  20. package/dist/kernel/index.js +2 -1
  21. package/dist/kernel/testing/index.d.ts +3 -2
  22. package/dist/persistence/index.d.ts +2 -2
  23. package/dist/persistence/index.js +2 -2
  24. package/dist/persistence/prisma/index.d.ts +2 -2
  25. package/dist/persistence/prisma/index.js +2 -2
  26. package/dist/{plugins-C94AT8Wr.d.ts → plugins-Oyo_iu0l.d.ts} +9 -6
  27. package/dist/{ports-855bktyD.d.ts → ports-ChGnJcn2.d.ts} +5 -106
  28. package/dist/{stage-BPw7m9Wx.d.ts → stage-_7BKqqUG.d.ts} +2 -2
  29. package/dist/testing/index.d.ts +2 -1
  30. package/dist/testing/index.js +23 -5
  31. package/dist/testing/index.js.map +1 -1
  32. package/package.json +1 -1
  33. package/skills/workflow-engine/SKILL.md +30 -11
  34. package/skills/workflow-engine/references/02-workflow-builder.md +2 -0
  35. package/skills/workflow-engine/references/03-runtime-setup.md +1 -1
  36. package/skills/workflow-engine/references/08-common-patterns.md +2 -1
  37. package/skills/workflow-engine/references/09-troubleshooting.md +4 -3
  38. package/dist/chunk-PHLNTR5Z.js.map +0 -1
  39. package/dist/chunk-RZY5YRGL.js.map +0 -1
  40. package/dist/chunk-WQPZ6KON.js.map +0 -1
  41. package/dist/chunk-ZYMT2PAO.js.map +0 -1
@@ -1,5 +1,5 @@
1
- export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createEnumHelper, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../../chunk-PHLNTR5Z.js';
1
+ export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createEnumHelper, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../../chunk-DIADEUGZ.js';
2
2
  import '../../chunk-MUWP5SF2.js';
3
- import '../../chunk-RZY5YRGL.js';
3
+ import '../../chunk-2MWO6UVR.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
- import { S as Stage } from './stage-BPw7m9Wx.js';
3
- import { P as Persistence, B as BlobStore, J as JobTransport, E as EventSink, S as Scheduler, C as Clock, a as KernelEventType, K as KernelEvent } from './ports-855bktyD.js';
2
+ import { S as Stage } from './stage-_7BKqqUG.js';
3
+ import { P as Persistence, B as BlobStore, J as JobTransport, E as EventSink, S as Scheduler, C as Clock } from './ports-ChGnJcn2.js';
4
+ import { a as KernelEventType, K as KernelEvent } from './events-D_P24UaY.js';
4
5
 
5
6
  /**
6
7
  * Workflow Builder - Fluent API for composing type-safe workflows
@@ -150,8 +151,8 @@ declare class WorkflowBuilder<TInput extends z.ZodTypeAny, TCurrentOutput extend
150
151
  *
151
152
  * Validates that all declared dependencies exist in the workflow.
152
153
  */
153
- pipe<TStageInput extends z.ZodTypeAny, TStageOutput extends z.ZodTypeAny, TStageConfig extends z.ZodTypeAny, TStageContext extends Record<string, unknown>>(stage: Stage<TStageInput, TStageOutput, TStageConfig, TStageContext>): WorkflowBuilder<TInput, TStageOutput, TContext & {
154
- [x: string]: z.infer<TStageOutput>;
154
+ pipe<TStageInput extends z.ZodTypeAny, TStageOutput extends z.ZodTypeAny, TStageConfig extends z.ZodTypeAny, TStageContext extends Record<string, unknown>, TStageId extends string = string>(stage: Stage<TStageInput, TStageOutput, TStageConfig, TStageContext, TStageId>): WorkflowBuilder<TInput, TStageOutput, TContext & {
155
+ [K in TStageId]: z.infer<TStageOutput>;
155
156
  }>;
156
157
  /**
157
158
  * Add a stage with strict input type checking
@@ -163,7 +164,7 @@ declare class WorkflowBuilder<TInput extends z.ZodTypeAny, TCurrentOutput extend
163
164
  * Add multiple stages that execute in parallel
164
165
  *
165
166
  * All stages receive the same input (current output)
166
- * Their outputs are merged into an object by index AND accumulated in context by stage ID.
167
+ * Their outputs are merged into an object by stage ID and accumulated in context.
167
168
  *
168
169
  * Note: This accepts stages regardless of strict input type matching.
169
170
  * This is necessary because stages using passthrough() can accept objects
@@ -293,6 +294,8 @@ interface JobExecuteResult {
293
294
  readonly output?: unknown;
294
295
  readonly error?: string;
295
296
  readonly nextPollAt?: Date;
297
+ /** True when the job was discarded because the run is no longer RUNNING. */
298
+ readonly ghost?: boolean;
296
299
  }
297
300
  /** Polls suspended stages to check if they can be resumed. */
298
301
  interface StagePollSuspendedCommand {
@@ -431,4 +434,4 @@ interface PluginRunner extends EventSink {
431
434
  declare function definePlugin<T extends KernelEventType>(definition: PluginDefinition<T>): PluginDefinition<T>;
432
435
  declare function createPluginRunner(config: PluginRunnerConfig): PluginRunner;
433
436
 
434
- export { WorkflowBuilder as A, type CommandResult as C, IdempotencyInProgressError as I, type JobExecuteCommand as J, type KernelDeps as K, type LeaseReapStaleCommand as L, type OutboxFlushCommand as O, type PluginDefinition as P, type RunCancelCommand as R, type StagePollSuspendedCommand as S, type WorkflowRegistry as W, type JobExecuteResult as a, type Kernel as b, type KernelCommand as c, type KernelCommandType as d, type KernelConfig as e, type LeaseReapStaleResult as f, type OutboxFlushResult as g, type PluginReplayDLQCommand as h, type PluginReplayDLQResult as i, type PluginRunner as j, type PluginRunnerConfig as k, type RunCancelResult as l, type RunClaimPendingCommand as m, type RunClaimPendingResult as n, type RunCreateCommand as o, type RunCreateResult as p, type RunRerunFromCommand as q, type RunRerunFromResult as r, type RunTransitionCommand as s, type RunTransitionResult as t, type StagePollSuspendedResult as u, createKernel as v, createPluginRunner as w, definePlugin as x, type InferWorkflowStageIds as y, Workflow as z };
437
+ export { WorkflowBuilder as A, type CommandResult as C, IdempotencyInProgressError as I, type JobExecuteCommand as J, type KernelDeps as K, type LeaseReapStaleCommand as L, type OutboxFlushCommand as O, type PluginDefinition as P, type RunCancelCommand as R, type StagePollSuspendedCommand as S, type WorkflowRegistry as W, type JobExecuteResult as a, type Kernel as b, type KernelCommand as c, type KernelCommandType as d, type KernelConfig as e, type LeaseReapStaleResult as f, type OutboxFlushResult as g, type PluginReplayDLQCommand as h, type PluginReplayDLQResult as i, type PluginRunner as j, type PluginRunnerConfig as k, type RunCancelResult as l, type RunClaimPendingCommand as m, type RunClaimPendingResult as n, type RunCreateCommand as o, type RunCreateResult as p, type RunRerunFromCommand as q, type RunRerunFromResult as r, type RunTransitionCommand as s, type RunTransitionResult as t, type StagePollSuspendedResult as u, createKernel as v, createPluginRunner as w, definePlugin as x, Workflow as y, type InferWorkflowStageIds as z };
@@ -1,108 +1,5 @@
1
- import { E as EnqueueJobInput, D as DequeueResult, a as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, S as Status, b as CreateStageInput, c as WorkflowStageRecord, d as UpsertStageInput, e as UpdateStageInput, f as CreateLogInput, C as CreateOutboxEventInput, O as OutboxRecord } from './interface-TsryH4d7.js';
2
-
3
- /**
4
- * Kernel Event Types
5
- *
6
- * Discriminated union of all events emitted by the workflow kernel.
7
- * Each event carries a string literal `type` discriminant, a `timestamp`,
8
- * and a `workflowRunId` that scopes the event to a specific run.
9
- *
10
- * This file contains ONLY types -- no runtime code.
11
- */
12
- /** Emitted when a new workflow run record is created. */
13
- interface WorkflowCreatedEvent {
14
- readonly type: "workflow:created";
15
- readonly timestamp: Date;
16
- readonly workflowRunId: string;
17
- readonly workflowId: string;
18
- }
19
- /** Emitted when a workflow run begins execution. */
20
- interface WorkflowStartedEvent {
21
- readonly type: "workflow:started";
22
- readonly timestamp: Date;
23
- readonly workflowRunId: string;
24
- }
25
- /** Emitted when a workflow run finishes successfully. */
26
- interface WorkflowCompletedEvent {
27
- readonly type: "workflow:completed";
28
- readonly timestamp: Date;
29
- readonly workflowRunId: string;
30
- readonly duration?: number;
31
- readonly totalCost?: number;
32
- readonly totalTokens?: number;
33
- readonly output?: unknown;
34
- }
35
- /** Emitted when a workflow run terminates due to an unrecoverable error. */
36
- interface WorkflowFailedEvent {
37
- readonly type: "workflow:failed";
38
- readonly timestamp: Date;
39
- readonly workflowRunId: string;
40
- readonly error: string;
41
- }
42
- /** Emitted when a workflow run is cancelled by an external request. */
43
- interface WorkflowCancelledEvent {
44
- readonly type: "workflow:cancelled";
45
- readonly timestamp: Date;
46
- readonly workflowRunId: string;
47
- readonly reason?: string;
48
- }
49
- /** Emitted when a workflow run suspends, waiting on an external signal. */
50
- interface WorkflowSuspendedEvent {
51
- readonly type: "workflow:suspended";
52
- readonly timestamp: Date;
53
- readonly workflowRunId: string;
54
- readonly stageId: string;
55
- }
56
- /** Emitted when a stage begins execution. */
57
- interface StageStartedEvent {
58
- readonly type: "stage:started";
59
- readonly timestamp: Date;
60
- readonly workflowRunId: string;
61
- readonly stageId: string;
62
- readonly stageName: string;
63
- readonly stageNumber: number;
64
- }
65
- /** Emitted when a stage completes successfully. */
66
- interface StageCompletedEvent {
67
- readonly type: "stage:completed";
68
- readonly timestamp: Date;
69
- readonly workflowRunId: string;
70
- readonly stageId: string;
71
- readonly stageName: string;
72
- readonly duration: number;
73
- }
74
- /** Emitted when a stage suspends, awaiting a future poll. */
75
- interface StageSuspendedEvent {
76
- readonly type: "stage:suspended";
77
- readonly timestamp: Date;
78
- readonly workflowRunId: string;
79
- readonly stageId: string;
80
- readonly stageName: string;
81
- readonly nextPollAt: Date;
82
- }
83
- /** Emitted when a stage fails with an error. */
84
- interface StageFailedEvent {
85
- readonly type: "stage:failed";
86
- readonly timestamp: Date;
87
- readonly workflowRunId: string;
88
- readonly stageId: string;
89
- readonly stageName: string;
90
- readonly error: string;
91
- }
92
- /** Emitted to report incremental progress within a stage. */
93
- interface StageProgressEvent {
94
- readonly type: "stage:progress";
95
- readonly timestamp: Date;
96
- readonly workflowRunId: string;
97
- readonly stageId: string;
98
- readonly progress: number;
99
- readonly message: string;
100
- readonly details?: Record<string, unknown>;
101
- }
102
- /** Discriminated union of every kernel event. */
103
- type KernelEvent = WorkflowCreatedEvent | WorkflowStartedEvent | WorkflowCompletedEvent | WorkflowFailedEvent | WorkflowCancelledEvent | WorkflowSuspendedEvent | StageStartedEvent | StageCompletedEvent | StageSuspendedEvent | StageFailedEvent | StageProgressEvent;
104
- /** String literal union of all kernel event type discriminants. */
105
- type KernelEventType = KernelEvent["type"];
1
+ import { E as EnqueueJobInput, D as DequeueResult, C as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, S as Status, a as CreateStageInput, b as WorkflowStageRecord, c as UpsertStageInput, d as UpdateStageInput, e as CreateLogInput, f as CreateOutboxEventInput, O as OutboxRecord } from './interface-DCdddCe0.js';
2
+ import { K as KernelEvent } from './events-D_P24UaY.js';
106
3
 
107
4
  /**
108
5
  * Kernel Port Interfaces
@@ -232,6 +129,8 @@ interface JobTransport {
232
129
  }>>;
233
130
  /** Release stale locks (for crashed workers). */
234
131
  releaseStaleJobs(staleThresholdMs?: number): Promise<number>;
132
+ /** Cancel all pending/suspended jobs for a workflow run. Returns count cancelled. */
133
+ cancelByRun(workflowRunId: string): Promise<number>;
235
134
  }
236
135
  /** Event publishing (replaces global EventBus). */
237
136
  interface EventSink {
@@ -243,4 +142,4 @@ interface Scheduler {
243
142
  cancel(commandType: string, correlationId: string): Promise<void>;
244
143
  }
245
144
 
246
- export type { BlobStore as B, Clock as C, EventSink as E, JobTransport as J, KernelEvent as K, Persistence as P, Scheduler as S, WorkflowCancelledEvent as W, KernelEventType as a, StageCompletedEvent as b, StageFailedEvent as c, StageProgressEvent as d, StageStartedEvent as e, StageSuspendedEvent as f, WorkflowCompletedEvent as g, WorkflowCreatedEvent as h, WorkflowFailedEvent as i, WorkflowStartedEvent as j, WorkflowSuspendedEvent as k };
145
+ export type { BlobStore as B, Clock as C, EventSink as E, JobTransport as J, Persistence as P, Scheduler as S };
@@ -120,8 +120,8 @@ interface CheckCompletionContext<TConfig> {
120
120
  log: (level: LogLevel, message: string, meta?: Record<string, unknown>) => void;
121
121
  storage: StageStorage;
122
122
  }
123
- interface Stage<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TConfig extends z.ZodTypeAny, TWorkflowContext = Record<string, unknown>> {
124
- id: string;
123
+ interface Stage<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TConfig extends z.ZodTypeAny, TWorkflowContext = Record<string, unknown>, TId extends string = string> {
124
+ id: TId;
125
125
  name: string;
126
126
  description?: string;
127
127
  /**
@@ -1,4 +1,4 @@
1
- import { A as AICallLogger, g as CreateAICallInput, h as AIHelperStats, i as AICallRecord, J as JobQueue, E as EnqueueJobInput, D as DequeueResult, j as JobRecord, k as JobStatus, l as WorkflowPersistence, a as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, m as WorkflowStatus, b as CreateStageInput, c as WorkflowStageRecord, d as UpsertStageInput, e as UpdateStageInput, n as WorkflowStageStatus, f as CreateLogInput, C as CreateOutboxEventInput, O as OutboxRecord, o as SaveArtifactInput, p as WorkflowArtifactRecord, q as WorkflowLogRecord } from '../interface-TsryH4d7.js';
1
+ import { A as AICallLogger, g as CreateAICallInput, h as AIHelperStats, i as AICallRecord, J as JobQueue, E as EnqueueJobInput, D as DequeueResult, j as JobRecord, k as JobStatus, l as WorkflowPersistence, C as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, m as WorkflowStatus, a as CreateStageInput, b as WorkflowStageRecord, c as UpsertStageInput, d as UpdateStageInput, n as WorkflowStageStatus, e as CreateLogInput, f as CreateOutboxEventInput, O as OutboxRecord, o as SaveArtifactInput, p as WorkflowArtifactRecord, q as WorkflowLogRecord } from '../interface-DCdddCe0.js';
2
2
 
3
3
  /**
4
4
  * In-Memory AI Call Logger
@@ -121,6 +121,7 @@ declare class InMemoryJobQueue implements JobQueue {
121
121
  workflowRunId: string;
122
122
  }>>;
123
123
  releaseStaleJobs(staleThresholdMs?: number): Promise<number>;
124
+ cancelByRun(workflowRunId: string): Promise<number>;
124
125
  /**
125
126
  * Clear all jobs - useful between tests
126
127
  */
@@ -1,4 +1,4 @@
1
- import { StaleVersionError } from '../chunk-RZY5YRGL.js';
1
+ import { StaleVersionError } from '../chunk-2MWO6UVR.js';
2
2
  import { randomUUID } from 'crypto';
3
3
 
4
4
  var InMemoryAICallLogger = class {
@@ -198,7 +198,7 @@ var InMemoryJobQueue = class {
198
198
  lockedAt: null,
199
199
  startedAt: null,
200
200
  completedAt: null,
201
- attempt: 1,
201
+ attempt: 0,
202
202
  maxAttempts: this.defaultMaxAttempts,
203
203
  lastError: null,
204
204
  nextPollAt: options.scheduledFor ?? null,
@@ -229,13 +229,15 @@ var InMemoryJobQueue = class {
229
229
  return null;
230
230
  }
231
231
  const job = pendingJobs[0];
232
+ const newAttempt = job.attempt + 1;
232
233
  const updated = {
233
234
  ...job,
234
235
  status: "RUNNING",
235
236
  workerId: this.workerId,
236
237
  lockedAt: now,
237
238
  startedAt: now,
238
- updatedAt: now
239
+ updatedAt: now,
240
+ attempt: newAttempt
239
241
  };
240
242
  this.jobs.set(job.id, updated);
241
243
  return {
@@ -244,7 +246,7 @@ var InMemoryJobQueue = class {
244
246
  workflowId: job.workflowId,
245
247
  stageId: job.stageId,
246
248
  priority: job.priority,
247
- attempt: job.attempt,
249
+ attempt: newAttempt,
248
250
  maxAttempts: job.maxAttempts,
249
251
  payload: job.payload
250
252
  };
@@ -288,7 +290,6 @@ var InMemoryJobQueue = class {
288
290
  const updated = {
289
291
  ...job,
290
292
  status: "PENDING",
291
- attempt: job.attempt + 1,
292
293
  lastError: error,
293
294
  workerId: null,
294
295
  lockedAt: null,
@@ -335,6 +336,23 @@ var InMemoryJobQueue = class {
335
336
  }
336
337
  return released;
337
338
  }
339
+ async cancelByRun(workflowRunId) {
340
+ const now = /* @__PURE__ */ new Date();
341
+ let count = 0;
342
+ for (const job of this.jobs.values()) {
343
+ if (job.workflowRunId === workflowRunId && (job.status === "PENDING" || job.status === "SUSPENDED")) {
344
+ const updated = {
345
+ ...job,
346
+ status: "CANCELLED",
347
+ completedAt: now,
348
+ updatedAt: now
349
+ };
350
+ this.jobs.set(job.id, updated);
351
+ count++;
352
+ }
353
+ }
354
+ return count;
355
+ }
338
356
  // ============================================================================
339
357
  // Test Helpers
340
358
  // ============================================================================
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 1,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: job.attempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING with incremented attempt\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n attempt: job.attempt + 1,\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 0,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job and increment attempt (matches Prisma dequeue semantics)\n const newAttempt = job.attempt + 1;\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n attempt: newAttempt,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: newAttempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING (attempt was already incremented during dequeue)\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n async cancelByRun(workflowRunId: string): Promise<number> {\n const now = new Date();\n let count = 0;\n for (const job of this.jobs.values()) {\n if (\n job.workflowRunId === workflowRunId &&\n (job.status === \"PENDING\" || job.status === \"SUSPENDED\")\n ) {\n const updated: JobRecord = {\n ...job,\n status: \"CANCELLED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n count++;\n }\n }\n return count;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bratsos/workflow-engine",
3
- "version": "0.5.1",
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",