All files / src/chat ToolHandler.ts

85.71% Statements 18/21
66.66% Branches 12/18
100% Functions 4/4
93.33% Lines 14/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51            32x 32x 30x             3x 3x 3x                 29x   30x   29x 29x 29x 21x   29x   21x                          
import { ToolExecutionMode } from "../constants.js";
import { ToolError } from "../errors/index.js";
import { ToolCall, ToolDefinition } from "./Tool.js";
 
export class ToolHandler {
  static shouldExecuteTools(toolCalls: ToolCall[] | undefined, mode?: ToolExecutionMode): boolean {
    Iif (!toolCalls || toolCalls.length === 0) return false;
    if (mode === ToolExecutionMode.DRY_RUN) return false;
    return true;
  }
 
  static async requestToolConfirmation(
    toolCall: ToolCall,
    onConfirm?: (call: ToolCall) => Promise<boolean> | boolean
  ): Promise<boolean> {
    Iif (!onConfirm) return true;
    const confirmed = await onConfirm(toolCall);
    return confirmed !== false;
  }
 
  static async execute(
    toolCall: ToolCall,
    tools: ToolDefinition[] | undefined,
    onStart?: (call: ToolCall) => void,
    onEnd?: (call: ToolCall, result: unknown) => void
  ): Promise<{ role: "tool"; tool_call_id: string; content: string }> {
    if (onStart) onStart(toolCall);
 
    const tool = tools?.find((t) => t.function.name === toolCall.function.name);
 
    if (tool?.handler) {
      const args = JSON.parse(toolCall.function.arguments);
      const result = await tool.handler(args);
      const safeResult = typeof result === "string" ? result : JSON.stringify(result);
 
      if (onEnd) onEnd(toolCall, result);
 
      return {
        role: "tool",
        tool_call_id: toolCall.id,
        content: safeResult
      };
    } else E{
      throw new ToolError(
        "Tool not found or no handler provided",
        toolCall.function?.name ?? "unknown"
      );
    }
  }
}