@bratsos/workflow-engine 0.1.0 → 0.2.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 (37) hide show
  1. package/README.md +270 -513
  2. package/dist/chunk-HL3OJG7W.js +1033 -0
  3. package/dist/chunk-HL3OJG7W.js.map +1 -0
  4. package/dist/{chunk-7IITBLFY.js → chunk-NYKMT46J.js} +268 -25
  5. package/dist/chunk-NYKMT46J.js.map +1 -0
  6. package/dist/chunk-SPXBCZLB.js +17 -0
  7. package/dist/chunk-SPXBCZLB.js.map +1 -0
  8. package/dist/{client-5vz5Vv4A.d.ts → client-D4PoxADF.d.ts} +3 -143
  9. package/dist/client.d.ts +3 -2
  10. package/dist/{index-DmR3E8D7.d.ts → index-DAzCfO1R.d.ts} +20 -1
  11. package/dist/index.d.ts +234 -601
  12. package/dist/index.js +46 -2034
  13. package/dist/index.js.map +1 -1
  14. package/dist/{interface-Cv22wvLG.d.ts → interface-MMqhfQQK.d.ts} +69 -2
  15. package/dist/kernel/index.d.ts +26 -0
  16. package/dist/kernel/index.js +3 -0
  17. package/dist/kernel/index.js.map +1 -0
  18. package/dist/kernel/testing/index.d.ts +44 -0
  19. package/dist/kernel/testing/index.js +85 -0
  20. package/dist/kernel/testing/index.js.map +1 -0
  21. package/dist/persistence/index.d.ts +2 -2
  22. package/dist/persistence/index.js +2 -1
  23. package/dist/persistence/prisma/index.d.ts +2 -2
  24. package/dist/persistence/prisma/index.js +2 -1
  25. package/dist/plugins-BCnDUwIc.d.ts +415 -0
  26. package/dist/ports-tU3rzPXJ.d.ts +245 -0
  27. package/dist/stage-BPw7m9Wx.d.ts +144 -0
  28. package/dist/testing/index.d.ts +23 -1
  29. package/dist/testing/index.js +156 -13
  30. package/dist/testing/index.js.map +1 -1
  31. package/package.json +11 -1
  32. package/skills/workflow-engine/SKILL.md +234 -348
  33. package/skills/workflow-engine/references/03-runtime-setup.md +111 -426
  34. package/skills/workflow-engine/references/05-persistence-setup.md +32 -0
  35. package/skills/workflow-engine/references/07-testing-patterns.md +141 -474
  36. package/skills/workflow-engine/references/08-common-patterns.md +118 -431
  37. package/dist/chunk-7IITBLFY.js.map +0 -1
@@ -30,10 +30,18 @@ type WorkflowStageStatus = Status;
30
30
  type JobStatus = Status;
31
31
  type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR";
32
32
  type ArtifactType = "STAGE_OUTPUT" | "ARTIFACT" | "METADATA";
