@falai/agent 1.1.0 → 1.1.2
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/dist/adapters/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/MemoryAdapter.js +2 -1
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/MongoAdapter.d.ts.map +1 -1
- package/dist/adapters/MongoAdapter.js +2 -1
- package/dist/adapters/MongoAdapter.js.map +1 -1
- package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/adapters/OpenSearchAdapter.js +2 -1
- package/dist/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.js +2 -1
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/adapters/PrismaAdapter.js +2 -1
- package/dist/adapters/PrismaAdapter.js.map +1 -1
- package/dist/adapters/RedisAdapter.d.ts.map +1 -1
- package/dist/adapters/RedisAdapter.js.map +1 -1
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.js +2 -1
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.js +2 -1
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +2 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +2 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.js +2 -1
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/core/Agent.d.ts +202 -67
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +366 -158
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/BatchExecutor.js +5 -6
- package/dist/cjs/core/BatchExecutor.js.map +1 -1
- package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -1
- package/dist/cjs/core/BatchPromptBuilder.js +5 -2
- package/dist/cjs/core/BatchPromptBuilder.js.map +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +6 -3
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
- package/dist/cjs/core/ResponseModal.js +18 -17
- package/dist/cjs/core/ResponseModal.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/core/RoutingEngine.js +8 -73
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/core/SessionManager.js +4 -11
- package/dist/cjs/core/SessionManager.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/utils/session.d.ts +6 -0
- package/dist/cjs/utils/session.d.ts.map +1 -1
- package/dist/cjs/utils/session.js +26 -8
- package/dist/cjs/utils/session.js.map +1 -1
- package/dist/core/Agent.d.ts +202 -67
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +366 -158
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/BatchExecutor.js +6 -7
- package/dist/core/BatchExecutor.js.map +1 -1
- package/dist/core/BatchPromptBuilder.d.ts.map +1 -1
- package/dist/core/BatchPromptBuilder.js +5 -2
- package/dist/core/BatchPromptBuilder.js.map +1 -1
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +6 -3
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/ResponseModal.d.ts.map +1 -1
- package/dist/core/ResponseModal.js +18 -17
- package/dist/core/ResponseModal.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts.map +1 -1
- package/dist/core/RoutingEngine.js +8 -73
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +4 -11
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/session.d.ts +6 -0
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +26 -8
- package/dist/utils/session.js.map +1 -1
- package/docs/api/README.md +33 -4
- package/docs/api/overview.md +9 -5
- package/docs/architecture/data-extraction-flow.md +17 -19
- package/docs/core/conversation-flows/data-collection.md +9 -3
- package/docs/core/conversation-flows/route-dsl.md +8 -1
- package/docs/core/error-handling.md +3 -4
- package/docs/core/persistence/session-storage.md +12 -0
- package/examples/integrations/database-integration.ts +10 -9
- package/examples/persistence/custom-adapter.ts +12 -15
- package/package.json +2 -2
- package/src/adapters/MemoryAdapter.ts +6 -8
- package/src/adapters/MongoAdapter.ts +6 -8
- package/src/adapters/OpenSearchAdapter.ts +6 -8
- package/src/adapters/PostgreSQLAdapter.ts +6 -8
- package/src/adapters/PrismaAdapter.ts +4 -6
- package/src/adapters/RedisAdapter.ts +4 -7
- package/src/adapters/SQLiteAdapter.ts +6 -9
- package/src/core/Agent.ts +427 -195
- package/src/core/BatchExecutor.ts +129 -129
- package/src/core/BatchPromptBuilder.ts +41 -38
- package/src/core/ResponseEngine.ts +56 -53
- package/src/core/ResponseModal.ts +79 -81
- package/src/core/RoutingEngine.ts +67 -149
- package/src/core/SessionManager.ts +4 -13
- package/src/index.ts +11 -11
- package/src/utils/session.ts +48 -10
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* and orchestrating their execution with a single LLM call.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
BatchResult,
|
|
10
|
-
StoppedReason,
|
|
11
|
-
StepOptions,
|
|
12
|
-
BatchExecutionError,
|
|
13
|
-
BatchExecutionResult,
|
|
8
|
+
import type {
|
|
9
|
+
BatchResult,
|
|
10
|
+
StoppedReason,
|
|
11
|
+
StepOptions,
|
|
12
|
+
BatchExecutionError,
|
|
13
|
+
BatchExecutionResult,
|
|
14
14
|
StepRef,
|
|
15
15
|
BatchExecutionEvent,
|
|
16
16
|
BatchExecutionEventListener,
|
|
@@ -22,7 +22,7 @@ import type { StructuredSchema } from '../types/schema';
|
|
|
22
22
|
import { Step } from './Step';
|
|
23
23
|
import { Route } from './Route';
|
|
24
24
|
import { END_ROUTE_ID } from '../constants';
|
|
25
|
-
import { logger, createTemplateContext, mergeCollected } from '../utils';
|
|
25
|
+
import { logger, createTemplateContext, mergeCollected, createSession } from '../utils';
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Step configuration relevant for needs-input detection
|
|
@@ -201,7 +201,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
201
201
|
details,
|
|
202
202
|
};
|
|
203
203
|
this.emitEvent(event);
|
|
204
|
-
|
|
204
|
+
|
|
205
205
|
// Also log the event when debug mode is enabled
|
|
206
206
|
logger.debug(`[BatchExecutor] Event: ${type}`, details);
|
|
207
207
|
}
|
|
@@ -230,14 +230,14 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
230
230
|
async determineBatch(params: DetermineBatchParams<TContext, TData>): Promise<BatchResult<TContext, TData>> {
|
|
231
231
|
const { route, currentStep, sessionData, context, maxSteps = 1 } = params;
|
|
232
232
|
const startTime = Date.now();
|
|
233
|
-
|
|
233
|
+
|
|
234
234
|
const batchSteps: StepOptions<TContext, TData>[] = [];
|
|
235
235
|
let stoppedReason: StoppedReason = 'route_complete';
|
|
236
236
|
let stoppedAtStep: StepOptions<TContext, TData> | undefined;
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
// Get all steps in the route for traversal
|
|
239
239
|
const allSteps = route.getAllSteps();
|
|
240
|
-
|
|
240
|
+
|
|
241
241
|
// Find starting position
|
|
242
242
|
let startIndex = 0;
|
|
243
243
|
if (currentStep) {
|
|
@@ -246,40 +246,37 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
246
246
|
startIndex = currentIndex;
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
// Log batch determination start (Requirement 11.1)
|
|
251
251
|
logger.debug(`[BatchExecutor] Starting batch determination from step index ${startIndex}, total steps: ${allSteps.length}`);
|
|
252
|
-
|
|
252
|
+
|
|
253
253
|
// Emit batch_start event (Requirement 11.3)
|
|
254
254
|
this.emitBatchEvent('batch_start', {
|
|
255
255
|
stepId: currentStep?.id,
|
|
256
256
|
reason: `Starting batch determination from ${currentStep?.id || 'initial step'}`,
|
|
257
257
|
batchSize: 0,
|
|
258
258
|
});
|
|
259
|
-
|
|
259
|
+
|
|
260
260
|
// Create template context for condition evaluation
|
|
261
261
|
const templateContext = createTemplateContext<TContext, TData>({
|
|
262
262
|
context,
|
|
263
263
|
data: sessionData,
|
|
264
|
-
session: {
|
|
265
|
-
id: `batch-${Date.now()}`,
|
|
266
|
-
data: sessionData
|
|
267
|
-
} as SessionState<TData>,
|
|
264
|
+
session: createSession<TData>({ data: sessionData }),
|
|
268
265
|
});
|
|
269
|
-
|
|
266
|
+
|
|
270
267
|
// Walk through steps starting from current position
|
|
271
268
|
for (let i = startIndex; i < allSteps.length; i++) {
|
|
272
269
|
const step = allSteps[i];
|
|
273
270
|
const stepOptions = step.toOptions();
|
|
274
|
-
|
|
271
|
+
|
|
275
272
|
// Check for END_ROUTE (Requirement 2.2)
|
|
276
273
|
if (step.id === END_ROUTE_ID) {
|
|
277
274
|
stoppedReason = 'end_route';
|
|
278
275
|
stoppedAtStep = stepOptions;
|
|
279
|
-
|
|
276
|
+
|
|
280
277
|
// Log stopping reason (Requirement 11.2)
|
|
281
278
|
logger.debug(`[BatchExecutor] Reached END_ROUTE, stopping batch`);
|
|
282
|
-
|
|
279
|
+
|
|
283
280
|
// Emit batch_stop event (Requirement 11.3)
|
|
284
281
|
this.emitBatchEvent('batch_stop', {
|
|
285
282
|
stepId: step.id,
|
|
@@ -289,14 +286,14 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
289
286
|
});
|
|
290
287
|
break;
|
|
291
288
|
}
|
|
292
|
-
|
|
289
|
+
|
|
293
290
|
// Evaluate skipIf condition (Requirements 7.1, 7.2, 7.3)
|
|
294
291
|
let shouldSkip = false;
|
|
295
292
|
if (step.skipIf) {
|
|
296
293
|
try {
|
|
297
294
|
const skipResult = await step.evaluateSkipIf(templateContext);
|
|
298
295
|
shouldSkip = skipResult.shouldSkip;
|
|
299
|
-
|
|
296
|
+
|
|
300
297
|
// Log skipIf evaluation (Requirement 11.1)
|
|
301
298
|
logger.debug(`[BatchExecutor] Step ${step.id} skipIf evaluated to: ${shouldSkip}`);
|
|
302
299
|
} catch (error) {
|
|
@@ -305,12 +302,12 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
305
302
|
shouldSkip = false;
|
|
306
303
|
}
|
|
307
304
|
}
|
|
308
|
-
|
|
305
|
+
|
|
309
306
|
// If skipIf is true, skip this step and continue (Requirement 7.2)
|
|
310
307
|
if (shouldSkip) {
|
|
311
308
|
// Log step skip (Requirement 11.1)
|
|
312
309
|
logger.debug(`[BatchExecutor] Skipping step ${step.id} due to skipIf condition`);
|
|
313
|
-
|
|
310
|
+
|
|
314
311
|
// Emit step_skipped event (Requirement 11.3)
|
|
315
312
|
this.emitBatchEvent('step_skipped', {
|
|
316
313
|
stepId: step.id,
|
|
@@ -318,15 +315,15 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
318
315
|
});
|
|
319
316
|
continue;
|
|
320
317
|
}
|
|
321
|
-
|
|
318
|
+
|
|
322
319
|
// Evaluate needsInput (Requirements 1.2, 1.3)
|
|
323
320
|
const stepNeedsInput = needsInput(step, sessionData);
|
|
324
|
-
|
|
321
|
+
|
|
325
322
|
if (stepNeedsInput) {
|
|
326
323
|
// Requirement 1.5: Stop when a step needs input
|
|
327
324
|
stoppedReason = 'needs_input';
|
|
328
325
|
stoppedAtStep = stepOptions;
|
|
329
|
-
|
|
326
|
+
|
|
330
327
|
// Log stopping reason with details (Requirement 11.1, 11.2)
|
|
331
328
|
const missingRequires = step.requires?.filter(
|
|
332
329
|
field => (sessionData as Record<string, unknown>)[String(field)] === undefined
|
|
@@ -338,12 +335,15 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
338
335
|
const warning = `[Agent] Step "${step.description || step.id}" requires data [${missingRequires.join(', ')}] that was not collected by previous steps. ` +
|
|
339
336
|
`Ensure earlier steps collect these fields before this step can proceed.`;
|
|
340
337
|
logger.warn(warning);
|
|
341
|
-
|
|
342
|
-
console
|
|
338
|
+
|
|
339
|
+
// Also log to console for developer visibility (but silence in test suites to prevent fast-check spam)
|
|
340
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
341
|
+
console.warn(warning);
|
|
342
|
+
}
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
logger.debug(`[BatchExecutor] Step ${step.id} needs input, stopping batch. Missing requires: [${missingRequires.join(', ')}], Collect fields: [${collectFields.join(', ')}]`);
|
|
346
|
-
|
|
346
|
+
|
|
347
347
|
// Emit batch_stop event (Requirement 11.3)
|
|
348
348
|
this.emitBatchEvent('batch_stop', {
|
|
349
349
|
stepId: step.id,
|
|
@@ -353,26 +353,26 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
353
353
|
});
|
|
354
354
|
break;
|
|
355
355
|
}
|
|
356
|
-
|
|
356
|
+
|
|
357
357
|
// Requirement 1.4: Step doesn't need input, include in batch
|
|
358
358
|
batchSteps.push(stepOptions);
|
|
359
|
-
|
|
359
|
+
|
|
360
360
|
// Log step inclusion with reason (Requirement 11.1)
|
|
361
361
|
logger.debug(`[BatchExecutor] Including step ${step.id} in batch (all requirements satisfied)`);
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
// Emit step_included event (Requirement 11.3)
|
|
364
364
|
this.emitBatchEvent('step_included', {
|
|
365
365
|
stepId: step.id,
|
|
366
366
|
reason: 'All requirements satisfied, no input needed',
|
|
367
367
|
batchSize: batchSteps.length,
|
|
368
368
|
});
|
|
369
|
-
|
|
369
|
+
|
|
370
370
|
// Check if we've reached the max steps limit
|
|
371
371
|
if (batchSteps.length >= maxSteps) {
|
|
372
372
|
stoppedReason = 'max_steps_reached';
|
|
373
|
-
|
|
373
|
+
|
|
374
374
|
logger.debug(`[BatchExecutor] Reached maxStepsPerBatch limit (${maxSteps}), stopping batch`);
|
|
375
|
-
|
|
375
|
+
|
|
376
376
|
this.emitBatchEvent('batch_stop', {
|
|
377
377
|
stepId: step.id,
|
|
378
378
|
reason: `Reached maxStepsPerBatch limit (${maxSteps})`,
|
|
@@ -381,16 +381,16 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
381
381
|
});
|
|
382
382
|
break;
|
|
383
383
|
}
|
|
384
|
-
|
|
384
|
+
|
|
385
385
|
// Move to next step in the sequence
|
|
386
386
|
const transitions = step.getTransitions();
|
|
387
387
|
if (transitions.length === 0) {
|
|
388
388
|
// No more transitions, route is complete
|
|
389
389
|
stoppedReason = 'route_complete';
|
|
390
|
-
|
|
390
|
+
|
|
391
391
|
// Log stopping reason (Requirement 11.2)
|
|
392
392
|
logger.debug(`[BatchExecutor] No more transitions from step ${step.id}, route complete`);
|
|
393
|
-
|
|
393
|
+
|
|
394
394
|
// Emit batch_stop event (Requirement 11.3)
|
|
395
395
|
this.emitBatchEvent('batch_stop', {
|
|
396
396
|
stepId: step.id,
|
|
@@ -400,7 +400,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
400
400
|
});
|
|
401
401
|
break;
|
|
402
402
|
}
|
|
403
|
-
|
|
403
|
+
|
|
404
404
|
// For linear routes, follow the first transition
|
|
405
405
|
// For branching routes, we'd need more complex logic
|
|
406
406
|
const nextStep = transitions[0];
|
|
@@ -414,10 +414,10 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
414
414
|
// Next step is END_ROUTE
|
|
415
415
|
stoppedReason = 'end_route';
|
|
416
416
|
stoppedAtStep = nextStep.toOptions();
|
|
417
|
-
|
|
417
|
+
|
|
418
418
|
// Log stopping reason (Requirement 11.2)
|
|
419
419
|
logger.debug(`[BatchExecutor] Next step is END_ROUTE, stopping batch`);
|
|
420
|
-
|
|
420
|
+
|
|
421
421
|
// Emit batch_stop event (Requirement 11.3)
|
|
422
422
|
this.emitBatchEvent('batch_stop', {
|
|
423
423
|
stepId: nextStep.id,
|
|
@@ -429,11 +429,11 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
431
|
}
|
|
432
|
-
|
|
432
|
+
|
|
433
433
|
// Log batch determination complete with timing (Requirement 11.1, 11.2)
|
|
434
434
|
const determinationTime = Date.now() - startTime;
|
|
435
435
|
logger.debug(`[BatchExecutor] Batch determination complete. Steps: ${batchSteps.length}, Stopped reason: ${stoppedReason}, Time: ${determinationTime}ms`);
|
|
436
|
-
|
|
436
|
+
|
|
437
437
|
return {
|
|
438
438
|
steps: batchSteps,
|
|
439
439
|
stoppedReason,
|
|
@@ -455,13 +455,13 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
455
455
|
async executePrepareHooks(params: ExecuteHooksParams<TContext, TData>): Promise<HookExecutionResult> {
|
|
456
456
|
const { steps, context, data, executeHook } = params;
|
|
457
457
|
const executedSteps: string[] = [];
|
|
458
|
-
|
|
458
|
+
|
|
459
459
|
logger.debug(`[BatchExecutor] Executing prepare hooks for ${steps.length} steps`);
|
|
460
|
-
|
|
460
|
+
|
|
461
461
|
for (const step of steps) {
|
|
462
462
|
if (step.prepare) {
|
|
463
463
|
logger.debug(`[BatchExecutor] Executing prepare hook for step: ${step.id}`);
|
|
464
|
-
|
|
464
|
+
|
|
465
465
|
try {
|
|
466
466
|
await executeHook(step.prepare, context, data, step);
|
|
467
467
|
executedSteps.push(step.id || 'unknown');
|
|
@@ -470,7 +470,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
470
470
|
// Requirement 5.4: Stop on prepare hook failure
|
|
471
471
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
472
472
|
logger.error(`[BatchExecutor] Prepare hook failed for step ${step.id}: ${errorMessage}`);
|
|
473
|
-
|
|
473
|
+
|
|
474
474
|
return {
|
|
475
475
|
success: false,
|
|
476
476
|
executedSteps,
|
|
@@ -484,7 +484,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
|
-
|
|
487
|
+
|
|
488
488
|
logger.debug(`[BatchExecutor] All prepare hooks completed successfully`);
|
|
489
489
|
return {
|
|
490
490
|
success: true,
|
|
@@ -508,13 +508,13 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
508
508
|
const { steps, context, data, executeHook } = params;
|
|
509
509
|
const executedSteps: string[] = [];
|
|
510
510
|
const errors: Array<{ stepId: string; error: BatchExecutionError }> = [];
|
|
511
|
-
|
|
511
|
+
|
|
512
512
|
logger.debug(`[BatchExecutor] Executing finalize hooks for ${steps.length} steps`);
|
|
513
|
-
|
|
513
|
+
|
|
514
514
|
for (const step of steps) {
|
|
515
515
|
if (step.finalize) {
|
|
516
516
|
logger.debug(`[BatchExecutor] Executing finalize hook for step: ${step.id}`);
|
|
517
|
-
|
|
517
|
+
|
|
518
518
|
try {
|
|
519
519
|
await executeHook(step.finalize, context, data, step);
|
|
520
520
|
executedSteps.push(step.id || 'unknown');
|
|
@@ -523,7 +523,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
523
523
|
// Requirement 5.5: Log error and continue with remaining hooks
|
|
524
524
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
525
525
|
logger.error(`[BatchExecutor] Finalize hook failed for step ${step.id}: ${errorMessage}`);
|
|
526
|
-
|
|
526
|
+
|
|
527
527
|
errors.push({
|
|
528
528
|
stepId: step.id || 'unknown',
|
|
529
529
|
error: {
|
|
@@ -533,18 +533,18 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
533
533
|
details: error,
|
|
534
534
|
},
|
|
535
535
|
});
|
|
536
|
-
|
|
536
|
+
|
|
537
537
|
// Continue to next step despite error
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
|
-
|
|
541
|
+
|
|
542
542
|
if (errors.length > 0) {
|
|
543
543
|
logger.warn(`[BatchExecutor] ${errors.length} finalize hook(s) failed, but execution continued`);
|
|
544
544
|
} else {
|
|
545
545
|
logger.debug(`[BatchExecutor] All finalize hooks completed successfully`);
|
|
546
546
|
}
|
|
547
|
-
|
|
547
|
+
|
|
548
548
|
// Always return success for finalize hooks (errors are logged but don't stop execution)
|
|
549
549
|
return {
|
|
550
550
|
success: true,
|
|
@@ -592,36 +592,36 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
592
592
|
* **Validates: Requirements 9.1, 9.2, 9.3, 2.4**
|
|
593
593
|
*/
|
|
594
594
|
async executeBatch(params: ExecuteBatchParams<TContext, TData>): Promise<BatchExecutionResult<TData>> {
|
|
595
|
-
const {
|
|
596
|
-
batch,
|
|
597
|
-
session: initialSession,
|
|
598
|
-
context,
|
|
599
|
-
executeHook,
|
|
600
|
-
generateMessage,
|
|
595
|
+
const {
|
|
596
|
+
batch,
|
|
597
|
+
session: initialSession,
|
|
598
|
+
context,
|
|
599
|
+
executeHook,
|
|
600
|
+
generateMessage,
|
|
601
601
|
schema,
|
|
602
602
|
routeId,
|
|
603
603
|
} = params;
|
|
604
|
-
|
|
604
|
+
|
|
605
605
|
// Track timing for each phase (Requirement 11.1)
|
|
606
606
|
const timing: BatchExecutionTiming = {
|
|
607
607
|
totalMs: 0,
|
|
608
608
|
};
|
|
609
609
|
const batchStartTime = Date.now();
|
|
610
|
-
|
|
610
|
+
|
|
611
611
|
// Track the last successful session state for error recovery
|
|
612
612
|
let lastSuccessfulSession = initialSession;
|
|
613
613
|
let currentSession = initialSession;
|
|
614
|
-
|
|
614
|
+
|
|
615
615
|
// Track executed steps for the response
|
|
616
616
|
const executedSteps: StepRef[] = [];
|
|
617
|
-
|
|
617
|
+
|
|
618
618
|
// Log batch execution start with details (Requirement 11.1)
|
|
619
619
|
logger.debug(`[BatchExecutor] Starting batch execution with ${batch.steps.length} steps, route: ${routeId || 'unknown'}`);
|
|
620
|
-
|
|
620
|
+
|
|
621
621
|
// If batch is empty, return early with appropriate reason
|
|
622
622
|
if (batch.steps.length === 0) {
|
|
623
623
|
logger.debug(`[BatchExecutor] Empty batch, returning with stopped reason: ${batch.stoppedReason}`);
|
|
624
|
-
|
|
624
|
+
|
|
625
625
|
// Emit batch_complete event for empty batch (Requirement 11.3)
|
|
626
626
|
timing.totalMs = Date.now() - batchStartTime;
|
|
627
627
|
this.emitBatchEvent('batch_complete', {
|
|
@@ -630,7 +630,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
630
630
|
reason: 'Empty batch',
|
|
631
631
|
timing,
|
|
632
632
|
});
|
|
633
|
-
|
|
633
|
+
|
|
634
634
|
return {
|
|
635
635
|
message: '',
|
|
636
636
|
session: currentSession,
|
|
@@ -639,26 +639,26 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
639
639
|
collectedData: {},
|
|
640
640
|
};
|
|
641
641
|
}
|
|
642
|
-
|
|
642
|
+
|
|
643
643
|
// PHASE 1: Execute prepare hooks (Requirement 5.4 - stop on failure)
|
|
644
644
|
const prepareStartTime = Date.now();
|
|
645
645
|
logger.debug(`[BatchExecutor] Phase 1: Executing prepare hooks`);
|
|
646
|
-
|
|
646
|
+
|
|
647
647
|
const prepareResult = await this.executePrepareHooks({
|
|
648
648
|
steps: batch.steps,
|
|
649
649
|
context,
|
|
650
650
|
data: currentSession.data,
|
|
651
651
|
executeHook,
|
|
652
652
|
});
|
|
653
|
-
|
|
653
|
+
|
|
654
654
|
timing.prepareHooksMs = Date.now() - prepareStartTime;
|
|
655
655
|
logger.debug(`[BatchExecutor] Prepare hooks completed in ${timing.prepareHooksMs}ms`);
|
|
656
|
-
|
|
656
|
+
|
|
657
657
|
if (!prepareResult.success) {
|
|
658
658
|
// Requirement 9.3: Preserve partial progress on errors
|
|
659
659
|
// Requirement 2.4: Stop and include error information
|
|
660
660
|
logger.error(`[BatchExecutor] Prepare hook failed:`, prepareResult.error);
|
|
661
|
-
|
|
661
|
+
|
|
662
662
|
// Emit batch_complete event with error (Requirement 11.3)
|
|
663
663
|
timing.totalMs = Date.now() - batchStartTime;
|
|
664
664
|
this.emitBatchEvent('batch_complete', {
|
|
@@ -667,7 +667,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
667
667
|
reason: `Prepare hook failed: ${prepareResult.error?.message}`,
|
|
668
668
|
timing,
|
|
669
669
|
});
|
|
670
|
-
|
|
670
|
+
|
|
671
671
|
return {
|
|
672
672
|
message: '',
|
|
673
673
|
session: lastSuccessfulSession, // Return last successful state
|
|
@@ -679,22 +679,22 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
679
679
|
error: prepareResult.error,
|
|
680
680
|
};
|
|
681
681
|
}
|
|
682
|
-
|
|
682
|
+
|
|
683
683
|
// Update last successful session after prepare hooks complete
|
|
684
684
|
lastSuccessfulSession = currentSession;
|
|
685
|
-
|
|
685
|
+
|
|
686
686
|
// PHASE 2: Make LLM call (Requirement 9.1 - preserve session state on failure)
|
|
687
687
|
const llmStartTime = Date.now();
|
|
688
688
|
logger.debug(`[BatchExecutor] Phase 2: Making LLM call`);
|
|
689
|
-
|
|
689
|
+
|
|
690
690
|
let llmResponse: Record<string, unknown>;
|
|
691
691
|
let message: string;
|
|
692
|
-
|
|
692
|
+
|
|
693
693
|
try {
|
|
694
694
|
const result = await generateMessage();
|
|
695
695
|
llmResponse = result.structured || {};
|
|
696
696
|
message = result.message || '';
|
|
697
|
-
|
|
697
|
+
|
|
698
698
|
timing.llmCallMs = Date.now() - llmStartTime;
|
|
699
699
|
logger.debug(`[BatchExecutor] LLM call successful in ${timing.llmCallMs}ms`);
|
|
700
700
|
} catch (error) {
|
|
@@ -702,7 +702,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
702
702
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
703
703
|
timing.llmCallMs = Date.now() - llmStartTime;
|
|
704
704
|
logger.error(`[BatchExecutor] LLM call failed after ${timing.llmCallMs}ms:`, errorMessage);
|
|
705
|
-
|
|
705
|
+
|
|
706
706
|
// Emit batch_complete event with error (Requirement 11.3)
|
|
707
707
|
timing.totalMs = Date.now() - batchStartTime;
|
|
708
708
|
this.emitBatchEvent('batch_complete', {
|
|
@@ -711,7 +711,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
711
711
|
reason: `LLM call failed: ${errorMessage}`,
|
|
712
712
|
timing,
|
|
713
713
|
});
|
|
714
|
-
|
|
714
|
+
|
|
715
715
|
return {
|
|
716
716
|
message: '',
|
|
717
717
|
session: lastSuccessfulSession, // Preserve session state
|
|
@@ -724,50 +724,50 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
724
724
|
},
|
|
725
725
|
};
|
|
726
726
|
}
|
|
727
|
-
|
|
727
|
+
|
|
728
728
|
// Update last successful session after LLM call
|
|
729
729
|
lastSuccessfulSession = currentSession;
|
|
730
|
-
|
|
730
|
+
|
|
731
731
|
// PHASE 3: Collect and validate data (Requirement 9.2 - include validation errors)
|
|
732
732
|
const collectStartTime = Date.now();
|
|
733
733
|
logger.debug(`[BatchExecutor] Phase 3: Collecting and validating data`);
|
|
734
|
-
|
|
734
|
+
|
|
735
735
|
const collectResult = this.collectBatchData({
|
|
736
736
|
steps: batch.steps,
|
|
737
737
|
llmResponse,
|
|
738
738
|
session: currentSession,
|
|
739
739
|
schema,
|
|
740
740
|
});
|
|
741
|
-
|
|
741
|
+
|
|
742
742
|
timing.dataCollectionMs = Date.now() - collectStartTime;
|
|
743
743
|
logger.debug(`[BatchExecutor] Data collection completed in ${timing.dataCollectionMs}ms`);
|
|
744
|
-
|
|
744
|
+
|
|
745
745
|
// Update session with collected data (even if validation failed)
|
|
746
746
|
currentSession = collectResult.session;
|
|
747
|
-
|
|
747
|
+
|
|
748
748
|
// Track collected data for response
|
|
749
749
|
const collectedData = collectResult.collectedData;
|
|
750
|
-
|
|
750
|
+
|
|
751
751
|
// Check for validation errors
|
|
752
752
|
let validationError: BatchExecutionError | undefined;
|
|
753
753
|
if (!collectResult.success && collectResult.validationErrors && collectResult.validationErrors.length > 0) {
|
|
754
754
|
// Requirement 9.2: Include validation errors in response
|
|
755
755
|
logger.warn(`[BatchExecutor] Data validation failed:`, collectResult.validationErrors);
|
|
756
|
-
|
|
756
|
+
|
|
757
757
|
validationError = {
|
|
758
758
|
type: 'data_validation',
|
|
759
759
|
message: `Validation failed for ${collectResult.validationErrors.length} field(s): ${collectResult.validationErrors.map(e => e.field).join(', ')}`,
|
|
760
760
|
details: collectResult.validationErrors,
|
|
761
761
|
};
|
|
762
|
-
|
|
762
|
+
|
|
763
763
|
// Note: We continue execution despite validation errors
|
|
764
764
|
// The error is included in the response for the caller to handle
|
|
765
765
|
}
|
|
766
|
-
|
|
766
|
+
|
|
767
767
|
// Update last successful session after data collection
|
|
768
768
|
// (even with validation errors, we preserve the collected data)
|
|
769
769
|
lastSuccessfulSession = currentSession;
|
|
770
|
-
|
|
770
|
+
|
|
771
771
|
// Build executed steps list
|
|
772
772
|
for (const step of batch.steps) {
|
|
773
773
|
if (step.id) {
|
|
@@ -777,26 +777,26 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
777
777
|
});
|
|
778
778
|
}
|
|
779
779
|
}
|
|
780
|
-
|
|
780
|
+
|
|
781
781
|
// PHASE 4: Execute finalize hooks (Requirement 5.5 - continue on failure)
|
|
782
782
|
const finalizeStartTime = Date.now();
|
|
783
783
|
logger.debug(`[BatchExecutor] Phase 4: Executing finalize hooks`);
|
|
784
|
-
|
|
784
|
+
|
|
785
785
|
const finalizeResult = await this.executeFinalizeHooks({
|
|
786
786
|
steps: batch.steps,
|
|
787
787
|
context,
|
|
788
788
|
data: currentSession.data,
|
|
789
789
|
executeHook,
|
|
790
790
|
});
|
|
791
|
-
|
|
791
|
+
|
|
792
792
|
timing.finalizeHooksMs = Date.now() - finalizeStartTime;
|
|
793
793
|
logger.debug(`[BatchExecutor] Finalize hooks completed in ${timing.finalizeHooksMs}ms`);
|
|
794
|
-
|
|
794
|
+
|
|
795
795
|
// Log finalize errors but don't fail the batch
|
|
796
796
|
let finalizeError: BatchExecutionError | undefined;
|
|
797
797
|
if (finalizeResult.errors && finalizeResult.errors.length > 0) {
|
|
798
798
|
logger.warn(`[BatchExecutor] Some finalize hooks failed:`, finalizeResult.errors);
|
|
799
|
-
|
|
799
|
+
|
|
800
800
|
// Create a summary error for finalize failures
|
|
801
801
|
finalizeError = {
|
|
802
802
|
type: 'finalize_hook',
|
|
@@ -804,12 +804,12 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
804
804
|
details: finalizeResult.errors,
|
|
805
805
|
};
|
|
806
806
|
}
|
|
807
|
-
|
|
807
|
+
|
|
808
808
|
// Determine the final stopped reason
|
|
809
809
|
// Priority: validation_error > finalize_error > batch.stoppedReason
|
|
810
810
|
let finalStoppedReason: StoppedReason = batch.stoppedReason;
|
|
811
811
|
let finalError: BatchExecutionError | undefined;
|
|
812
|
-
|
|
812
|
+
|
|
813
813
|
if (validationError) {
|
|
814
814
|
finalStoppedReason = 'validation_error';
|
|
815
815
|
finalError = validationError;
|
|
@@ -818,11 +818,11 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
818
818
|
// but include the error in the response
|
|
819
819
|
finalError = finalizeError;
|
|
820
820
|
}
|
|
821
|
-
|
|
821
|
+
|
|
822
822
|
// Calculate total time and log completion (Requirement 11.1, 11.2)
|
|
823
823
|
timing.totalMs = Date.now() - batchStartTime;
|
|
824
824
|
logger.debug(`[BatchExecutor] Batch execution complete. Stopped reason: ${finalStoppedReason}, Executed steps: ${executedSteps.length}, Total time: ${timing.totalMs}ms`);
|
|
825
|
-
|
|
825
|
+
|
|
826
826
|
// Emit batch_complete event (Requirement 11.3)
|
|
827
827
|
this.emitBatchEvent('batch_complete', {
|
|
828
828
|
batchSize: executedSteps.length,
|
|
@@ -830,7 +830,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
830
830
|
reason: `Batch completed with ${executedSteps.length} steps`,
|
|
831
831
|
timing,
|
|
832
832
|
});
|
|
833
|
-
|
|
833
|
+
|
|
834
834
|
return {
|
|
835
835
|
message,
|
|
836
836
|
session: currentSession,
|
|
@@ -857,9 +857,9 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
857
857
|
*/
|
|
858
858
|
collectBatchData(params: CollectBatchDataParams<TData>): CollectBatchDataResult<TData> {
|
|
859
859
|
const { steps, llmResponse, session, schema } = params;
|
|
860
|
-
|
|
860
|
+
|
|
861
861
|
logger.debug(`[BatchExecutor] Collecting batch data from ${steps.length} steps`);
|
|
862
|
-
|
|
862
|
+
|
|
863
863
|
// Requirement 6.1: Gather all collect fields from all steps in the batch
|
|
864
864
|
const allCollectFields = new Set<string>();
|
|
865
865
|
for (const step of steps) {
|
|
@@ -869,9 +869,9 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
871
|
}
|
|
872
|
-
|
|
872
|
+
|
|
873
873
|
logger.debug(`[BatchExecutor] Collect fields to extract: ${Array.from(allCollectFields).join(', ')}`);
|
|
874
|
-
|
|
874
|
+
|
|
875
875
|
// If no fields to collect, return early with unchanged session
|
|
876
876
|
if (allCollectFields.size === 0) {
|
|
877
877
|
logger.debug(`[BatchExecutor] No collect fields defined, skipping data collection`);
|
|
@@ -882,12 +882,12 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
882
882
|
fieldsCollected: [],
|
|
883
883
|
};
|
|
884
884
|
}
|
|
885
|
-
|
|
885
|
+
|
|
886
886
|
// Extract data from LLM response for all collect fields
|
|
887
887
|
const collectedData: Partial<TData> = {};
|
|
888
888
|
const fieldsCollected: string[] = [];
|
|
889
889
|
const fieldsMissing: string[] = [];
|
|
890
|
-
|
|
890
|
+
|
|
891
891
|
for (const field of allCollectFields) {
|
|
892
892
|
// Check if the field exists in the LLM response
|
|
893
893
|
if (field in llmResponse && llmResponse[field] !== undefined) {
|
|
@@ -899,20 +899,20 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
899
899
|
logger.debug(`[BatchExecutor] Field '${field}' not found in LLM response`);
|
|
900
900
|
}
|
|
901
901
|
}
|
|
902
|
-
|
|
902
|
+
|
|
903
903
|
// Requirement 6.2: Validate collected data against the agent schema
|
|
904
904
|
const validationErrors: ValidationError[] = [];
|
|
905
|
-
|
|
905
|
+
|
|
906
906
|
if (schema && Object.keys(collectedData).length > 0) {
|
|
907
907
|
logger.debug(`[BatchExecutor] Validating collected data against schema`);
|
|
908
|
-
|
|
908
|
+
|
|
909
909
|
const validationResult = this.validateAgainstSchema(collectedData, schema);
|
|
910
910
|
if (!validationResult.valid) {
|
|
911
911
|
validationErrors.push(...validationResult.errors);
|
|
912
912
|
logger.warn(`[BatchExecutor] Schema validation found ${validationErrors.length} error(s)`);
|
|
913
913
|
}
|
|
914
914
|
}
|
|
915
|
-
|
|
915
|
+
|
|
916
916
|
// Requirement 6.3: Update session data with all collected values
|
|
917
917
|
// Only merge valid data (data that passed validation or had no schema to validate against)
|
|
918
918
|
let updatedSession = session;
|
|
@@ -922,11 +922,11 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
922
922
|
updatedSession = mergeCollected(session, collectedData);
|
|
923
923
|
logger.debug(`[BatchExecutor] Updated session with collected data`);
|
|
924
924
|
}
|
|
925
|
-
|
|
925
|
+
|
|
926
926
|
const success = validationErrors.length === 0;
|
|
927
|
-
|
|
927
|
+
|
|
928
928
|
logger.debug(`[BatchExecutor] Data collection complete. Success: ${success}, Fields collected: ${fieldsCollected.length}, Fields missing: ${fieldsMissing.length}`);
|
|
929
|
-
|
|
929
|
+
|
|
930
930
|
return {
|
|
931
931
|
success,
|
|
932
932
|
collectedData,
|
|
@@ -956,7 +956,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
956
956
|
schema: StructuredSchema
|
|
957
957
|
): { valid: boolean; errors: ValidationError[] } {
|
|
958
958
|
const errors: ValidationError[] = [];
|
|
959
|
-
|
|
959
|
+
|
|
960
960
|
// Check if provided fields exist in schema
|
|
961
961
|
if (schema.properties) {
|
|
962
962
|
for (const [key, value] of Object.entries(data)) {
|
|
@@ -977,7 +977,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
977
977
|
}
|
|
978
978
|
}
|
|
979
979
|
}
|
|
980
|
-
|
|
980
|
+
|
|
981
981
|
return {
|
|
982
982
|
valid: errors.length === 0,
|
|
983
983
|
errors,
|
|
@@ -997,18 +997,18 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
997
997
|
// Null/undefined values are handled separately (required field check)
|
|
998
998
|
return null;
|
|
999
999
|
}
|
|
1000
|
-
|
|
1000
|
+
|
|
1001
1001
|
const expectedType = fieldSchema.type;
|
|
1002
1002
|
if (!expectedType) {
|
|
1003
1003
|
// No type specified, consider valid
|
|
1004
1004
|
return null;
|
|
1005
1005
|
}
|
|
1006
|
-
|
|
1006
|
+
|
|
1007
1007
|
const actualType = Array.isArray(value) ? 'array' : typeof value;
|
|
1008
|
-
|
|
1008
|
+
|
|
1009
1009
|
// Handle array of types
|
|
1010
1010
|
const allowedTypes = Array.isArray(expectedType) ? expectedType : [expectedType];
|
|
1011
|
-
|
|
1011
|
+
|
|
1012
1012
|
// Map JavaScript types to JSON Schema types
|
|
1013
1013
|
const typeMapping: Record<string, string> = {
|
|
1014
1014
|
'string': 'string',
|
|
@@ -1017,9 +1017,9 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
1017
1017
|
'object': 'object',
|
|
1018
1018
|
'array': 'array',
|
|
1019
1019
|
};
|
|
1020
|
-
|
|
1020
|
+
|
|
1021
1021
|
const mappedActualType = typeMapping[actualType] || actualType;
|
|
1022
|
-
|
|
1022
|
+
|
|
1023
1023
|
// Check if actual type matches any allowed type
|
|
1024
1024
|
// Also handle 'integer' as a valid number type
|
|
1025
1025
|
const isValidType = allowedTypes.some(t => {
|
|
@@ -1028,7 +1028,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
1028
1028
|
}
|
|
1029
1029
|
return t === mappedActualType;
|
|
1030
1030
|
});
|
|
1031
|
-
|
|
1031
|
+
|
|
1032
1032
|
if (!isValidType) {
|
|
1033
1033
|
return {
|
|
1034
1034
|
field,
|
|
@@ -1037,7 +1037,7 @@ export class BatchExecutor<TContext = unknown, TData = unknown> {
|
|
|
1037
1037
|
schemaPath: `properties.${field}.type`,
|
|
1038
1038
|
};
|
|
1039
1039
|
}
|
|
1040
|
-
|
|
1040
|
+
|
|
1041
1041
|
return null;
|
|
1042
1042
|
}
|
|
1043
1043
|
}
|
|
@@ -1068,7 +1068,7 @@ export interface ExecuteHooksParams<TContext, TData> {
|
|
|
1068
1068
|
/**
|
|
1069
1069
|
* Type for the hook execution function
|
|
1070
1070
|
*/
|
|
1071
|
-
export type HookFunction<TContext, TData> =
|
|
1071
|
+
export type HookFunction<TContext, TData> =
|
|
1072
1072
|
| string
|
|
1073
1073
|
| Tool<TContext, TData>
|
|
1074
1074
|
| ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
|