@node-llm/core 1.16.2 → 1.17.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.
- package/dist/agent/Agent.d.ts +3 -0
- package/dist/agent/Agent.d.ts.map +1 -1
- package/dist/agent/Agent.js +3 -0
- package/dist/aliases.d.ts +33 -9
- package/dist/aliases.d.ts.map +1 -1
- package/dist/aliases.js +34 -10
- package/dist/chat/Chat.d.ts +16 -5
- package/dist/chat/Chat.d.ts.map +1 -1
- package/dist/chat/Chat.js +113 -78
- package/dist/chat/ChatOptions.d.ts +19 -0
- package/dist/chat/ChatOptions.d.ts.map +1 -1
- package/dist/chat/ChatStream.d.ts.map +1 -1
- package/dist/chat/ChatStream.js +69 -58
- package/dist/chat/ToolCallOutcome.d.ts +30 -0
- package/dist/chat/ToolCallOutcome.d.ts.map +1 -0
- package/dist/chat/ToolCallOutcome.js +43 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/llm.d.ts +1 -1
- package/dist/llm.d.ts.map +1 -1
- package/dist/models/models.json +1464 -1014
- package/dist/providers/bedrock/BedrockProvider.js +1 -1
- package/dist/providers/bedrock/Chat.js +1 -1
- package/dist/providers/bedrock/Embeddings.js +1 -1
- package/dist/providers/bedrock/Image.js +1 -1
- package/dist/providers/bedrock/Moderation.js +1 -1
- package/dist/providers/bedrock/Streaming.js +1 -1
- package/dist/providers/bedrock/config.d.ts +9 -1
- package/dist/providers/bedrock/config.d.ts.map +1 -1
- package/dist/providers/bedrock/config.js +4 -2
- package/dist/providers/bedrock/index.d.ts.map +1 -1
- package/dist/providers/bedrock/index.js +1 -0
- package/dist/utils/handler-stacking.d.ts +31 -0
- package/dist/utils/handler-stacking.d.ts.map +1 -0
- package/dist/utils/handler-stacking.js +66 -0
- package/package.json +13 -10
package/dist/chat/Chat.js
CHANGED
|
@@ -12,8 +12,10 @@ import { ToolExecutionMode } from "../constants.js";
|
|
|
12
12
|
import { ConfigurationError } from "../errors/index.js";
|
|
13
13
|
import { ChatValidator } from "./Validation.js";
|
|
14
14
|
import { ToolHandler } from "./ToolHandler.js";
|
|
15
|
+
import { shouldRunToolCallsConcurrently, executeToolCallOutcomes } from "./ToolCallOutcome.js";
|
|
15
16
|
import { logger } from "../utils/logger.js";
|
|
16
17
|
import { runMiddleware } from "../utils/middleware-runner.js";
|
|
18
|
+
import { collectHandlers, runAllHandlers, runDirectiveHandlers, runConfirmHandlers, runChainHandlers } from "../utils/handler-stacking.js";
|
|
17
19
|
import { ChatResponseString } from "./ChatResponse.js";
|
|
18
20
|
export class Chat {
|
|
19
21
|
provider;
|
|
@@ -45,6 +47,9 @@ export class Chat {
|
|
|
45
47
|
if (!this.options.toolExecution) {
|
|
46
48
|
this.options.toolExecution = config.toolExecution || ToolExecutionMode.AUTO;
|
|
47
49
|
}
|
|
50
|
+
if (this.options.toolConcurrency === undefined) {
|
|
51
|
+
this.options.toolConcurrency = config.toolConcurrency;
|
|
52
|
+
}
|
|
48
53
|
if (options.tools) {
|
|
49
54
|
const toolList = options.tools;
|
|
50
55
|
this.options.tools = []; // Clear and re-add via normalized method
|
|
@@ -285,11 +290,11 @@ export class Chat {
|
|
|
285
290
|
}
|
|
286
291
|
// --- Event Handlers ---
|
|
287
292
|
onNewMessage(handler) {
|
|
288
|
-
this.options.
|
|
293
|
+
this.options.onNewMessageHandlers = [...(this.options.onNewMessageHandlers ?? []), handler];
|
|
289
294
|
return this;
|
|
290
295
|
}
|
|
291
296
|
onEndMessage(handler) {
|
|
292
|
-
this.options.
|
|
297
|
+
this.options.onEndMessageHandlers = [...(this.options.onEndMessageHandlers ?? []), handler];
|
|
293
298
|
return this;
|
|
294
299
|
}
|
|
295
300
|
onToolCall(handler) {
|
|
@@ -299,21 +304,29 @@ export class Chat {
|
|
|
299
304
|
return this.onToolCallEnd((_call, result) => handler(result));
|
|
300
305
|
}
|
|
301
306
|
/**
|
|
302
|
-
* Called when a tool call starts.
|
|
307
|
+
* Called when a tool call starts. Calling this more than once registers
|
|
308
|
+
* additional handlers rather than replacing the previous one.
|
|
303
309
|
*/
|
|
304
310
|
onToolCallStart(handler) {
|
|
305
|
-
this.options.
|
|
311
|
+
this.options.onToolCallStartHandlers = [
|
|
312
|
+
...(this.options.onToolCallStartHandlers ?? []),
|
|
313
|
+
handler
|
|
314
|
+
];
|
|
306
315
|
return this;
|
|
307
316
|
}
|
|
308
317
|
/**
|
|
309
|
-
* Called when a tool call ends successfully.
|
|
318
|
+
* Called when a tool call ends successfully. Calling this more than once
|
|
319
|
+
* registers additional handlers rather than replacing the previous one.
|
|
310
320
|
*/
|
|
311
321
|
onToolCallEnd(handler) {
|
|
312
|
-
this.options.
|
|
322
|
+
this.options.onToolCallEndHandlers = [...(this.options.onToolCallEndHandlers ?? []), handler];
|
|
313
323
|
return this;
|
|
314
324
|
}
|
|
315
325
|
onToolCallError(handler) {
|
|
316
|
-
this.options.
|
|
326
|
+
this.options.onToolCallErrorHandlers = [
|
|
327
|
+
...(this.options.onToolCallErrorHandlers ?? []),
|
|
328
|
+
handler
|
|
329
|
+
];
|
|
317
330
|
return this;
|
|
318
331
|
}
|
|
319
332
|
/**
|
|
@@ -326,28 +339,49 @@ export class Chat {
|
|
|
326
339
|
this.options.toolExecution = mode;
|
|
327
340
|
return this;
|
|
328
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Enable or disable concurrent execution of independent tool calls
|
|
344
|
+
* returned in the same turn. Disabled ("confirm" mode always runs
|
|
345
|
+
* sequentially since approval is interactive).
|
|
346
|
+
*/
|
|
347
|
+
withToolConcurrency(enabled) {
|
|
348
|
+
this.options.toolConcurrency = enabled;
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
329
351
|
/**
|
|
330
352
|
* Hook for confirming tool execution in "confirm" mode.
|
|
331
|
-
* Return true to proceed, false to cancel the specific call.
|
|
353
|
+
* Return true to proceed, false to cancel the specific call. When multiple
|
|
354
|
+
* handlers are registered, every one of them must approve.
|
|
332
355
|
*/
|
|
333
356
|
onConfirmToolCall(handler) {
|
|
334
|
-
this.options.
|
|
357
|
+
this.options.onConfirmToolCallHandlers = [
|
|
358
|
+
...(this.options.onConfirmToolCallHandlers ?? []),
|
|
359
|
+
handler
|
|
360
|
+
];
|
|
335
361
|
return this;
|
|
336
362
|
}
|
|
337
363
|
/**
|
|
338
364
|
* Add a hook to process messages before sending to the LLM.
|
|
339
|
-
* Useful for PII detection, redaction, and input moderation.
|
|
365
|
+
* Useful for PII detection, redaction, and input moderation. Multiple
|
|
366
|
+
* hooks chain: each one's output feeds the next.
|
|
340
367
|
*/
|
|
341
368
|
beforeRequest(handler) {
|
|
342
|
-
this.options.
|
|
369
|
+
this.options.onBeforeRequestHandlers = [
|
|
370
|
+
...(this.options.onBeforeRequestHandlers ?? []),
|
|
371
|
+
handler
|
|
372
|
+
];
|
|
343
373
|
return this;
|
|
344
374
|
}
|
|
345
375
|
/**
|
|
346
376
|
* Add a hook to process the response before returning it.
|
|
347
|
-
* Useful for output redaction, compliance, and post-moderation.
|
|
377
|
+
* Useful for output redaction, compliance, and post-moderation. Multiple
|
|
378
|
+
* hooks chain: each one's output feeds the next.
|
|
348
379
|
*/
|
|
349
380
|
afterResponse(handler) {
|
|
350
|
-
this.options.
|
|
381
|
+
this.options.onAfterResponseHandlers = [
|
|
382
|
+
...(this.options.onAfterResponseHandlers ?? []),
|
|
383
|
+
handler
|
|
384
|
+
];
|
|
351
385
|
return this;
|
|
352
386
|
}
|
|
353
387
|
/**
|
|
@@ -398,6 +432,23 @@ export class Chat {
|
|
|
398
432
|
options: this.options,
|
|
399
433
|
state
|
|
400
434
|
};
|
|
435
|
+
const newMessageHandlers = collectHandlers(this.options.onNewMessage, this.options.onNewMessageHandlers);
|
|
436
|
+
const endMessageHandlers = collectHandlers(this.options.onEndMessage, this.options.onEndMessageHandlers);
|
|
437
|
+
const beforeRequestHandlers = collectHandlers(this.options.onBeforeRequest, this.options.onBeforeRequestHandlers);
|
|
438
|
+
const afterResponseHandlers = collectHandlers(this.options.onAfterResponse, this.options.onAfterResponseHandlers);
|
|
439
|
+
const toolCallStartHandlers = collectHandlers(this.options.onToolCallStart, this.options.onToolCallStartHandlers);
|
|
440
|
+
const toolCallEndHandlers = collectHandlers(this.options.onToolCallEnd, this.options.onToolCallEndHandlers);
|
|
441
|
+
const toolCallErrorHandlers = collectHandlers(this.options.onToolCallError, this.options.onToolCallErrorHandlers);
|
|
442
|
+
const confirmToolCallHandlers = collectHandlers(this.options.onConfirmToolCall, this.options.onConfirmToolCallHandlers);
|
|
443
|
+
const combinedToolCallStart = toolCallStartHandlers.length
|
|
444
|
+
? (call) => toolCallStartHandlers.forEach((handler) => handler(call))
|
|
445
|
+
: undefined;
|
|
446
|
+
const combinedToolCallEnd = toolCallEndHandlers.length
|
|
447
|
+
? (call, result) => toolCallEndHandlers.forEach((handler) => handler(call, result))
|
|
448
|
+
: undefined;
|
|
449
|
+
const combinedConfirmToolCall = confirmToolCallHandlers.length
|
|
450
|
+
? (call) => runConfirmHandlers(confirmToolCallHandlers, call)
|
|
451
|
+
: undefined;
|
|
401
452
|
try {
|
|
402
453
|
// 1. onRequest Hook
|
|
403
454
|
await runMiddleware(this.middlewares, "onRequest", context);
|
|
@@ -426,12 +477,7 @@ export class Chat {
|
|
|
426
477
|
...this.options.params
|
|
427
478
|
};
|
|
428
479
|
// --- Content Policy Hooks (Input) ---
|
|
429
|
-
|
|
430
|
-
const result = await this.options.onBeforeRequest(executeOptions.messages);
|
|
431
|
-
if (result) {
|
|
432
|
-
executeOptions.messages = result;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
480
|
+
executeOptions.messages = await runChainHandlers(beforeRequestHandlers, executeOptions.messages);
|
|
435
481
|
const trackUsage = (u) => {
|
|
436
482
|
if (u) {
|
|
437
483
|
if (u.cost === undefined) {
|
|
@@ -458,18 +504,12 @@ export class Chat {
|
|
|
458
504
|
}
|
|
459
505
|
};
|
|
460
506
|
// Start generation
|
|
461
|
-
|
|
462
|
-
this.options.onNewMessage();
|
|
507
|
+
await runAllHandlers(newMessageHandlers);
|
|
463
508
|
let response = await this.executor.executeChat(executeOptions);
|
|
464
509
|
trackUsage(response.usage);
|
|
465
510
|
assistantMessage = new ChatResponseString(response.content ?? "", response.usage ?? { input_tokens: 0, output_tokens: 0, total_tokens: 0 }, this.model, this.provider.id, response.thinking, response.reasoning, response.tool_calls, response.finish_reason, this.options.schema, response.metadata, response.attachments);
|
|
466
511
|
// --- Content Policy Hooks (Output - Turn 1) ---
|
|
467
|
-
|
|
468
|
-
const result = await this.options.onAfterResponse(assistantMessage);
|
|
469
|
-
if (result) {
|
|
470
|
-
assistantMessage = result;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
512
|
+
assistantMessage = await runChainHandlers(afterResponseHandlers, assistantMessage);
|
|
473
513
|
// Add to history (temporary, might be rolled back on retry)
|
|
474
514
|
this.messages.push({
|
|
475
515
|
role: "assistant",
|
|
@@ -477,9 +517,8 @@ export class Chat {
|
|
|
477
517
|
tool_calls: response.tool_calls,
|
|
478
518
|
usage: response.usage
|
|
479
519
|
});
|
|
480
|
-
if (
|
|
481
|
-
(
|
|
482
|
-
this.options.onEndMessage(assistantMessage);
|
|
520
|
+
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
521
|
+
await runAllHandlers(endMessageHandlers, assistantMessage);
|
|
483
522
|
}
|
|
484
523
|
const maxToolCalls = options?.maxToolCalls ?? this.options.maxToolCalls ?? 5;
|
|
485
524
|
let stepCount = 0;
|
|
@@ -493,55 +532,56 @@ export class Chat {
|
|
|
493
532
|
if (stepCount > maxToolCalls) {
|
|
494
533
|
throw new Error(`[NodeLLM] Maximum tool execution calls (${maxToolCalls}) exceeded.`);
|
|
495
534
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
535
|
+
const runConcurrently = shouldRunToolCallsConcurrently(this.options.toolConcurrency, this.options.toolExecution, response.tool_calls.length);
|
|
536
|
+
const outcomes = await executeToolCallOutcomes(response.tool_calls, {
|
|
537
|
+
...this.options,
|
|
538
|
+
tools: this.options.tools,
|
|
539
|
+
onToolCallStart: combinedToolCallStart,
|
|
540
|
+
onToolCallEnd: combinedToolCallEnd,
|
|
541
|
+
onConfirmToolCall: combinedConfirmToolCall
|
|
542
|
+
}, this.middlewares, context, runConcurrently);
|
|
543
|
+
for (const outcome of outcomes) {
|
|
544
|
+
const toolCall = outcome.toolCall;
|
|
545
|
+
if (outcome.kind === "cancelled") {
|
|
546
|
+
this.messages.push(this.provider.formatToolResultMessage(toolCall.id, "Action cancelled by user."));
|
|
547
|
+
continue;
|
|
503
548
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const toolResult = await ToolHandler.execute(toolCall, this.options.tools, this.options.onToolCallStart, this.options.onToolCallEnd);
|
|
507
|
-
await runMiddleware(this.middlewares, "onToolCallEnd", context, toolCall, toolResult.content);
|
|
549
|
+
if (outcome.kind === "success") {
|
|
550
|
+
const { toolResult } = outcome;
|
|
508
551
|
this.messages.push(this.provider.formatToolResultMessage(toolResult.tool_call_id, toolResult.content));
|
|
509
552
|
if (toolResult.halted) {
|
|
510
553
|
haltTriggered = true;
|
|
511
554
|
assistantMessage = new ChatResponseString(toolResult.content, totalUsage, this.model, this.provider.id, undefined, undefined, undefined, "tool_halt");
|
|
512
|
-
|
|
513
|
-
this.options.onEndMessage(assistantMessage);
|
|
514
|
-
}
|
|
555
|
+
await runAllHandlers(endMessageHandlers, assistantMessage);
|
|
515
556
|
break;
|
|
516
557
|
}
|
|
558
|
+
continue;
|
|
517
559
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
this.messages.push(this.provider.formatToolResultMessage(toolResult.tool_call_id, toolResult.content));
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
catch (retryError) {
|
|
533
|
-
currentError = retryError;
|
|
534
|
-
await runMiddleware(this.middlewares, "onToolCallError", context, toolCall, currentError);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
this.messages.push(this.provider.formatToolResultMessage(toolCall.id, `Fatal error executing tool '${toolCall.function.name}': ${currentError.message}`, { isError: true }));
|
|
538
|
-
if (directive === "CONTINUE")
|
|
560
|
+
let currentError = outcome.error;
|
|
561
|
+
const middlewareDirective = await runMiddleware(this.middlewares, "onToolCallError", context, toolCall, currentError);
|
|
562
|
+
const directive = middlewareDirective ||
|
|
563
|
+
(await runDirectiveHandlers(toolCallErrorHandlers, toolCall, currentError));
|
|
564
|
+
if (directive === "STOP")
|
|
565
|
+
throw currentError;
|
|
566
|
+
if (directive === "RETRY") {
|
|
567
|
+
try {
|
|
568
|
+
const toolResult = await ToolHandler.execute(toolCall, this.options.tools, combinedToolCallStart, combinedToolCallEnd);
|
|
569
|
+
await runMiddleware(this.middlewares, "onToolCallEnd", context, toolCall, toolResult.content);
|
|
570
|
+
this.messages.push(this.provider.formatToolResultMessage(toolResult.tool_call_id, toolResult.content));
|
|
539
571
|
continue;
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
572
|
+
}
|
|
573
|
+
catch (retryError) {
|
|
574
|
+
currentError = retryError;
|
|
575
|
+
await runMiddleware(this.middlewares, "onToolCallError", context, toolCall, currentError);
|
|
576
|
+
}
|
|
544
577
|
}
|
|
578
|
+
this.messages.push(this.provider.formatToolResultMessage(toolCall.id, `Fatal error executing tool '${toolCall.function.name}': ${currentError.message}`, { isError: true }));
|
|
579
|
+
if (directive === "CONTINUE")
|
|
580
|
+
continue;
|
|
581
|
+
const errorObj = currentError;
|
|
582
|
+
if (errorObj.fatal || errorObj.status === 401 || errorObj.status === 403)
|
|
583
|
+
throw currentError;
|
|
584
|
+
logger.error(`Tool execution failed:`, currentError);
|
|
545
585
|
}
|
|
546
586
|
if (haltTriggered)
|
|
547
587
|
break;
|
|
@@ -562,23 +602,18 @@ export class Chat {
|
|
|
562
602
|
});
|
|
563
603
|
trackUsage(response.usage);
|
|
564
604
|
assistantMessage = new ChatResponseString(response.content ?? "", response.usage ?? { input_tokens: 0, output_tokens: 0, total_tokens: 0 }, this.model, this.provider.id, response.thinking, response.reasoning, response.tool_calls, response.finish_reason, this.options.schema, response.metadata, response.attachments);
|
|
565
|
-
|
|
566
|
-
const result = await this.options.onAfterResponse(assistantMessage);
|
|
567
|
-
if (result)
|
|
568
|
-
assistantMessage = result;
|
|
569
|
-
}
|
|
605
|
+
assistantMessage = await runChainHandlers(afterResponseHandlers, assistantMessage);
|
|
570
606
|
this.messages.push({
|
|
571
607
|
role: "assistant",
|
|
572
608
|
content: assistantMessage?.toString() || null,
|
|
573
609
|
tool_calls: response.tool_calls,
|
|
574
610
|
usage: response.usage
|
|
575
611
|
});
|
|
576
|
-
if (
|
|
577
|
-
(
|
|
578
|
-
this.options.onEndMessage(assistantMessage);
|
|
612
|
+
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
613
|
+
await runAllHandlers(endMessageHandlers, assistantMessage);
|
|
579
614
|
}
|
|
580
615
|
}
|
|
581
|
-
finalResponse = new ChatResponseString(assistantMessage.toString() || "", totalUsage, this.model, this.provider.id, assistantMessage.thinking, assistantMessage.reasoning, response.tool_calls, assistantMessage.finish_reason, this.options.schema);
|
|
616
|
+
finalResponse = new ChatResponseString(assistantMessage.toString() || "", totalUsage, this.model, this.provider.id, assistantMessage.thinking, assistantMessage.reasoning, response.tool_calls, assistantMessage.finish_reason, this.options.schema, assistantMessage.metadata, assistantMessage.attachments);
|
|
582
617
|
// 5. onResponse Hook
|
|
583
618
|
const requestDirective = await runMiddleware(this.middlewares, "onResponse", context, finalResponse);
|
|
584
619
|
if (requestDirective && typeof requestDirective === "object") {
|
|
@@ -18,6 +18,17 @@ export interface ChatOptions {
|
|
|
18
18
|
onToolCallStart?: (toolCall: unknown) => void;
|
|
19
19
|
onToolCallEnd?: (toolCall: unknown, result: unknown) => void;
|
|
20
20
|
onToolCallError?: (toolCall: unknown, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>;
|
|
21
|
+
/**
|
|
22
|
+
* Additional handlers registered via the fluent on*() methods. Each on*()
|
|
23
|
+
* call appends here instead of overwriting the single onX field above, so
|
|
24
|
+
* e.g. calling chat.onToolCallStart() twice runs both handlers instead of
|
|
25
|
+
* silently dropping the first.
|
|
26
|
+
*/
|
|
27
|
+
onNewMessageHandlers?: Array<() => void>;
|
|
28
|
+
onEndMessageHandlers?: Array<(message: ChatResponseString) => void>;
|
|
29
|
+
onToolCallStartHandlers?: Array<(toolCall: unknown) => void>;
|
|
30
|
+
onToolCallEndHandlers?: Array<(toolCall: unknown, result: unknown) => void>;
|
|
31
|
+
onToolCallErrorHandlers?: Array<(toolCall: unknown, error: Error) => "STOP" | "CONTINUE" | "RETRY" | void | Promise<"STOP" | "CONTINUE" | "RETRY" | void>>;
|
|
21
32
|
headers?: Record<string, string>;
|
|
22
33
|
responseFormat?: ResponseFormat;
|
|
23
34
|
thinking?: ThinkingConfig;
|
|
@@ -29,10 +40,18 @@ export interface ChatOptions {
|
|
|
29
40
|
maxToolCalls?: number;
|
|
30
41
|
requestTimeout?: number;
|
|
31
42
|
toolExecution?: ToolExecutionMode;
|
|
43
|
+
/**
|
|
44
|
+
* When true, independent tool calls returned in the same turn are executed
|
|
45
|
+
* concurrently instead of one at a time. Defaults to `config.toolConcurrency`.
|
|
46
|
+
*/
|
|
47
|
+
toolConcurrency?: boolean;
|
|
32
48
|
toolChoice?: ToolChoice;
|
|
33
49
|
toolCalls?: "one" | "many" | number;
|
|
34
50
|
onConfirmToolCall?: (toolCall: unknown) => Promise<boolean> | boolean;
|
|
35
51
|
onBeforeRequest?: (messages: Message[]) => Promise<Message[] | void>;
|
|
36
52
|
onAfterResponse?: (response: ChatResponseString) => Promise<ChatResponseString | void>;
|
|
53
|
+
onConfirmToolCallHandlers?: Array<(toolCall: unknown) => Promise<boolean> | boolean>;
|
|
54
|
+
onBeforeRequestHandlers?: Array<(messages: Message[]) => Promise<Message[] | void>>;
|
|
55
|
+
onAfterResponseHandlers?: Array<(response: ChatResponseString) => Promise<ChatResponseString | void>>;
|
|
37
56
|
}
|
|
38
57
|
//# sourceMappingURL=ChatOptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,eAAe,CAAC,EAAE,CAChB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,KAAK,KACT,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IAC1F,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACtE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatOptions.d.ts","sourceRoot":"","sources":["../../src/chat/ChatOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,eAAe,CAAC,EAAE,CAChB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,KAAK,KACT,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IAC1F;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC,CAAC;IACpE,uBAAuB,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IAC7D,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC;IAC5E,uBAAuB,CAAC,EAAE,KAAK,CAC7B,CACE,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,KAAK,KACT,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC,CAC1F,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACtE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACrE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IACvF,yBAAyB,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;IACrF,uBAAuB,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACpF,uBAAuB,CAAC,EAAE,KAAK,CAC7B,CAAC,QAAQ,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CACrE,CAAC;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatStream.d.ts","sourceRoot":"","sources":["../../src/chat/ChatStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,WAAW,EAIZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAyB,MAAM,0BAA0B,CAAC;AAEtF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatStream.d.ts","sourceRoot":"","sources":["../../src/chat/ChatStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,WAAW,EAIZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAyB,MAAM,0BAA0B,CAAC;AAEtF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAqBvC;;;GAGG;AACH,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,cAAc,CAAY;gBAGf,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,WAAgB,EAC1C,QAAQ,CAAC,EAAE,OAAO,EAAE,EACpB,cAAc,CAAC,EAAE,OAAO,EAAE;IAiC5B,IAAI,OAAO,IAAI,SAAS,OAAO,EAAE,CAEhC;IAED,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAAC,SAAS,CAAC;CAuZrF"}
|
package/dist/chat/ChatStream.js
CHANGED
|
@@ -11,6 +11,8 @@ import { logger } from "../utils/logger.js";
|
|
|
11
11
|
import { ModelRegistry } from "../models/ModelRegistry.js";
|
|
12
12
|
import { runMiddleware } from "../utils/middleware-runner.js";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { shouldRunToolCallsConcurrently, executeToolCallOutcomes } from "./ToolCallOutcome.js";
|
|
15
|
+
import { collectHandlers, runAllHandlers, runDirectiveHandlers, runConfirmHandlers, runChainHandlers } from "../utils/handler-stacking.js";
|
|
14
16
|
/**
|
|
15
17
|
* Internal handler for chat streaming logic.
|
|
16
18
|
* Wraps the provider's stream with side effects like history updates and events.
|
|
@@ -48,6 +50,9 @@ export class ChatStream {
|
|
|
48
50
|
if (!this.options.toolExecution) {
|
|
49
51
|
this.options.toolExecution = config.toolExecution || ToolExecutionMode.AUTO;
|
|
50
52
|
}
|
|
53
|
+
if (this.options.toolConcurrency === undefined) {
|
|
54
|
+
this.options.toolConcurrency = config.toolConcurrency;
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
get history() {
|
|
53
58
|
return [...this.systemMessages, ...this.messages];
|
|
@@ -63,6 +68,23 @@ export class ChatStream {
|
|
|
63
68
|
const requestId = randomUUID();
|
|
64
69
|
const state = {};
|
|
65
70
|
const middlewares = options.middlewares || [];
|
|
71
|
+
const newMessageHandlers = collectHandlers(options.onNewMessage, options.onNewMessageHandlers);
|
|
72
|
+
const endMessageHandlers = collectHandlers(options.onEndMessage, options.onEndMessageHandlers);
|
|
73
|
+
const beforeRequestHandlers = collectHandlers(options.onBeforeRequest, options.onBeforeRequestHandlers);
|
|
74
|
+
const afterResponseHandlers = collectHandlers(options.onAfterResponse, options.onAfterResponseHandlers);
|
|
75
|
+
const toolCallStartHandlers = collectHandlers(options.onToolCallStart, options.onToolCallStartHandlers);
|
|
76
|
+
const toolCallEndHandlers = collectHandlers(options.onToolCallEnd, options.onToolCallEndHandlers);
|
|
77
|
+
const toolCallErrorHandlers = collectHandlers(options.onToolCallError, options.onToolCallErrorHandlers);
|
|
78
|
+
const confirmToolCallHandlers = collectHandlers(options.onConfirmToolCall, options.onConfirmToolCallHandlers);
|
|
79
|
+
const combinedToolCallStart = toolCallStartHandlers.length
|
|
80
|
+
? (call) => toolCallStartHandlers.forEach((handler) => handler(call))
|
|
81
|
+
: undefined;
|
|
82
|
+
const combinedToolCallEnd = toolCallEndHandlers.length
|
|
83
|
+
? (call, result) => toolCallEndHandlers.forEach((handler) => handler(call, result))
|
|
84
|
+
: undefined;
|
|
85
|
+
const combinedConfirmToolCall = confirmToolCallHandlers.length
|
|
86
|
+
? (call) => runConfirmHandlers(confirmToolCallHandlers, call)
|
|
87
|
+
: undefined;
|
|
66
88
|
// Process Multimodal Content
|
|
67
89
|
let messageContent = content;
|
|
68
90
|
const files = [...(requestOptions.images ?? []), ...(requestOptions.files ?? [])];
|
|
@@ -143,12 +165,7 @@ export class ChatStream {
|
|
|
143
165
|
let currentTurnUsage;
|
|
144
166
|
context.messages = [...systemMessages, ...messages];
|
|
145
167
|
let requestMessages = context.messages; // Use up-to-date messages from context
|
|
146
|
-
|
|
147
|
-
const result = await options.onBeforeRequest(requestMessages);
|
|
148
|
-
if (result) {
|
|
149
|
-
requestMessages = result;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
168
|
+
requestMessages = await runChainHandlers(beforeRequestHandlers, requestMessages);
|
|
152
169
|
const streamRequest = {
|
|
153
170
|
model,
|
|
154
171
|
messages: requestMessages,
|
|
@@ -170,8 +187,7 @@ export class ChatStream {
|
|
|
170
187
|
}
|
|
171
188
|
for await (const chunk of provider.stream(streamRequest)) {
|
|
172
189
|
if (isFirst) {
|
|
173
|
-
|
|
174
|
-
options.onNewMessage();
|
|
190
|
+
await runAllHandlers(newMessageHandlers);
|
|
175
191
|
isFirst = false;
|
|
176
192
|
}
|
|
177
193
|
if (chunk.content) {
|
|
@@ -204,12 +220,7 @@ export class ChatStream {
|
|
|
204
220
|
}
|
|
205
221
|
assistantResponse = new ChatResponseString(fullContent || "", currentTurnUsage || { input_tokens: 0, output_tokens: 0, total_tokens: 0 }, model, provider.id, thinking.text || thinking.signature ? thinking : undefined, fullReasoning || undefined, toolCalls, undefined, // finish_reason
|
|
206
222
|
options.schema);
|
|
207
|
-
|
|
208
|
-
const result = await options.onAfterResponse(assistantResponse);
|
|
209
|
-
if (result) {
|
|
210
|
-
assistantResponse = result;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
223
|
+
assistantResponse = await runChainHandlers(afterResponseHandlers, assistantResponse);
|
|
213
224
|
messages.push({
|
|
214
225
|
role: "assistant",
|
|
215
226
|
content: assistantResponse || null,
|
|
@@ -218,62 +229,62 @@ export class ChatStream {
|
|
|
218
229
|
usage: currentTurnUsage
|
|
219
230
|
});
|
|
220
231
|
if (!toolCalls || toolCalls.length === 0) {
|
|
221
|
-
|
|
222
|
-
options.onEndMessage(assistantResponse);
|
|
223
|
-
}
|
|
232
|
+
await runAllHandlers(endMessageHandlers, assistantResponse);
|
|
224
233
|
break;
|
|
225
234
|
}
|
|
226
235
|
if (!ToolHandler.shouldExecuteTools(toolCalls, options.toolExecution)) {
|
|
227
236
|
break;
|
|
228
237
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
238
|
+
const runConcurrently = shouldRunToolCallsConcurrently(options.toolConcurrency, options.toolExecution, toolCalls.length);
|
|
239
|
+
const outcomes = await executeToolCallOutcomes(toolCalls, {
|
|
240
|
+
...options,
|
|
241
|
+
tools: options.tools,
|
|
242
|
+
onToolCallStart: combinedToolCallStart,
|
|
243
|
+
onToolCallEnd: combinedToolCallEnd,
|
|
244
|
+
onConfirmToolCall: combinedConfirmToolCall
|
|
245
|
+
}, middlewares, context, runConcurrently);
|
|
246
|
+
for (const outcome of outcomes) {
|
|
247
|
+
const toolCall = outcome.toolCall;
|
|
248
|
+
if (outcome.kind === "cancelled") {
|
|
249
|
+
messages.push(provider.formatToolResultMessage(toolCall.id, "Action cancelled by user."));
|
|
250
|
+
continue;
|
|
236
251
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
const toolResult = await ToolHandler.execute(toolCall, options.tools, options.onToolCallStart, options.onToolCallEnd);
|
|
241
|
-
// 3. onToolCallEnd Hook
|
|
242
|
-
await runMiddleware(middlewares, "onToolCallEnd", context, toolCall, toolResult.content);
|
|
252
|
+
if (outcome.kind === "success") {
|
|
253
|
+
const { toolResult } = outcome;
|
|
243
254
|
messages.push(provider.formatToolResultMessage(toolResult.tool_call_id, toolResult.content));
|
|
255
|
+
continue;
|
|
244
256
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
catch (retryError) {
|
|
261
|
-
currentError = retryError;
|
|
262
|
-
await runMiddleware(middlewares, "onToolCallError", context, toolCall, currentError);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
messages.push(provider.formatToolResultMessage(toolCall.id, `Fatal error executing tool '${toolCall.function.name}': ${currentError.message}`, { isError: true }));
|
|
266
|
-
if (directive === "CONTINUE") {
|
|
257
|
+
let currentError = outcome.error;
|
|
258
|
+
// 4. onToolCallError Hook
|
|
259
|
+
const middlewareDirective = await runMiddleware(middlewares, "onToolCallError", context, toolCall, currentError);
|
|
260
|
+
const directive = middlewareDirective ||
|
|
261
|
+
(await runDirectiveHandlers(toolCallErrorHandlers, toolCall, currentError));
|
|
262
|
+
if (directive === "STOP") {
|
|
263
|
+
throw currentError;
|
|
264
|
+
}
|
|
265
|
+
if (directive === "RETRY") {
|
|
266
|
+
try {
|
|
267
|
+
const toolResult = await ToolHandler.execute(toolCall, options.tools, combinedToolCallStart, combinedToolCallEnd);
|
|
268
|
+
await runMiddleware(middlewares, "onToolCallEnd", context, toolCall, toolResult.content);
|
|
269
|
+
messages.push(provider.formatToolResultMessage(toolResult.tool_call_id, toolResult.content));
|
|
267
270
|
continue;
|
|
268
271
|
}
|
|
269
|
-
|
|
270
|
-
currentError
|
|
271
|
-
|
|
272
|
-
if (isFatal) {
|
|
273
|
-
throw currentError;
|
|
272
|
+
catch (retryError) {
|
|
273
|
+
currentError = retryError;
|
|
274
|
+
await runMiddleware(middlewares, "onToolCallError", context, toolCall, currentError);
|
|
274
275
|
}
|
|
275
|
-
logger.error(`Tool execution failed for '${toolCall.function.name}':`, currentError);
|
|
276
276
|
}
|
|
277
|
+
messages.push(provider.formatToolResultMessage(toolCall.id, `Fatal error executing tool '${toolCall.function.name}': ${currentError.message}`, { isError: true }));
|
|
278
|
+
if (directive === "CONTINUE") {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const isFatal = currentError.fatal === true ||
|
|
282
|
+
currentError.status === 401 ||
|
|
283
|
+
currentError.status === 403;
|
|
284
|
+
if (isFatal) {
|
|
285
|
+
throw currentError;
|
|
286
|
+
}
|
|
287
|
+
logger.error(`Tool execution failed for '${toolCall.function.name}':`, currentError);
|
|
277
288
|
}
|
|
278
289
|
// Loop continues -> streaming next chunk
|
|
279
290
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ToolCall, ToolDefinition } from "./Tool.js";
|
|
2
|
+
import { ToolExecutionMode } from "../constants.js";
|
|
3
|
+
import { ToolExecutionResult } from "./ToolHandler.js";
|
|
4
|
+
import { Middleware, MiddlewareContext } from "../types/Middleware.js";
|
|
5
|
+
export type ToolCallOutcome = {
|
|
6
|
+
kind: "cancelled";
|
|
7
|
+
toolCall: ToolCall;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "success";
|
|
10
|
+
toolCall: ToolCall;
|
|
11
|
+
toolResult: ToolExecutionResult;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "error";
|
|
14
|
+
toolCall: ToolCall;
|
|
15
|
+
error: unknown;
|
|
16
|
+
};
|
|
17
|
+
export interface ToolCallExecutionOptions {
|
|
18
|
+
tools?: ToolDefinition[];
|
|
19
|
+
toolExecution?: ToolExecutionMode;
|
|
20
|
+
onConfirmToolCall?: (toolCall: unknown) => Promise<boolean> | boolean;
|
|
21
|
+
onToolCallStart?: (toolCall: unknown) => void;
|
|
22
|
+
onToolCallEnd?: (toolCall: unknown, result: unknown) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Confirm mode stays sequential since approval is interactive; concurrency
|
|
26
|
+
* only kicks in for AUTO/DRY_RUN turns with more than one independent call.
|
|
27
|
+
*/
|
|
28
|
+
export declare function shouldRunToolCallsConcurrently(toolConcurrency: boolean | undefined, toolExecution: ToolExecutionMode | undefined, callCount: number): boolean;
|
|
29
|
+
export declare function executeToolCallOutcomes(toolCalls: ToolCall[], options: ToolCallExecutionOptions, middlewares: Middleware[], context: MiddlewareContext, concurrent: boolean): Promise<ToolCallOutcome[]>;
|
|
30
|
+
//# sourceMappingURL=ToolCallOutcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolCallOutcome.d.ts","sourceRoot":"","sources":["../../src/chat/ToolCallOutcome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAe,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGvE,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,mBAAmB,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACtE,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9D;AAuCD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,eAAe,EAAE,OAAO,GAAG,SAAS,EACpC,aAAa,EAAE,iBAAiB,GAAG,SAAS,EAC5C,SAAS,EAAE,MAAM,GAChB,OAAO,CAET;AAED,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,QAAQ,EAAE,EACrB,OAAO,EAAE,wBAAwB,EACjC,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5B"}
|