33
+ declare class StaleVersionError extends Error {
34
+ readonly entity: string;
35
+ readonly id: string;
36
+ readonly expected: number;
37
+ readonly actual: number;
38
+ constructor(entity: string, id: string, expected: number, actual: number);
39
+ }
33
40
  interface WorkflowRunRecord {
34
41
  id: string;
35
42
  createdAt: Date;
36
43
  updatedAt: Date;
44
+ version: number;
37
45
  workflowId: string;
38
46
  workflowName: string;
39
47
  workflowType: string;
@@ -52,6 +60,7 @@ interface WorkflowStageRecord {
52
60
  id: string;
53
61
  createdAt: Date;
54
62
  updatedAt: Date;
63
+ version: number;
55
64
  workflowRunId: string;
56
65
  stageId: string;
57
66
  stageName: string;
@@ -94,6 +103,31 @@ interface WorkflowArtifactRecord {
94
103
  size: number;
95
104
  metadata: unknown | null;
96
105
  }
106
+ interface OutboxRecord {
107
+ id: string;
108
+ workflowRunId: string;
109
+ sequence: number;
110
+ eventType: string;
111
+ payload: unknown;
112
+ causationId: string;
113
+ occurredAt: Date;
114
+ publishedAt: Date | null;
115
+ retryCount: number;
116
+ dlqAt: Date | null;
117
+ }
118
+ interface CreateOutboxEventInput {
119
+ workflowRunId: string;
120
+ eventType: string;
121
+ payload: unknown;
122
+ causationId: string;
123
+ occurredAt: Date;
124
+ }
125
+ interface IdempotencyRecord {
126
+ key: string;
127
+ commandType: string;
128
+ result: unknown;
129
+ createdAt: Date;
130
+ }
97
131
  interface AICallRecord {
98
132
  id: string;
99
133
  createdAt: Date;
@@ -113,6 +147,7 @@ interface JobRecord {
113
147
  createdAt: Date;
114
148
  updatedAt: Date;
115
149
  workflowRunId: string;
150
+ workflowId: string;
116
151
  stageId: string;
117
152
  status: JobStatus;
118
153
  priority: number;
@@ -140,11 +175,12 @@ interface CreateRunInput {
140
175
  interface UpdateRunInput {
141
176
  status?: WorkflowStatus;
142
177
  startedAt?: Date;
143
- completedAt?: Date;
178
+ completedAt?: Date | null;
144
179
  duration?: number;
145
180
  output?: unknown;
146
181
  totalCost?: number;
147
182
  totalTokens?: number;
183
+ expectedVersion?: number;
148
184
  }
149
185
  interface CreateStageInput {
150
186
  workflowRunId: string;
@@ -173,6 +209,7 @@ interface UpdateStageInput {
173
209
  embeddingInfo?: unknown;
174
210
  artifacts?: unknown;
175
211
  errorMessage?: string;
212
+ expectedVersion?: number;
176
213
  }
177
214
  interface UpsertStageInput {
178
215
  workflowRunId: string;
@@ -210,6 +247,7 @@ interface CreateAICallInput {
210
247
  }
211
248
  interface EnqueueJobInput {
212
249
  workflowRunId: string;
250
+ workflowId: string;
213
251
  stageId: string;
214
252
  priority?: number;
215
253
  payload?: Record<string, unknown>;
@@ -218,12 +256,16 @@ interface EnqueueJobInput {
218
256
  interface DequeueResult {
219
257
  jobId: string;
220
258
  workflowRunId: string;
259
+ workflowId: string;
221
260
  stageId: string;
222
261
  priority: number;
223
262
  attempt: number;
263
+ maxAttempts: number;
224
264
  payload: Record<string, unknown>;
225
265
  }
226
266
  interface WorkflowPersistence {
267
+ /** Execute operations within a transaction boundary. */
268
+ withTransaction<T>(fn: (tx: WorkflowPersistence) => Promise<T>): Promise<T>;
227
269
  createRun(data: CreateRunInput): Promise<WorkflowRunRecord>;
228
270
  updateRun(id: string, data: UpdateRunInput): Promise<void>;
229
271
  getRun(id: string): Promise<WorkflowRunRecord | null>;
@@ -271,6 +313,31 @@ interface WorkflowPersistence {
271
313
  listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]>;
272
314
  getStageIdForArtifact(runId: string, stageId: string): Promise<string | null>;
273
315
  saveStageOutput(runId: string, workflowType: string, stageId: string, output: unknown): Promise<string>;
316
+ /** Increment retry count for a failed outbox event. Returns new count. */
317
+ incrementOutboxRetryCount(id: string): Promise<number>;
318
+ /** Move an outbox event to DLQ (sets dlqAt). */
319
+ moveOutboxEventToDLQ(id: string): Promise<void>;
320
+ /** Reset DLQ events so they can be reprocessed by outbox.flush. Returns count reset. */
321
+ replayDLQEvents(maxEvents: number): Promise<number>;
322
+ /** Write events to the outbox. Sequences are auto-assigned per workflowRunId. */
323
+ appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void>;
324
+ /** Read unpublished events ordered by (workflowRunId, sequence). */
325
+ getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]>;
326
+ /** Mark events as published. */
327
+ markOutboxEventsPublished(ids: string[]): Promise<void>;
328
+ /** Atomically acquire an idempotency key for command execution. */
329
+ acquireIdempotencyKey(key: string, commandType: string): Promise<{
330
+ status: "acquired";
331
+ } | {
332
+ status: "replay";
333
+ result: unknown;
334
+ } | {
335
+ status: "in_progress";
336
+ }>;
337
+ /** Mark an idempotency key as completed and cache the command result. */
338
+ completeIdempotencyKey(key: string, commandType: string, result: unknown): Promise<void>;
339
+ /** Release an in-progress idempotency key after command failure. */
340
+ releaseIdempotencyKey(key: string, commandType: string): Promise<void>;
274
341
  }
275
342
  interface AIHelperStats {
276
343
  totalCalls: number;
@@ -341,4 +408,4 @@ interface JobQueue {
341
408
  releaseStaleJobs(staleThresholdMs?: number): Promise<number>;
342
409
  }
343
410
 
344
- export type { AICallLogger as A, CreateAICallInput as C, DequeueResult as D, EnqueueJobInput as E, JobQueue as J, LogLevel as L, SaveArtifactInput as S, UpdateRunInput as U, WorkflowPersistence as W, AIHelperStats as a, AICallRecord as b, JobRecord as c, JobStatus as d, CreateRunInput as e, WorkflowRunRecord as f, WorkflowStatus as g, CreateStageInput as h, WorkflowStageRecord as i, UpsertStageInput as j, UpdateStageInput as k, WorkflowStageStatus as l, CreateLogInput as m, WorkflowArtifactRecord as n, WorkflowLogRecord as o, ArtifactType as p, Status as q };
411
+ export { type AICallLogger as A, type CreateOutboxEventInput as C, type DequeueResult as D, type EnqueueJobInput as E, type IdempotencyRecord as I, type JobQueue as J, type LogLevel as L, type OutboxRecord as O, type Status as S, type UpdateRunInput as U, type WorkflowRunRecord as W, type CreateRunInput as a, type CreateStageInput as b, type WorkflowStageRecord as c, type UpsertStageInput as d, type UpdateStageInput as e, type CreateLogInput as f, type CreateAICallInput as g, type AIHelperStats as h, type AICallRecord as i, type JobRecord as j, type JobStatus as k, type WorkflowPersistence as l, type WorkflowStatus as m, type WorkflowStageStatus as n, type SaveArtifactInput as o, type WorkflowArtifactRecord as p, type WorkflowLogRecord as q, type ArtifactType as r, StaleVersionError as s };
@@ -0,0 +1,26 @@
1
+ import { K as KernelDeps } from '../plugins-BCnDUwIc.js';
2
+ export { C as CommandResult, I as IdempotencyInProgressError, J as JobExecuteCommand, a as JobExecuteResult, b as Kernel, c as KernelCommand, d as KernelCommandType, e as KernelConfig, L as LeaseReapStaleCommand, f as LeaseReapStaleResult, O as OutboxFlushCommand, g as OutboxFlushResult, P as PluginDefinition, h as PluginReplayDLQCommand, i as PluginReplayDLQResult, j as PluginRunner, k as PluginRunnerConfig, R as RunCancelCommand, l as RunCancelResult, m as RunClaimPendingCommand, n as RunClaimPendingResult, o as RunCreateCommand, p as RunCreateResult, q as RunRerunFromCommand, r as RunRerunFromResult, s as RunTransitionCommand, t as RunTransitionResult, S as StagePollSuspendedCommand, u as StagePollSuspendedResult, W as WorkflowRegistry, v as createKernel, w as createPluginRunner, x as definePlugin } from '../plugins-BCnDUwIc.js';
3
+ export { B as BlobStore, C as Clock, E as EventSink, J as JobTransport, K as KernelEvent, a as KernelEventType, P as Persistence, S as Scheduler, b as StageCompletedEvent, c as StageFailedEvent, d as StageProgressEvent, e as StageStartedEvent, f as StageSuspendedEvent, W as WorkflowCancelledEvent, g as WorkflowCompletedEvent, h as WorkflowCreatedEvent, i as WorkflowFailedEvent, j as WorkflowStartedEvent, k as WorkflowSuspendedEvent } from '../ports-tU3rzPXJ.js';
4
+ export { C as CreateOutboxEventInput, I as IdempotencyRecord, O as OutboxRecord } from '../interface-MMqhfQQK.js';
5
+ import 'zod';
6
+ import '../stage-BPw7m9Wx.js';
7
+
8
+ /**
9
+ * Load workflow context from completed stages.
10
+ *
11
+ * For each completed stage, loads the output from BlobStore using
12
+ * the _artifactKey stored in stage.outputData.
13
+ */
14
+
15
+ declare function loadWorkflowContext(workflowRunId: string, deps: KernelDeps): Promise<Record<string, unknown>>;
16
+
17
+ /**
18
+ * Save stage output to BlobStore and return the blob key.
19
+ *
20
+ * The key is stored in stage.outputData._artifactKey so that
21
+ * loadWorkflowContext() can retrieve it later.
22
+ */
23
+
24
+ declare function saveStageOutput(runId: string, workflowType: string, stageId: string, output: unknown, deps: KernelDeps): Promise<string>;
25
+
26
+ export { loadWorkflowContext, saveStageOutput };
@@ -0,0 +1,3 @@
1
+ export { IdempotencyInProgressError, createKernel, createPluginRunner, definePlugin, loadWorkflowContext, saveStageOutput } from '../chunk-HL3OJG7W.js';
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,44 @@
1
+ import { E as EventSink, K as KernelEvent, a as KernelEventType, C as Clock, B as BlobStore, S as Scheduler } from '../../ports-tU3rzPXJ.js';
2
+ import '../../interface-MMqhfQQK.js';
3
+
4
+ declare class CollectingEventSink implements EventSink {
5
+ readonly events: KernelEvent[];
6
+ emit(event: KernelEvent): Promise<void>;
7
+ getByType<T extends KernelEventType>(type: T): Extract<KernelEvent, {
8
+ type: T;
9
+ }>[];
10
+ clear(): void;
11
+ get length(): number;
12
+ }
13
+
14
+ declare class FakeClock implements Clock {
15
+ private currentTime;
16
+ constructor(initialTime?: Date);
17
+ now(): Date;
18
+ advance(ms: number): void;
19
+ set(time: Date): void;
20
+ }
21
+
22
+ declare class InMemoryBlobStore implements BlobStore {
23
+ private store;
24
+ put(key: string, data: unknown): Promise<void>;
25
+ get(key: string): Promise<unknown>;
26
+ has(key: string): Promise<boolean>;
27
+ delete(key: string): Promise<void>;
28
+ list(prefix: string): Promise<string[]>;
29
+ clear(): void;
30
+ size(): number;
31
+ }
32
+
33
+ declare class NoopScheduler implements Scheduler {
34
+ readonly scheduled: Array<{
35
+ commandType: string;
36
+ payload: unknown;
37
+ runAt: Date;
38
+ }>;
39
+ schedule(commandType: string, payload: unknown, runAt: Date): Promise<void>;
40
+ cancel(_commandType: string, _correlationId: string): Promise<void>;
41
+ clear(): void;
42
+ }
43
+
44
+ export { CollectingEventSink, FakeClock, InMemoryBlobStore, NoopScheduler };
@@ -0,0 +1,85 @@
1
+ // src/kernel/testing/collecting-event-sink.ts
2
+ var CollectingEventSink = class {
3
+ events = [];
4
+ async emit(event) {
5
+ this.events.push(event);
6
+ }
7
+ getByType(type) {
8
+ return this.events.filter(
9
+ (e) => e.type === type
10
+ );
11
+ }
12
+ clear() {
13
+ this.events.length = 0;
14
+ }
15
+ get length() {
16
+ return this.events.length;
17
+ }
18
+ };
19
+
20
+ // src/kernel/testing/fake-clock.ts
21
+ var FakeClock = class {
22
+ currentTime;
23
+ constructor(initialTime) {
24
+ this.currentTime = initialTime ?? /* @__PURE__ */ new Date("2025-01-01T00:00:00Z");
25
+ }
26
+ now() {
27
+ return new Date(this.currentTime.getTime());
28
+ }
29
+ advance(ms) {
30
+ this.currentTime = new Date(this.currentTime.getTime() + ms);
31
+ }
32
+ set(time) {
33
+ this.currentTime = new Date(time.getTime());
34
+ }
35
+ };
36
+
37
+ // src/kernel/testing/in-memory-blob-store.ts
38
+ function deepClone(value) {
39
+ return JSON.parse(JSON.stringify(value));
40
+ }
41
+ var InMemoryBlobStore = class {
42
+ store = /* @__PURE__ */ new Map();
43
+ async put(key, data) {
44
+ this.store.set(key, deepClone(data));
45
+ }
46
+ async get(key) {
47
+ if (!this.store.has(key)) {
48
+ throw new Error(`Blob not found: ${key}`);
49
+ }
50
+ return deepClone(this.store.get(key));
51
+ }
52
+ async has(key) {
53
+ return this.store.has(key);
54
+ }
55
+ async delete(key) {
56
+ this.store.delete(key);
57
+ }
58
+ async list(prefix) {
59
+ return [...this.store.keys()].filter((k) => k.startsWith(prefix));
60
+ }
61
+ // Test helpers
62
+ clear() {
63
+ this.store.clear();
64
+ }
65
+ size() {
66
+ return this.store.size;
67
+ }
68
+ };
69
+
70
+ // src/kernel/testing/noop-scheduler.ts
71
+ var NoopScheduler = class {
72
+ scheduled = [];
73
+ async schedule(commandType, payload, runAt) {
74
+ this.scheduled.push({ commandType, payload, runAt });
75
+ }
76
+ async cancel(_commandType, _correlationId) {
77
+ }
78
+ clear() {
79
+ this.scheduled.length = 0;
80
+ }
81
+ };
82
+
83
+ export { CollectingEventSink, FakeClock, InMemoryBlobStore, NoopScheduler };
84
+ //# sourceMappingURL=index.js.map
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/kernel/testing/collecting-event-sink.ts","../../../src/kernel/testing/fake-clock.ts","../../../src/kernel/testing/in-memory-blob-store.ts","../../../src/kernel/testing/noop-scheduler.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { KernelEvent, KernelEventType } from \"../events\";\nimport type { EventSink } from \"../ports\";\n\nexport class CollectingEventSink implements EventSink {\n readonly events: KernelEvent[] = [];\n\n async emit(event: KernelEvent): Promise<void> {\n this.events.push(event);\n }\n\n getByType<T extends KernelEventType>(\n type: T,\n ): Extract<KernelEvent, { type: T }>[] {\n return this.events.filter(\n (e): e is Extract<KernelEvent, { type: T }> => e.type === type,\n );\n }\n\n clear(): void {\n this.events.length = 0;\n }\n\n get length(): number {\n return this.events.length;\n }\n}\n","import type { Clock } from \"../ports\";\n\nexport class FakeClock implements Clock {\n private currentTime: Date;\n\n constructor(initialTime?: Date) {\n this.currentTime = initialTime ?? new Date(\"2025-01-01T00:00:00Z\");\n }\n\n now(): Date {\n return new Date(this.currentTime.getTime());\n }\n\n advance(ms: number): void {\n this.currentTime = new Date(this.currentTime.getTime() + ms);\n }\n\n set(time: Date): void {\n this.currentTime = new Date(time.getTime());\n }\n}\n","import type { BlobStore } from \"../ports\";\n\nfunction deepClone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nexport class InMemoryBlobStore implements BlobStore {\n private store = new Map<string, unknown>();\n\n async put(key: string, data: unknown): Promise<void> {\n this.store.set(key, deepClone(data));\n }\n\n async get(key: string): Promise<unknown> {\n if (!this.store.has(key)) {\n throw new Error(`Blob not found: ${key}`);\n }\n return deepClone(this.store.get(key));\n }\n\n async has(key: string): Promise<boolean> {\n return this.store.has(key);\n }\n\n async delete(key: string): Promise<void> {\n this.store.delete(key);\n }\n\n async list(prefix: string): Promise<string[]> {\n return [...this.store.keys()].filter((k) => k.startsWith(prefix));\n }\n\n // Test helpers\n clear(): void {\n this.store.clear();\n }\n\n size(): number {\n return this.store.size;\n }\n}\n","import type { Scheduler } from \"../ports\";\n\nexport class NoopScheduler implements Scheduler {\n readonly scheduled: Array<{\n commandType: string;\n payload: unknown;\n runAt: Date;\n }> = [];\n\n async schedule(\n commandType: string,\n payload: unknown,\n runAt: Date,\n ): Promise<void> {\n this.scheduled.push({ commandType, payload, runAt });\n }\n\n async cancel(_commandType: string, _correlationId: string): Promise<void> {\n // No-op in Phase 1\n }\n\n clear(): void {\n this.scheduled.length = 0;\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- export { A as AICallLogger, b as AICallRecord, a as AIHelperStats, p as ArtifactType, C as CreateAICallInput, m as CreateLogInput, e as CreateRunInput, h as CreateStageInput, D as DequeueResult, E as EnqueueJobInput, J as JobQueue, c as JobRecord, d as JobStatus, L as LogLevel, S as SaveArtifactInput, q as Status, U as UpdateRunInput, k as UpdateStageInput, j as UpsertStageInput, n as WorkflowArtifactRecord, o as WorkflowLogRecord, W as WorkflowPersistence, f as WorkflowRunRecord, i as WorkflowStageRecord, l as WorkflowStageStatus, g as WorkflowStatus } from '../interface-Cv22wvLG.js';
2
- export { P as PrismaAICallLogger, a as PrismaJobQueue, c as PrismaWorkflowPersistence, e as createPrismaAICallLogger, f as createPrismaJobQueue, g as createPrismaWorkflowPersistence } from '../index-DmR3E8D7.js';
1
+ export { A as AICallLogger, i as AICallRecord, h as AIHelperStats, r as ArtifactType, g as CreateAICallInput, f as CreateLogInput, a as CreateRunInput, b as CreateStageInput, D as DequeueResult, E as EnqueueJobInput, J as JobQueue, j as JobRecord, k as JobStatus, L as LogLevel, o as SaveArtifactInput, S as Status, U as UpdateRunInput, e as UpdateStageInput, d as UpsertStageInput, p as WorkflowArtifactRecord, q as WorkflowLogRecord, l as WorkflowPersistence, W as WorkflowRunRecord, c as WorkflowStageRecord, n as WorkflowStageStatus, m as WorkflowStatus } from '../interface-MMqhfQQK.js';
2
+ export { P as PrismaAICallLogger, a as PrismaJobQueue, c as PrismaWorkflowPersistence, e as createPrismaAICallLogger, f as createPrismaJobQueue, g as createPrismaWorkflowPersistence } from '../index-DAzCfO1R.js';
@@ -1,5 +1,6 @@
1
1
  import '../chunk-D7RVRRM2.js';
2
- export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../chunk-7IITBLFY.js';
2
+ export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../chunk-NYKMT46J.js';
3
3
  import '../chunk-MUWP5SF2.js';
4
+ import '../chunk-SPXBCZLB.js';
4
5
  //# sourceMappingURL=index.js.map
5
6
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
- export { D as DatabaseType, P as PrismaAICallLogger, a as PrismaJobQueue, b as PrismaJobQueueOptions, c as PrismaWorkflowPersistence, d as PrismaWorkflowPersistenceOptions, e as createPrismaAICallLogger, f as createPrismaJobQueue, g as createPrismaWorkflowPersistence } from '../../index-DmR3E8D7.js';
2
- import '../../interface-Cv22wvLG.js';
1
+ export { D as DatabaseType, P as PrismaAICallLogger, a as PrismaJobQueue, b as PrismaJobQueueOptions, c as PrismaWorkflowPersistence, d as PrismaWorkflowPersistenceOptions, e as createPrismaAICallLogger, f as createPrismaJobQueue, g as createPrismaWorkflowPersistence } from '../../index-DAzCfO1R.js';
2
+ import '../../interface-MMqhfQQK.js';
3
3
 
4
4
  /**
5
5
  * Prisma Enum Compatibility Layer
@@ -1,4 +1,5 @@
1
- export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createEnumHelper, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../../chunk-7IITBLFY.js';
1
+ export { PrismaAICallLogger, PrismaJobQueue, PrismaWorkflowPersistence, createEnumHelper, createPrismaAICallLogger, createPrismaJobQueue, createPrismaWorkflowPersistence } from '../../chunk-NYKMT46J.js';
2
2
  import '../../chunk-MUWP5SF2.js';
3
+ import '../../chunk-SPXBCZLB.js';
3
4
  //# sourceMappingURL=index.js.map
4
5
  //# sourceMappingURL=index.js.map