@agnt5/sdk 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -0
- package/dist/__tests__/integration/helpers.d.ts +41 -0
- package/dist/__tests__/integration/helpers.d.ts.map +1 -0
- package/dist/__tests__/integration/helpers.js +78 -0
- package/dist/__tests__/integration/helpers.js.map +1 -0
- package/dist/agent.d.ts +260 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +493 -0
- package/dist/agent.js.map +1 -0
- package/dist/async-context.d.ts +57 -0
- package/dist/async-context.d.ts.map +1 -0
- package/dist/async-context.js +52 -0
- package/dist/async-context.js.map +1 -0
- package/dist/batch.d.ts +116 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +98 -0
- package/dist/batch.js.map +1 -0
- package/dist/chat.d.ts +137 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +278 -0
- package/dist/chat.js.map +1 -0
- package/dist/client.d.ts +394 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +757 -0
- package/dist/client.js.map +1 -0
- package/dist/context.d.ts +47 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +244 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +148 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +201 -0
- package/dist/errors.js.map +1 -0
- package/dist/eval.d.ts +242 -0
- package/dist/eval.d.ts.map +1 -0
- package/dist/eval.js +452 -0
- package/dist/eval.js.map +1 -0
- package/dist/event-emitter.d.ts +28 -0
- package/dist/event-emitter.d.ts.map +1 -0
- package/dist/event-emitter.js +79 -0
- package/dist/event-emitter.js.map +1 -0
- package/dist/events.d.ts +285 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +256 -0
- package/dist/events.js.map +1 -0
- package/dist/function.d.ts +61 -0
- package/dist/function.d.ts.map +1 -0
- package/dist/function.js +78 -0
- package/dist/function.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/lm.d.ts +301 -0
- package/dist/lm.d.ts.map +1 -0
- package/dist/lm.js +283 -0
- package/dist/lm.js.map +1 -0
- package/dist/logging.d.ts +68 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +165 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp-server.d.ts +98 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +307 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp.d.ts +73 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +224 -0
- package/dist/mcp.js.map +1 -0
- package/dist/memory.d.ts +234 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +609 -0
- package/dist/memory.js.map +1 -0
- package/dist/platform-adapters.d.ts +121 -0
- package/dist/platform-adapters.d.ts.map +1 -0
- package/dist/platform-adapters.js +174 -0
- package/dist/platform-adapters.js.map +1 -0
- package/dist/platform-context.d.ts +55 -0
- package/dist/platform-context.d.ts.map +1 -0
- package/dist/platform-context.js +196 -0
- package/dist/platform-context.js.map +1 -0
- package/dist/retry-utils.d.ts +169 -0
- package/dist/retry-utils.d.ts.map +1 -0
- package/dist/retry-utils.js +304 -0
- package/dist/retry-utils.js.map +1 -0
- package/dist/sandbox.d.ts +103 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +168 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema-utils.d.ts +250 -0
- package/dist/schema-utils.d.ts.map +1 -0
- package/dist/schema-utils.js +444 -0
- package/dist/schema-utils.js.map +1 -0
- package/dist/scorer.d.ts +130 -0
- package/dist/scorer.d.ts.map +1 -0
- package/dist/scorer.js +211 -0
- package/dist/scorer.js.map +1 -0
- package/dist/state.d.ts +92 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +151 -0
- package/dist/state.js.map +1 -0
- package/dist/tool.d.ts +120 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +215 -0
- package/dist/tool.js.map +1 -0
- package/dist/tracing.d.ts +82 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +206 -0
- package/dist/tracing.js.map +1 -0
- package/dist/types.d.ts +139 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/worker.d.ts +111 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +944 -0
- package/dist/worker.js.map +1 -0
- package/dist/workflow-utils.d.ts +257 -0
- package/dist/workflow-utils.d.ts.map +1 -0
- package/dist/workflow-utils.js +370 -0
- package/dist/workflow-utils.js.map +1 -0
- package/dist/workflow.d.ts +78 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +138 -0
- package/dist/workflow.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow utilities for parallel execution and orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Phase 4.3: Enhanced workflow capabilities including:
|
|
5
|
+
* - Parallel execution with Promise.all
|
|
6
|
+
* - Gather with named results
|
|
7
|
+
* - Child workflow execution
|
|
8
|
+
* - Enhanced step tracking
|
|
9
|
+
*/
|
|
10
|
+
import { WorkflowRegistry } from './workflow.js';
|
|
11
|
+
/**
|
|
12
|
+
* Run multiple async tasks in parallel and return results in order.
|
|
13
|
+
*
|
|
14
|
+
* @param tasks - Array of promises to execute in parallel
|
|
15
|
+
* @returns Array of results in the same order as tasks
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const [result1, result2, result3] = await parallel([
|
|
20
|
+
* fetchUser(userId),
|
|
21
|
+
* fetchOrders(userId),
|
|
22
|
+
* fetchSettings(userId),
|
|
23
|
+
* ]);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export async function parallel(tasks) {
|
|
27
|
+
return Promise.all(tasks);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run tasks in parallel with named results.
|
|
31
|
+
*
|
|
32
|
+
* @param tasks - Object with task names as keys and promises as values
|
|
33
|
+
* @returns Object with same keys and resolved values
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const results = await gather({
|
|
38
|
+
* user: fetchUser(userId),
|
|
39
|
+
* orders: fetchOrders(userId),
|
|
40
|
+
* settings: fetchSettings(userId),
|
|
41
|
+
* });
|
|
42
|
+
* // results.user, results.orders, results.settings
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function gather(tasks) {
|
|
46
|
+
const keys = Object.keys(tasks);
|
|
47
|
+
const promises = Object.values(tasks);
|
|
48
|
+
const results = await Promise.all(promises);
|
|
49
|
+
const resultObj = {};
|
|
50
|
+
for (let i = 0; i < keys.length; i++) {
|
|
51
|
+
resultObj[keys[i]] = results[i];
|
|
52
|
+
}
|
|
53
|
+
return resultObj;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Execute a child workflow from within a parent workflow.
|
|
57
|
+
*
|
|
58
|
+
* @param ctx - Parent workflow context
|
|
59
|
+
* @param workflowNameOrHandler - Workflow name or handler function
|
|
60
|
+
* @param input - Input data for the child workflow
|
|
61
|
+
* @returns Result from the child workflow
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const processOrder = workflow('process-order', async (ctx, orderId) => {
|
|
66
|
+
* // Execute child workflow
|
|
67
|
+
* const validation = await executeChildWorkflow(ctx, 'validate-order', orderId);
|
|
68
|
+
*
|
|
69
|
+
* if (!validation.valid) {
|
|
70
|
+
* throw new Error('Invalid order');
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* return { status: 'processed' };
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export async function executeChildWorkflow(ctx, workflowNameOrHandler, input) {
|
|
78
|
+
let workflowName;
|
|
79
|
+
let handler;
|
|
80
|
+
// Resolve workflow handler
|
|
81
|
+
if (typeof workflowNameOrHandler === 'string') {
|
|
82
|
+
workflowName = workflowNameOrHandler;
|
|
83
|
+
const config = WorkflowRegistry.get(workflowName);
|
|
84
|
+
if (!config) {
|
|
85
|
+
throw new Error(`Workflow '${workflowName}' not found in registry`);
|
|
86
|
+
}
|
|
87
|
+
handler = config.handler;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
handler = workflowNameOrHandler;
|
|
91
|
+
workflowName = handler.name || 'anonymous-child-workflow';
|
|
92
|
+
}
|
|
93
|
+
ctx.logger.info(`Starting child workflow: ${workflowName}`);
|
|
94
|
+
try {
|
|
95
|
+
// Execute child workflow with parent context
|
|
96
|
+
const result = await handler(ctx, input);
|
|
97
|
+
ctx.logger.info(`Child workflow completed: ${workflowName}`);
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
ctx.logger.error(`Child workflow failed: ${workflowName}`, { error: error.message });
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Execute multiple child workflows in parallel.
|
|
107
|
+
*
|
|
108
|
+
* @param ctx - Parent workflow context
|
|
109
|
+
* @param workflows - Array of [workflowNameOrHandler, input] tuples
|
|
110
|
+
* @returns Array of results from child workflows
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const results = await parallelWorkflows(ctx, [
|
|
115
|
+
* ['validate-user', userId],
|
|
116
|
+
* ['validate-payment', paymentId],
|
|
117
|
+
* ['validate-inventory', items],
|
|
118
|
+
* ]);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export async function parallelWorkflows(ctx, workflows) {
|
|
122
|
+
const tasks = workflows.map(([nameOrHandler, input]) => executeChildWorkflow(ctx, nameOrHandler, input));
|
|
123
|
+
return parallel(tasks);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Execute child workflows with named results.
|
|
127
|
+
*
|
|
128
|
+
* @param ctx - Parent workflow context
|
|
129
|
+
* @param workflows - Object with workflow names as keys and [nameOrHandler, input] as values
|
|
130
|
+
* @returns Object with same keys and workflow results
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const results = await gatherWorkflows(ctx, {
|
|
135
|
+
* user: ['validate-user', userId],
|
|
136
|
+
* payment: ['validate-payment', paymentId],
|
|
137
|
+
* inventory: ['check-inventory', items],
|
|
138
|
+
* });
|
|
139
|
+
* // results.user, results.payment, results.inventory
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export async function gatherWorkflows(ctx, workflows) {
|
|
143
|
+
const tasks = {};
|
|
144
|
+
for (const [key, [nameOrHandler, input]] of Object.entries(workflows)) {
|
|
145
|
+
tasks[key] = executeChildWorkflow(ctx, nameOrHandler, input);
|
|
146
|
+
}
|
|
147
|
+
return gather(tasks);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Fan-out pattern: Execute the same workflow with different inputs in parallel.
|
|
151
|
+
*
|
|
152
|
+
* @param ctx - Parent workflow context
|
|
153
|
+
* @param workflowNameOrHandler - Workflow to execute
|
|
154
|
+
* @param inputs - Array of inputs for each workflow execution
|
|
155
|
+
* @returns Array of results
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const userIds = [1, 2, 3, 4, 5];
|
|
160
|
+
* const results = await fanOut(ctx, 'process-user', userIds);
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export async function fanOut(ctx, workflowNameOrHandler, inputs) {
|
|
164
|
+
const tasks = inputs.map(input => executeChildWorkflow(ctx, workflowNameOrHandler, input));
|
|
165
|
+
return parallel(tasks);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Execute workflows in batches to avoid overwhelming the system.
|
|
169
|
+
*
|
|
170
|
+
* @param ctx - Parent workflow context
|
|
171
|
+
* @param workflowNameOrHandler - Workflow to execute
|
|
172
|
+
* @param inputs - Array of inputs for each workflow execution
|
|
173
|
+
* @param batchSize - Number of workflows to execute in parallel per batch (default: 10)
|
|
174
|
+
* @returns Array of results
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const userIds = Array.from({ length: 100 }, (_, i) => i);
|
|
179
|
+
* const results = await batchExecute(ctx, 'process-user', userIds, 10);
|
|
180
|
+
* // Processes 100 users in batches of 10
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export async function batchExecute(ctx, workflowNameOrHandler, inputs, batchSize = 10) {
|
|
184
|
+
const results = [];
|
|
185
|
+
for (let i = 0; i < inputs.length; i += batchSize) {
|
|
186
|
+
const batch = inputs.slice(i, i + batchSize);
|
|
187
|
+
ctx.logger.info(`Processing batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(inputs.length / batchSize)}`);
|
|
188
|
+
const batchResults = await fanOut(ctx, workflowNameOrHandler, batch);
|
|
189
|
+
results.push(...batchResults);
|
|
190
|
+
}
|
|
191
|
+
return results;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Race pattern: Return the first workflow that completes successfully.
|
|
195
|
+
*
|
|
196
|
+
* @param ctx - Parent workflow context
|
|
197
|
+
* @param workflows - Array of [workflowNameOrHandler, input] tuples
|
|
198
|
+
* @returns Result from the first workflow to complete
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const result = await race(ctx, [
|
|
203
|
+
* ['fetch-from-cache', cacheKey],
|
|
204
|
+
* ['fetch-from-db', dbId],
|
|
205
|
+
* ['fetch-from-api', apiUrl],
|
|
206
|
+
* ]);
|
|
207
|
+
* // Returns whichever completes first
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export async function race(ctx, workflows) {
|
|
211
|
+
const tasks = workflows.map(([nameOrHandler, input]) => executeChildWorkflow(ctx, nameOrHandler, input));
|
|
212
|
+
return Promise.race(tasks);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Execute workflows with a timeout.
|
|
216
|
+
*
|
|
217
|
+
* @param ctx - Parent workflow context
|
|
218
|
+
* @param workflowNameOrHandler - Workflow to execute
|
|
219
|
+
* @param input - Input data for the workflow
|
|
220
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
221
|
+
* @returns Result from the workflow
|
|
222
|
+
* @throws TimeoutError if workflow exceeds timeout
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```typescript
|
|
226
|
+
* try {
|
|
227
|
+
* const result = await withTimeout(ctx, 'slow-workflow', input, 5000);
|
|
228
|
+
* } catch (error) {
|
|
229
|
+
* if (error instanceof TimeoutError) {
|
|
230
|
+
* // Handle timeout
|
|
231
|
+
* }
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export async function withTimeout(ctx, workflowNameOrHandler, input, timeoutMs) {
|
|
236
|
+
const { TimeoutError } = await import('./errors.js');
|
|
237
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
reject(new TimeoutError(`Workflow execution timed out after ${timeoutMs}ms`, timeoutMs, 'withTimeout'));
|
|
240
|
+
}, timeoutMs);
|
|
241
|
+
});
|
|
242
|
+
const workflowPromise = executeChildWorkflow(ctx, workflowNameOrHandler, input);
|
|
243
|
+
return Promise.race([workflowPromise, timeoutPromise]);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Saga pattern coordinator for managing compensating transactions.
|
|
247
|
+
*
|
|
248
|
+
* Executes steps sequentially, and if any step fails, executes compensating
|
|
249
|
+
* actions in reverse order.
|
|
250
|
+
*
|
|
251
|
+
* @param ctx - Workflow context
|
|
252
|
+
* @param steps - Array of [action, compensation] tuples
|
|
253
|
+
* @returns Result from the final step
|
|
254
|
+
* @throws Error from failed step after compensation
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* const result = await saga(ctx, [
|
|
259
|
+
* [
|
|
260
|
+
* async () => await reserveInventory(items),
|
|
261
|
+
* async () => await releaseInventory(items),
|
|
262
|
+
* ],
|
|
263
|
+
* [
|
|
264
|
+
* async () => await chargePayment(paymentInfo),
|
|
265
|
+
* async () => await refundPayment(paymentInfo),
|
|
266
|
+
* ],
|
|
267
|
+
* [
|
|
268
|
+
* async () => await shipOrder(orderId),
|
|
269
|
+
* async () => await cancelShipment(orderId),
|
|
270
|
+
* ],
|
|
271
|
+
* ]);
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
export async function saga(ctx, steps) {
|
|
275
|
+
const completedSteps = [];
|
|
276
|
+
let lastResult;
|
|
277
|
+
try {
|
|
278
|
+
for (let i = 0; i < steps.length; i++) {
|
|
279
|
+
const [action, compensation] = steps[i];
|
|
280
|
+
ctx.logger.info(`Executing saga step ${i + 1}/${steps.length}`);
|
|
281
|
+
lastResult = await action();
|
|
282
|
+
completedSteps.push(compensation);
|
|
283
|
+
}
|
|
284
|
+
return lastResult;
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
ctx.logger.error(`Saga failed at step ${completedSteps.length + 1}, executing compensations`);
|
|
288
|
+
// Execute compensations in reverse order
|
|
289
|
+
for (let i = completedSteps.length - 1; i >= 0; i--) {
|
|
290
|
+
try {
|
|
291
|
+
ctx.logger.info(`Executing compensation ${i + 1}/${completedSteps.length}`);
|
|
292
|
+
await completedSteps[i]();
|
|
293
|
+
}
|
|
294
|
+
catch (compensationError) {
|
|
295
|
+
ctx.logger.error(`Compensation ${i + 1} failed: ${compensationError.message}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Retry a workflow with exponential backoff.
|
|
303
|
+
*
|
|
304
|
+
* @param ctx - Workflow context
|
|
305
|
+
* @param workflowNameOrHandler - Workflow to execute
|
|
306
|
+
* @param input - Input data for the workflow
|
|
307
|
+
* @param maxAttempts - Maximum number of attempts (default: 3)
|
|
308
|
+
* @param initialDelayMs - Initial delay in milliseconds (default: 1000)
|
|
309
|
+
* @returns Result from the workflow
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* const result = await retryWorkflow(
|
|
314
|
+
* ctx,
|
|
315
|
+
* 'unstable-api-call',
|
|
316
|
+
* apiParams,
|
|
317
|
+
* 5, // 5 attempts
|
|
318
|
+
* 2000 // Start with 2 second delay
|
|
319
|
+
* );
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
/**
|
|
323
|
+
* Durable sleep that survives workflow restarts.
|
|
324
|
+
*
|
|
325
|
+
* Unlike `setTimeout` or `new Promise(resolve => setTimeout(...))`, this sleep
|
|
326
|
+
* is checkpointed via `ctx.step()`. If the workflow crashes and restarts, it
|
|
327
|
+
* only sleeps for the remaining duration (or skips entirely if the period has
|
|
328
|
+
* already elapsed).
|
|
329
|
+
*
|
|
330
|
+
* @param ctx - Workflow context
|
|
331
|
+
* @param durationMs - Duration to sleep in milliseconds
|
|
332
|
+
* @param name - Optional name for the sleep checkpoint (auto-generated if omitted)
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* ```typescript
|
|
336
|
+
* const notifyLater = workflow('notify-later', async (ctx, userId) => {
|
|
337
|
+
* await ctx.step('send-ack', () => sendAck(userId));
|
|
338
|
+
*
|
|
339
|
+
* // Wait 24 hours (survives restarts!)
|
|
340
|
+
* await sleep(ctx, 24 * 60 * 60 * 1000, 'wait_24h');
|
|
341
|
+
*
|
|
342
|
+
* await ctx.step('send-followup', () => sendFollowup(userId));
|
|
343
|
+
* });
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
export async function sleep(ctx, durationMs, name) {
|
|
347
|
+
const sleepName = name || `sleep_${durationMs}ms`;
|
|
348
|
+
// ctx.step() checkpoints the start time — on replay it returns the cached value
|
|
349
|
+
const startTime = await ctx.step(sleepName, () => Date.now());
|
|
350
|
+
const elapsed = Date.now() - startTime;
|
|
351
|
+
const remaining = durationMs - elapsed;
|
|
352
|
+
if (remaining > 0) {
|
|
353
|
+
ctx.logger.info(`Starting durable sleep '${sleepName}': ${remaining}ms`);
|
|
354
|
+
await new Promise(resolve => setTimeout(resolve, remaining));
|
|
355
|
+
ctx.logger.info(`Sleep '${sleepName}' completed`);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
ctx.logger.info(`Sleep '${sleepName}' already elapsed (${elapsed}ms ago)`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
export async function retryWorkflow(ctx, workflowNameOrHandler, input, maxAttempts = 3, initialDelayMs = 1000) {
|
|
362
|
+
const { executeWithRetry } = await import('./retry-utils.js');
|
|
363
|
+
return executeWithRetry(() => executeChildWorkflow(ctx, workflowNameOrHandler, input), {
|
|
364
|
+
retryPolicy: { maxAttempts, initialIntervalMs: initialDelayMs, maxIntervalMs: 60000 },
|
|
365
|
+
backoffPolicy: 'exponential',
|
|
366
|
+
jitter: true,
|
|
367
|
+
context: ctx,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=workflow-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-utils.js","sourceRoot":"","sources":["../src/workflow-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow component for multi-step orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1: In-memory orchestration with basic coordination
|
|
5
|
+
* Phase 2: Durable execution with checkpoint/replay and distributed tasks
|
|
6
|
+
*/
|
|
7
|
+
import type { WorkflowHandler } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Workflow configuration
|
|
10
|
+
*/
|
|
11
|
+
export interface WorkflowConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
handler: WorkflowHandler;
|
|
14
|
+
/** Cron expression for scheduled execution (e.g., "0 0/6 * * *") */
|
|
15
|
+
cron?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Global workflow registry
|
|
19
|
+
*/
|
|
20
|
+
export declare class WorkflowRegistry {
|
|
21
|
+
private static workflows;
|
|
22
|
+
/**
|
|
23
|
+
* Register a workflow handler
|
|
24
|
+
*/
|
|
25
|
+
static register(config: WorkflowConfig): void;
|
|
26
|
+
/**
|
|
27
|
+
* Get workflow configuration by name
|
|
28
|
+
*/
|
|
29
|
+
static get(name: string): WorkflowConfig | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Get all registered workflows
|
|
32
|
+
*/
|
|
33
|
+
static all(): Map<string, WorkflowConfig>;
|
|
34
|
+
/**
|
|
35
|
+
* List all registered workflow names
|
|
36
|
+
*/
|
|
37
|
+
static listNames(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Clear all registered workflows (for testing)
|
|
40
|
+
*/
|
|
41
|
+
static clear(): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Workflow options
|
|
45
|
+
*/
|
|
46
|
+
export interface WorkflowOptions {
|
|
47
|
+
/** Custom workflow name (defaults to function name) */
|
|
48
|
+
name?: string;
|
|
49
|
+
/** Cron expression for scheduled execution (e.g., "0 0/6 * * *") */
|
|
50
|
+
cron?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decorator to mark a function as a durable workflow
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const processOrder = workflow('process-order', async (ctx: Context, orderId: string) => {
|
|
58
|
+
* // Validate order
|
|
59
|
+
* const order = await ctx.step('validate', async () => {
|
|
60
|
+
* return { id: orderId, total: 100 };
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Process payment
|
|
64
|
+
* const payment = await ctx.step('payment', async () => {
|
|
65
|
+
* return { status: 'success' };
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Fulfill order
|
|
69
|
+
* await ctx.step('fulfill', async () => {
|
|
70
|
+
* console.log('Order fulfilled');
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* return { status: 'completed' };
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function workflow<TInput = any, TOutput = any>(nameOrHandler: string | WorkflowHandler<TInput, TOutput>, handlerOrOptions?: WorkflowHandler<TInput, TOutput> | WorkflowOptions, optionsParam?: WorkflowOptions): WorkflowHandler<TInput, TOutput>;
|
|
78
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAW,eAAe,EAAE,MAAM,YAAY,CAAC;AAG3D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;IACzB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAqC;IAE7D;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAO7C;;OAEG;IACH,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIpD;;OAEG;IACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;IAIzC;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;CAGrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EAClD,aAAa,EAAE,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,EACxD,gBAAgB,CAAC,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EACrE,YAAY,CAAC,EAAE,eAAe,GAC7B,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CA+DlC"}
|
package/dist/workflow.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow component for multi-step orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1: In-memory orchestration with basic coordination
|
|
5
|
+
* Phase 2: Durable execution with checkpoint/replay and distributed tasks
|
|
6
|
+
*/
|
|
7
|
+
import { ContextImpl } from './context.js';
|
|
8
|
+
/**
|
|
9
|
+
* Global workflow registry
|
|
10
|
+
*/
|
|
11
|
+
export class WorkflowRegistry {
|
|
12
|
+
/**
|
|
13
|
+
* Register a workflow handler
|
|
14
|
+
*/
|
|
15
|
+
static register(config) {
|
|
16
|
+
if (this.workflows.has(config.name)) {
|
|
17
|
+
console.warn(`Overwriting existing workflow '${config.name}'`);
|
|
18
|
+
}
|
|
19
|
+
this.workflows.set(config.name, config);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get workflow configuration by name
|
|
23
|
+
*/
|
|
24
|
+
static get(name) {
|
|
25
|
+
return this.workflows.get(name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get all registered workflows
|
|
29
|
+
*/
|
|
30
|
+
static all() {
|
|
31
|
+
return new Map(this.workflows);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* List all registered workflow names
|
|
35
|
+
*/
|
|
36
|
+
static listNames() {
|
|
37
|
+
return Array.from(this.workflows.keys());
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Clear all registered workflows (for testing)
|
|
41
|
+
*/
|
|
42
|
+
static clear() {
|
|
43
|
+
this.workflows.clear();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
WorkflowRegistry.workflows = new Map();
|
|
47
|
+
/**
|
|
48
|
+
* Decorator to mark a function as a durable workflow
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const processOrder = workflow('process-order', async (ctx: Context, orderId: string) => {
|
|
53
|
+
* // Validate order
|
|
54
|
+
* const order = await ctx.step('validate', async () => {
|
|
55
|
+
* return { id: orderId, total: 100 };
|
|
56
|
+
* });
|
|
57
|
+
*
|
|
58
|
+
* // Process payment
|
|
59
|
+
* const payment = await ctx.step('payment', async () => {
|
|
60
|
+
* return { status: 'success' };
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* // Fulfill order
|
|
64
|
+
* await ctx.step('fulfill', async () => {
|
|
65
|
+
* console.log('Order fulfilled');
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* return { status: 'completed' };
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function workflow(nameOrHandler, handlerOrOptions, optionsParam) {
|
|
73
|
+
let workflowName;
|
|
74
|
+
let handler;
|
|
75
|
+
let options = {};
|
|
76
|
+
// Parse arguments
|
|
77
|
+
if (typeof nameOrHandler === 'string') {
|
|
78
|
+
workflowName = nameOrHandler;
|
|
79
|
+
if (typeof handlerOrOptions === 'function') {
|
|
80
|
+
handler = handlerOrOptions;
|
|
81
|
+
options = optionsParam || {};
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
throw new Error('Invalid workflow definition: handler must be a function');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (typeof nameOrHandler === 'function') {
|
|
88
|
+
handler = nameOrHandler;
|
|
89
|
+
workflowName = handler.name || 'anonymous-workflow';
|
|
90
|
+
options = handlerOrOptions || {};
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw new Error('Invalid workflow definition');
|
|
94
|
+
}
|
|
95
|
+
// Override name if provided in options
|
|
96
|
+
if (options.name) {
|
|
97
|
+
workflowName = options.name;
|
|
98
|
+
}
|
|
99
|
+
// Register workflow
|
|
100
|
+
const config = {
|
|
101
|
+
name: workflowName,
|
|
102
|
+
handler,
|
|
103
|
+
cron: options.cron,
|
|
104
|
+
};
|
|
105
|
+
WorkflowRegistry.register(config);
|
|
106
|
+
// Create wrapper that provides context
|
|
107
|
+
const workflowWrapper = async (ctxOrInput, input) => {
|
|
108
|
+
let ctx;
|
|
109
|
+
let actualInput;
|
|
110
|
+
// Determine if first arg is Context or input
|
|
111
|
+
if (isContext(ctxOrInput)) {
|
|
112
|
+
ctx = ctxOrInput;
|
|
113
|
+
actualInput = input;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Auto-create context for direct workflow calls
|
|
117
|
+
ctx = new ContextImpl(`workflow-${workflowName}-${Date.now()}`, `run-${Date.now()}`, 0, workflowName);
|
|
118
|
+
actualInput = ctxOrInput;
|
|
119
|
+
}
|
|
120
|
+
// Execute workflow
|
|
121
|
+
return handler(ctx, actualInput);
|
|
122
|
+
};
|
|
123
|
+
// Attach config for introspection
|
|
124
|
+
workflowWrapper._agnt5_config = config;
|
|
125
|
+
return workflowWrapper;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Type guard to check if value is a Context
|
|
129
|
+
*/
|
|
130
|
+
function isContext(value) {
|
|
131
|
+
return (value &&
|
|
132
|
+
typeof value === 'object' &&
|
|
133
|
+
'invocationId' in value &&
|
|
134
|
+
'runId' in value &&
|
|
135
|
+
'step' in value &&
|
|
136
|
+
'logger' in value);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"}
|