@cogitator-ai/workflows 0.1.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 (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/builder.d.ts +39 -0
  4. package/dist/builder.d.ts.map +1 -0
  5. package/dist/builder.js +224 -0
  6. package/dist/builder.js.map +1 -0
  7. package/dist/checkpoint.d.ts +33 -0
  8. package/dist/checkpoint.d.ts.map +1 -0
  9. package/dist/checkpoint.js +108 -0
  10. package/dist/checkpoint.js.map +1 -0
  11. package/dist/executor.d.ts +24 -0
  12. package/dist/executor.d.ts.map +1 -0
  13. package/dist/executor.js +207 -0
  14. package/dist/executor.js.map +1 -0
  15. package/dist/human/approval-store.d.ts +95 -0
  16. package/dist/human/approval-store.d.ts.map +1 -0
  17. package/dist/human/approval-store.js +377 -0
  18. package/dist/human/approval-store.js.map +1 -0
  19. package/dist/human/human-node.d.ts +104 -0
  20. package/dist/human/human-node.d.ts.map +1 -0
  21. package/dist/human/human-node.js +342 -0
  22. package/dist/human/human-node.js.map +1 -0
  23. package/dist/human/index.d.ts +17 -0
  24. package/dist/human/index.d.ts.map +1 -0
  25. package/dist/human/index.js +17 -0
  26. package/dist/human/index.js.map +1 -0
  27. package/dist/human/notifiers.d.ts +85 -0
  28. package/dist/human/notifiers.d.ts.map +1 -0
  29. package/dist/human/notifiers.js +289 -0
  30. package/dist/human/notifiers.js.map +1 -0
  31. package/dist/index.d.ts +32 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +19 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/manager/index.d.ts +19 -0
  36. package/dist/manager/index.d.ts.map +1 -0
  37. package/dist/manager/index.js +17 -0
  38. package/dist/manager/index.js.map +1 -0
  39. package/dist/manager/run-store.d.ts +78 -0
  40. package/dist/manager/run-store.d.ts.map +1 -0
  41. package/dist/manager/run-store.js +390 -0
  42. package/dist/manager/run-store.js.map +1 -0
  43. package/dist/manager/scheduler.d.ts +159 -0
  44. package/dist/manager/scheduler.d.ts.map +1 -0
  45. package/dist/manager/scheduler.js +355 -0
  46. package/dist/manager/scheduler.js.map +1 -0
  47. package/dist/manager/workflow-manager.d.ts +114 -0
  48. package/dist/manager/workflow-manager.d.ts.map +1 -0
  49. package/dist/manager/workflow-manager.js +460 -0
  50. package/dist/manager/workflow-manager.js.map +1 -0
  51. package/dist/nodes/agent.d.ts +24 -0
  52. package/dist/nodes/agent.d.ts.map +1 -0
  53. package/dist/nodes/agent.js +37 -0
  54. package/dist/nodes/agent.js.map +1 -0
  55. package/dist/nodes/base.d.ts +12 -0
  56. package/dist/nodes/base.d.ts.map +1 -0
  57. package/dist/nodes/base.js +5 -0
  58. package/dist/nodes/base.js.map +1 -0
  59. package/dist/nodes/function.d.ts +27 -0
  60. package/dist/nodes/function.d.ts.map +1 -0
  61. package/dist/nodes/function.js +29 -0
  62. package/dist/nodes/function.js.map +1 -0
  63. package/dist/nodes/index.d.ts +8 -0
  64. package/dist/nodes/index.d.ts.map +1 -0
  65. package/dist/nodes/index.js +8 -0
  66. package/dist/nodes/index.js.map +1 -0
  67. package/dist/nodes/tool.d.ts +19 -0
  68. package/dist/nodes/tool.d.ts.map +1 -0
  69. package/dist/nodes/tool.js +26 -0
  70. package/dist/nodes/tool.js.map +1 -0
  71. package/dist/observability/exporters.d.ts +93 -0
  72. package/dist/observability/exporters.d.ts.map +1 -0
  73. package/dist/observability/exporters.js +330 -0
  74. package/dist/observability/exporters.js.map +1 -0
  75. package/dist/observability/index.d.ts +17 -0
  76. package/dist/observability/index.d.ts.map +1 -0
  77. package/dist/observability/index.js +17 -0
  78. package/dist/observability/index.js.map +1 -0
  79. package/dist/observability/metrics.d.ts +114 -0
  80. package/dist/observability/metrics.d.ts.map +1 -0
  81. package/dist/observability/metrics.js +435 -0
  82. package/dist/observability/metrics.js.map +1 -0
  83. package/dist/observability/span-attributes.d.ts +95 -0
  84. package/dist/observability/span-attributes.d.ts.map +1 -0
  85. package/dist/observability/span-attributes.js +142 -0
  86. package/dist/observability/span-attributes.js.map +1 -0
  87. package/dist/observability/tracer.d.ts +110 -0
  88. package/dist/observability/tracer.d.ts.map +1 -0
  89. package/dist/observability/tracer.js +409 -0
  90. package/dist/observability/tracer.js.map +1 -0
  91. package/dist/patterns/index.d.ts +15 -0
  92. package/dist/patterns/index.d.ts.map +1 -0
  93. package/dist/patterns/index.js +15 -0
  94. package/dist/patterns/index.js.map +1 -0
  95. package/dist/patterns/map-reduce.d.ts +223 -0
  96. package/dist/patterns/map-reduce.d.ts.map +1 -0
  97. package/dist/patterns/map-reduce.js +378 -0
  98. package/dist/patterns/map-reduce.js.map +1 -0
  99. package/dist/saga/circuit-breaker.d.ts +153 -0
  100. package/dist/saga/circuit-breaker.d.ts.map +1 -0
  101. package/dist/saga/circuit-breaker.js +306 -0
  102. package/dist/saga/circuit-breaker.js.map +1 -0
  103. package/dist/saga/compensation.d.ts +134 -0
  104. package/dist/saga/compensation.d.ts.map +1 -0
  105. package/dist/saga/compensation.js +240 -0
  106. package/dist/saga/compensation.js.map +1 -0
  107. package/dist/saga/dead-letter.d.ts +113 -0
  108. package/dist/saga/dead-letter.d.ts.map +1 -0
  109. package/dist/saga/dead-letter.js +307 -0
  110. package/dist/saga/dead-letter.js.map +1 -0
  111. package/dist/saga/idempotency.d.ts +95 -0
  112. package/dist/saga/idempotency.d.ts.map +1 -0
  113. package/dist/saga/idempotency.js +266 -0
  114. package/dist/saga/idempotency.js.map +1 -0
  115. package/dist/saga/index.d.ts +16 -0
  116. package/dist/saga/index.d.ts.map +1 -0
  117. package/dist/saga/index.js +16 -0
  118. package/dist/saga/index.js.map +1 -0
  119. package/dist/saga/retry.d.ts +59 -0
  120. package/dist/saga/retry.d.ts.map +1 -0
  121. package/dist/saga/retry.js +222 -0
  122. package/dist/saga/retry.js.map +1 -0
  123. package/dist/scheduler.d.ts +37 -0
  124. package/dist/scheduler.d.ts.map +1 -0
  125. package/dist/scheduler.js +151 -0
  126. package/dist/scheduler.js.map +1 -0
  127. package/dist/subworkflows/index.d.ts +16 -0
  128. package/dist/subworkflows/index.d.ts.map +1 -0
  129. package/dist/subworkflows/index.js +16 -0
  130. package/dist/subworkflows/index.js.map +1 -0
  131. package/dist/subworkflows/parallel-subworkflows.d.ts +139 -0
  132. package/dist/subworkflows/parallel-subworkflows.d.ts.map +1 -0
  133. package/dist/subworkflows/parallel-subworkflows.js +270 -0
  134. package/dist/subworkflows/parallel-subworkflows.js.map +1 -0
  135. package/dist/subworkflows/subworkflow-node.d.ts +136 -0
  136. package/dist/subworkflows/subworkflow-node.d.ts.map +1 -0
  137. package/dist/subworkflows/subworkflow-node.js +164 -0
  138. package/dist/subworkflows/subworkflow-node.js.map +1 -0
  139. package/dist/timers/cron-parser.d.ts +110 -0
  140. package/dist/timers/cron-parser.d.ts.map +1 -0
  141. package/dist/timers/cron-parser.js +412 -0
  142. package/dist/timers/cron-parser.js.map +1 -0
  143. package/dist/timers/index.d.ts +18 -0
  144. package/dist/timers/index.d.ts.map +1 -0
  145. package/dist/timers/index.js +18 -0
  146. package/dist/timers/index.js.map +1 -0
  147. package/dist/timers/timer-manager.d.ts +219 -0
  148. package/dist/timers/timer-manager.d.ts.map +1 -0
  149. package/dist/timers/timer-manager.js +351 -0
  150. package/dist/timers/timer-manager.js.map +1 -0
  151. package/dist/timers/timer-node.d.ts +144 -0
  152. package/dist/timers/timer-node.d.ts.map +1 -0
  153. package/dist/timers/timer-node.js +246 -0
  154. package/dist/timers/timer-node.js.map +1 -0
  155. package/dist/timers/timer-store.d.ts +90 -0
  156. package/dist/timers/timer-store.d.ts.map +1 -0
  157. package/dist/timers/timer-store.js +357 -0
  158. package/dist/timers/timer-store.js.map +1 -0
  159. package/dist/triggers/cron-trigger.d.ts +102 -0
  160. package/dist/triggers/cron-trigger.d.ts.map +1 -0
  161. package/dist/triggers/cron-trigger.js +309 -0
  162. package/dist/triggers/cron-trigger.js.map +1 -0
  163. package/dist/triggers/index.d.ts +14 -0
  164. package/dist/triggers/index.d.ts.map +1 -0
  165. package/dist/triggers/index.js +10 -0
  166. package/dist/triggers/index.js.map +1 -0
  167. package/dist/triggers/rate-limiter.d.ts +130 -0
  168. package/dist/triggers/rate-limiter.d.ts.map +1 -0
  169. package/dist/triggers/rate-limiter.js +294 -0
  170. package/dist/triggers/rate-limiter.js.map +1 -0
  171. package/dist/triggers/trigger-manager.d.ts +166 -0
  172. package/dist/triggers/trigger-manager.d.ts.map +1 -0
  173. package/dist/triggers/trigger-manager.js +436 -0
  174. package/dist/triggers/trigger-manager.js.map +1 -0
  175. package/dist/triggers/webhook-trigger.d.ts +150 -0
  176. package/dist/triggers/webhook-trigger.d.ts.map +1 -0
  177. package/dist/triggers/webhook-trigger.js +452 -0
  178. package/dist/triggers/webhook-trigger.js.map +1 -0
  179. package/package.json +44 -0
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Compensation Manager for Saga pattern
3
+ *
4
+ * Features:
5
+ * - Automatic compensation on failure
6
+ * - Reverse-order execution
7
+ * - Partial compensation (only completed steps)
8
+ * - Compensation condition checking
9
+ * - Compensation result tracking
10
+ */
11
+ /**
12
+ * Compensation Manager class
13
+ */
14
+ export class CompensationManager {
15
+ steps = new Map();
16
+ completedNodes = new Map();
17
+ executionOrder = [];
18
+ /**
19
+ * Register a compensation step for a node
20
+ */
21
+ registerCompensation(nodeId, compensationFn, options = {}) {
22
+ this.steps.set(nodeId, {
23
+ nodeId,
24
+ compensationFn,
25
+ condition: options.condition,
26
+ order: options.order ?? 'reverse',
27
+ timeout: options.timeout,
28
+ retries: options.retries ?? 0,
29
+ });
30
+ }
31
+ /**
32
+ * Register compensation from config
33
+ */
34
+ registerFromConfig(nodeId, config) {
35
+ if (!config.compensate)
36
+ return;
37
+ this.registerCompensation(nodeId, config.compensate, {
38
+ condition: config.compensateCondition,
39
+ order: config.compensateOrder,
40
+ });
41
+ }
42
+ /**
43
+ * Mark a node as completed with its result
44
+ */
45
+ markCompleted(nodeId, result) {
46
+ this.completedNodes.set(nodeId, result);
47
+ this.executionOrder.push(nodeId);
48
+ }
49
+ /**
50
+ * Clear a node's completion status (for retries)
51
+ */
52
+ clearCompleted(nodeId) {
53
+ this.completedNodes.delete(nodeId);
54
+ const idx = this.executionOrder.indexOf(nodeId);
55
+ if (idx !== -1) {
56
+ this.executionOrder.splice(idx, 1);
57
+ }
58
+ }
59
+ /**
60
+ * Check if a node has a compensation step
61
+ */
62
+ hasCompensation(nodeId) {
63
+ return this.steps.has(nodeId);
64
+ }
65
+ /**
66
+ * Get nodes that need compensation (completed nodes with compensation steps)
67
+ */
68
+ getCompensableNodes() {
69
+ return this.executionOrder.filter((nodeId) => this.steps.has(nodeId) && this.completedNodes.has(nodeId));
70
+ }
71
+ /**
72
+ * Execute compensation for all completed nodes
73
+ */
74
+ async compensate(state, failedNodeId, error) {
75
+ const startTime = Date.now();
76
+ const compensated = [];
77
+ const partialFailures = [];
78
+ const nodesToCompensate = this.getCompensableNodes();
79
+ const sortedNodes = this.sortByCompensationOrder(nodesToCompensate);
80
+ for (const nodeId of sortedNodes) {
81
+ const step = this.steps.get(nodeId);
82
+ const originalResult = this.completedNodes.get(nodeId);
83
+ const stepStart = Date.now();
84
+ if (step.condition && !step.condition(state, error)) {
85
+ compensated.push({
86
+ nodeId,
87
+ success: true,
88
+ duration: 0,
89
+ skipped: true,
90
+ skipReason: 'Condition not met',
91
+ });
92
+ continue;
93
+ }
94
+ let lastError;
95
+ let success = false;
96
+ for (let attempt = 0; attempt <= (step.retries ?? 0); attempt++) {
97
+ try {
98
+ if (step.timeout) {
99
+ await this.withTimeout(step.compensationFn(state, originalResult), step.timeout);
100
+ }
101
+ else {
102
+ await step.compensationFn(state, originalResult);
103
+ }
104
+ success = true;
105
+ break;
106
+ }
107
+ catch (err) {
108
+ lastError = err instanceof Error ? err : new Error(String(err));
109
+ }
110
+ }
111
+ compensated.push({
112
+ nodeId,
113
+ success,
114
+ error: lastError,
115
+ duration: Date.now() - stepStart,
116
+ skipped: false,
117
+ });
118
+ if (!success) {
119
+ partialFailures.push(nodeId);
120
+ }
121
+ }
122
+ return {
123
+ triggeredBy: {
124
+ nodeId: failedNodeId,
125
+ error,
126
+ },
127
+ compensated,
128
+ totalDuration: Date.now() - startTime,
129
+ allSuccessful: partialFailures.length === 0,
130
+ partialFailures,
131
+ };
132
+ }
133
+ /**
134
+ * Sort nodes by their compensation order
135
+ */
136
+ sortByCompensationOrder(nodes) {
137
+ const result = [];
138
+ const parallel = [];
139
+ const reverse = [];
140
+ const forward = [];
141
+ for (const nodeId of nodes) {
142
+ const step = this.steps.get(nodeId);
143
+ const order = step?.order ?? 'reverse';
144
+ switch (order) {
145
+ case 'parallel':
146
+ parallel.push(nodeId);
147
+ break;
148
+ case 'forward':
149
+ forward.push(nodeId);
150
+ break;
151
+ case 'reverse':
152
+ default:
153
+ reverse.push(nodeId);
154
+ break;
155
+ }
156
+ }
157
+ result.push(...parallel);
158
+ const reverseOrder = [...this.executionOrder]
159
+ .reverse()
160
+ .filter((n) => reverse.includes(n));
161
+ result.push(...reverseOrder);
162
+ const forwardOrder = this.executionOrder.filter((n) => forward.includes(n));
163
+ result.push(...forwardOrder);
164
+ return result;
165
+ }
166
+ /**
167
+ * Execute with timeout
168
+ */
169
+ async withTimeout(promise, timeoutMs) {
170
+ return Promise.race([
171
+ promise,
172
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Compensation timeout')), timeoutMs)),
173
+ ]);
174
+ }
175
+ /**
176
+ * Reset manager state
177
+ */
178
+ reset() {
179
+ this.completedNodes.clear();
180
+ this.executionOrder = [];
181
+ }
182
+ /**
183
+ * Get current state summary
184
+ */
185
+ getSummary() {
186
+ return {
187
+ registeredSteps: this.steps.size,
188
+ completedNodes: this.completedNodes.size,
189
+ compensableNodes: this.getCompensableNodes().length,
190
+ executionOrder: [...this.executionOrder],
191
+ };
192
+ }
193
+ }
194
+ /**
195
+ * Create a compensation manager
196
+ */
197
+ export function createCompensationManager() {
198
+ return new CompensationManager();
199
+ }
200
+ /**
201
+ * Compensation builder for fluent API
202
+ */
203
+ export class CompensationBuilder {
204
+ steps = [];
205
+ /**
206
+ * Add a compensation step
207
+ */
208
+ addStep(nodeId, fn, options = {}) {
209
+ this.steps.push({ nodeId, fn, options });
210
+ return this;
211
+ }
212
+ /**
213
+ * Add conditional compensation
214
+ */
215
+ addConditionalStep(nodeId, fn, condition, options = {}) {
216
+ this.steps.push({
217
+ nodeId,
218
+ fn,
219
+ options: { ...options, condition },
220
+ });
221
+ return this;
222
+ }
223
+ /**
224
+ * Build the compensation manager
225
+ */
226
+ build() {
227
+ const manager = new CompensationManager();
228
+ for (const step of this.steps) {
229
+ manager.registerCompensation(step.nodeId, step.fn, step.options);
230
+ }
231
+ return manager;
232
+ }
233
+ }
234
+ /**
235
+ * Create a compensation builder
236
+ */
237
+ export function compensationBuilder() {
238
+ return new CompensationBuilder();
239
+ }
240
+ //# sourceMappingURL=compensation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compensation.js","sourceRoot":"","sources":["../../src/saga/compensation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Dead Letter Queue (DLQ) for failed workflow nodes
3
+ *
4
+ * Features:
5
+ * - Multiple storage backends (memory, file)
6
+ * - Failed node tracking with full context
7
+ * - Retry capability
8
+ * - Expiration/cleanup
9
+ * - Query and filtering
10
+ */
11
+ import type { DeadLetterEntry, WorkflowState } from '@cogitator-ai/types';
12
+ /**
13
+ * Extended dead letter entry (alias for DeadLetterEntry, for backwards compat)
14
+ */
15
+ export type ExtendedDeadLetterEntry = DeadLetterEntry;
16
+ /**
17
+ * DLQ query filters
18
+ */
19
+ export interface DLQFilters {
20
+ workflowId?: string;
21
+ workflowName?: string;
22
+ nodeId?: string;
23
+ minAttempts?: number;
24
+ maxAttempts?: number;
25
+ createdAfter?: number;
26
+ createdBefore?: number;
27
+ tags?: string[];
28
+ limit?: number;
29
+ offset?: number;
30
+ }
31
+ /**
32
+ * Abstract DLQ implementation
33
+ */
34
+ export declare abstract class BaseDLQ {
35
+ abstract add(entry: DeadLetterEntry): Promise<string>;
36
+ abstract get(id: string): Promise<DeadLetterEntry | null>;
37
+ abstract list(filters?: DLQFilters): Promise<DeadLetterEntry[]>;
38
+ abstract retry(id: string): Promise<boolean>;
39
+ abstract remove(id: string): Promise<boolean>;
40
+ abstract count(filters?: DLQFilters): Promise<number>;
41
+ abstract clear(): Promise<void>;
42
+ }
43
+ /**
44
+ * In-memory Dead Letter Queue
45
+ */
46
+ export declare class InMemoryDLQ extends BaseDLQ {
47
+ private entries;
48
+ private defaultTTL;
49
+ private cleanupInterval?;
50
+ constructor(options?: {
51
+ defaultTTL?: number;
52
+ cleanupIntervalMs?: number;
53
+ });
54
+ add(entry: DeadLetterEntry): Promise<string>;
55
+ get(id: string): Promise<DeadLetterEntry | null>;
56
+ list(filters?: DLQFilters): Promise<DeadLetterEntry[]>;
57
+ retry(id: string): Promise<boolean>;
58
+ remove(id: string): Promise<boolean>;
59
+ count(filters?: DLQFilters): Promise<number>;
60
+ clear(): Promise<void>;
61
+ /**
62
+ * Cleanup expired entries
63
+ */
64
+ private cleanup;
65
+ /**
66
+ * Stop cleanup interval
67
+ */
68
+ destroy(): void;
69
+ }
70
+ /**
71
+ * File-based Dead Letter Queue
72
+ */
73
+ export declare class FileDLQ extends BaseDLQ {
74
+ private directory;
75
+ private defaultTTL;
76
+ private initialized;
77
+ constructor(directory: string, options?: {
78
+ defaultTTL?: number;
79
+ });
80
+ private ensureInitialized;
81
+ private getFilePath;
82
+ add(entry: DeadLetterEntry): Promise<string>;
83
+ get(id: string): Promise<DeadLetterEntry | null>;
84
+ list(filters?: DLQFilters): Promise<DeadLetterEntry[]>;
85
+ retry(id: string): Promise<boolean>;
86
+ remove(id: string): Promise<boolean>;
87
+ count(filters?: DLQFilters): Promise<number>;
88
+ clear(): Promise<void>;
89
+ }
90
+ /**
91
+ * Create DLQ entry from error
92
+ */
93
+ export declare function createDLQEntry(nodeId: string, workflowId: string, workflowName: string, state: WorkflowState, error: Error, options?: {
94
+ input?: unknown;
95
+ attempts?: number;
96
+ maxAttempts?: number;
97
+ tags?: string[];
98
+ metadata?: Record<string, unknown>;
99
+ }): DeadLetterEntry;
100
+ /**
101
+ * Create an in-memory DLQ
102
+ */
103
+ export declare function createInMemoryDLQ(options?: {
104
+ defaultTTL?: number;
105
+ cleanupIntervalMs?: number;
106
+ }): InMemoryDLQ;
107
+ /**
108
+ * Create a file-based DLQ
109
+ */
110
+ export declare function createFileDLQ(directory: string, options?: {
111
+ defaultTTL?: number;
112
+ }): FileDLQ;
113
+ //# sourceMappingURL=dead-letter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-letter.d.ts","sourceRoot":"","sources":["../../src/saga/dead-letter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Dead Letter Queue (DLQ) for failed workflow nodes
3
+ *
4
+ * Features:
5
+ * - Multiple storage backends (memory, file)
6
+ * - Failed node tracking with full context
7
+ * - Retry capability
8
+ * - Expiration/cleanup
9
+ * - Query and filtering
10
+ */
11
+ import { nanoid } from 'nanoid';
12
+ import { promises as fs } from 'fs';
13
+ import { join } from 'path';
14
+ /**
15
+ * Abstract DLQ implementation
16
+ */
17
+ export class BaseDLQ {
18
+ }
19
+ /**
20
+ * In-memory Dead Letter Queue
21
+ */
22
+ export class InMemoryDLQ extends BaseDLQ {
23
+ entries = new Map();
24
+ defaultTTL;
25
+ cleanupInterval;
26
+ constructor(options = {}) {
27
+ super();
28
+ this.defaultTTL = options.defaultTTL ?? 7 * 24 * 60 * 60 * 1000;
29
+ if (options.cleanupIntervalMs) {
30
+ this.cleanupInterval = setInterval(() => void this.cleanup(), options.cleanupIntervalMs);
31
+ }
32
+ }
33
+ async add(entry) {
34
+ const id = `dlq_${nanoid(12)}`;
35
+ const now = Date.now();
36
+ const extended = {
37
+ ...entry,
38
+ id,
39
+ createdAt: now,
40
+ expiresAt: now + this.defaultTTL,
41
+ };
42
+ this.entries.set(id, extended);
43
+ return id;
44
+ }
45
+ async get(id) {
46
+ const entry = this.entries.get(id);
47
+ if (!entry)
48
+ return null;
49
+ if (entry.expiresAt && entry.expiresAt < Date.now()) {
50
+ this.entries.delete(id);
51
+ return null;
52
+ }
53
+ return entry;
54
+ }
55
+ async list(filters = {}) {
56
+ const now = Date.now();
57
+ let results = [];
58
+ for (const entry of this.entries.values()) {
59
+ if (entry.expiresAt && entry.expiresAt < now)
60
+ continue;
61
+ if (filters.workflowId && entry.workflowId !== filters.workflowId)
62
+ continue;
63
+ if (filters.workflowName && entry.workflowName !== filters.workflowName)
64
+ continue;
65
+ if (filters.nodeId && entry.nodeId !== filters.nodeId)
66
+ continue;
67
+ if (filters.minAttempts !== undefined && entry.attempts < filters.minAttempts)
68
+ continue;
69
+ if (filters.maxAttempts !== undefined && entry.attempts > filters.maxAttempts)
70
+ continue;
71
+ if (filters.createdAfter !== undefined && entry.createdAt < filters.createdAfter)
72
+ continue;
73
+ if (filters.createdBefore !== undefined && entry.createdAt > filters.createdBefore)
74
+ continue;
75
+ if (filters.tags && !filters.tags.every((t) => entry.tags?.includes(t)))
76
+ continue;
77
+ results.push(entry);
78
+ }
79
+ results.sort((a, b) => b.createdAt - a.createdAt);
80
+ if (filters.offset) {
81
+ results = results.slice(filters.offset);
82
+ }
83
+ if (filters.limit) {
84
+ results = results.slice(0, filters.limit);
85
+ }
86
+ return results;
87
+ }
88
+ async retry(id) {
89
+ const entry = await this.get(id);
90
+ if (!entry)
91
+ return false;
92
+ entry.attempts++;
93
+ entry.lastAttempt = Date.now();
94
+ return true;
95
+ }
96
+ async remove(id) {
97
+ return this.entries.delete(id);
98
+ }
99
+ async count(filters = {}) {
100
+ const results = await this.list(filters);
101
+ return results.length;
102
+ }
103
+ async clear() {
104
+ this.entries.clear();
105
+ }
106
+ /**
107
+ * Cleanup expired entries
108
+ */
109
+ async cleanup() {
110
+ const now = Date.now();
111
+ const toDelete = [];
112
+ for (const [id, entry] of this.entries) {
113
+ if (entry.expiresAt && entry.expiresAt < now) {
114
+ toDelete.push(id);
115
+ }
116
+ }
117
+ for (const id of toDelete) {
118
+ this.entries.delete(id);
119
+ }
120
+ }
121
+ /**
122
+ * Stop cleanup interval
123
+ */
124
+ destroy() {
125
+ if (this.cleanupInterval) {
126
+ clearInterval(this.cleanupInterval);
127
+ this.cleanupInterval = undefined;
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * File-based Dead Letter Queue
133
+ */
134
+ export class FileDLQ extends BaseDLQ {
135
+ directory;
136
+ defaultTTL;
137
+ initialized = false;
138
+ constructor(directory, options = {}) {
139
+ super();
140
+ this.directory = directory;
141
+ this.defaultTTL = options.defaultTTL ?? 7 * 24 * 60 * 60 * 1000;
142
+ }
143
+ async ensureInitialized() {
144
+ if (this.initialized)
145
+ return;
146
+ try {
147
+ await fs.mkdir(this.directory, { recursive: true });
148
+ }
149
+ catch {
150
+ }
151
+ this.initialized = true;
152
+ }
153
+ getFilePath(id) {
154
+ return join(this.directory, `${id}.json`);
155
+ }
156
+ async add(entry) {
157
+ await this.ensureInitialized();
158
+ const id = `dlq_${nanoid(12)}`;
159
+ const now = Date.now();
160
+ const extended = {
161
+ ...entry,
162
+ id,
163
+ createdAt: now,
164
+ expiresAt: now + this.defaultTTL,
165
+ };
166
+ const filePath = this.getFilePath(id);
167
+ await fs.writeFile(filePath, JSON.stringify(extended, null, 2));
168
+ return id;
169
+ }
170
+ async get(id) {
171
+ await this.ensureInitialized();
172
+ try {
173
+ const filePath = this.getFilePath(id);
174
+ const content = await fs.readFile(filePath, 'utf-8');
175
+ const entry = JSON.parse(content);
176
+ if (entry.expiresAt && entry.expiresAt < Date.now()) {
177
+ await this.remove(id);
178
+ return null;
179
+ }
180
+ return entry;
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
186
+ async list(filters = {}) {
187
+ await this.ensureInitialized();
188
+ const now = Date.now();
189
+ let results = [];
190
+ try {
191
+ const files = await fs.readdir(this.directory);
192
+ for (const file of files) {
193
+ if (!file.endsWith('.json'))
194
+ continue;
195
+ const filePath = join(this.directory, file);
196
+ try {
197
+ const content = await fs.readFile(filePath, 'utf-8');
198
+ const entry = JSON.parse(content);
199
+ if (entry.expiresAt && entry.expiresAt < now) {
200
+ await fs.unlink(filePath).catch(() => { });
201
+ continue;
202
+ }
203
+ if (filters.workflowId && entry.workflowId !== filters.workflowId)
204
+ continue;
205
+ if (filters.workflowName && entry.workflowName !== filters.workflowName)
206
+ continue;
207
+ if (filters.nodeId && entry.nodeId !== filters.nodeId)
208
+ continue;
209
+ if (filters.minAttempts !== undefined && entry.attempts < filters.minAttempts)
210
+ continue;
211
+ if (filters.maxAttempts !== undefined && entry.attempts > filters.maxAttempts)
212
+ continue;
213
+ if (filters.createdAfter !== undefined && entry.createdAt < filters.createdAfter)
214
+ continue;
215
+ if (filters.createdBefore !== undefined && entry.createdAt > filters.createdBefore)
216
+ continue;
217
+ if (filters.tags && !filters.tags.every((t) => entry.tags?.includes(t)))
218
+ continue;
219
+ results.push(entry);
220
+ }
221
+ catch {
222
+ }
223
+ }
224
+ }
225
+ catch {
226
+ }
227
+ results.sort((a, b) => b.createdAt - a.createdAt);
228
+ if (filters.offset) {
229
+ results = results.slice(filters.offset);
230
+ }
231
+ if (filters.limit) {
232
+ results = results.slice(0, filters.limit);
233
+ }
234
+ return results;
235
+ }
236
+ async retry(id) {
237
+ const entry = await this.get(id);
238
+ if (!entry)
239
+ return false;
240
+ entry.attempts++;
241
+ entry.lastAttempt = Date.now();
242
+ const filePath = this.getFilePath(id);
243
+ await fs.writeFile(filePath, JSON.stringify(entry, null, 2));
244
+ return true;
245
+ }
246
+ async remove(id) {
247
+ try {
248
+ await fs.unlink(this.getFilePath(id));
249
+ return true;
250
+ }
251
+ catch {
252
+ return false;
253
+ }
254
+ }
255
+ async count(filters = {}) {
256
+ const results = await this.list(filters);
257
+ return results.length;
258
+ }
259
+ async clear() {
260
+ await this.ensureInitialized();
261
+ try {
262
+ const files = await fs.readdir(this.directory);
263
+ await Promise.all(files
264
+ .filter((f) => f.endsWith('.json'))
265
+ .map((f) => fs.unlink(join(this.directory, f)).catch(() => { })));
266
+ }
267
+ catch {
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Create DLQ entry from error
273
+ */
274
+ export function createDLQEntry(nodeId, workflowId, workflowName, state, error, options = {}) {
275
+ return {
276
+ id: '',
277
+ nodeId,
278
+ workflowId,
279
+ workflowName,
280
+ state,
281
+ input: options.input,
282
+ error: {
283
+ name: error.name,
284
+ message: error.message,
285
+ stack: error.stack,
286
+ },
287
+ attempts: options.attempts ?? 1,
288
+ maxAttempts: options.maxAttempts ?? 1,
289
+ lastAttempt: Date.now(),
290
+ createdAt: Date.now(),
291
+ tags: options.tags,
292
+ metadata: options.metadata,
293
+ };
294
+ }
295
+ /**
296
+ * Create an in-memory DLQ
297
+ */
298
+ export function createInMemoryDLQ(options) {
299
+ return new InMemoryDLQ(options);
300
+ }
301
+ /**
302
+ * Create a file-based DLQ
303
+ */
304
+ export function createFileDLQ(directory, options) {
305
+ return new FileDLQ(directory, options);
306
+ }
307
+ //# sourceMappingURL=dead-letter.js.map