/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { type FunctionDeclaration, type PartListUnion } from '@google/genai'; import { type ToolContext, type ContextAwareTool } from './tool-context.js'; import { ToolErrorType } from './tool-error.js'; import { type DiffUpdateResult } from '../ide/ideContext.js'; import type { MessageBus } from '../confirmation-bus/message-bus.js'; import { ToolConfirmationOutcome, type ToolConfirmationPayload } from './tool-confirmation-types.js'; import type { AnsiOutput } from '../utils/terminalSerializer.js'; export { ToolConfirmationOutcome } from './tool-confirmation-types.js'; export type { ToolConfirmationPayload } from './tool-confirmation-types.js'; /** * Represents a validated and ready-to-execute tool call. * An instance of this is created by a `ToolBuilder`. */ export interface ToolInvocation { /** * The validated parameters for this specific invocation. */ params: TParams; /** * Gets a pre-execution description of the tool operation. * * @returns A markdown string describing what the tool will do. */ getDescription(): string; /** * Determines what file system paths the tool will affect. * @returns A list of such paths. */ toolLocations(): ToolLocation[]; /** * Determines if the tool should prompt for confirmation before execution. * @returns Confirmation details or false if no confirmation is needed. */ shouldConfirmExecute(abortSignal: AbortSignal): Promise; /** * Executes the tool with the validated parameters. * @param signal AbortSignal for tool cancellation. * @param updateOutput Optional callback to stream output. * @param terminalColumns Optional terminal width for PTY mode. * @param terminalRows Optional terminal height for PTY mode. * @param setPidCallback Optional callback to propagate PTY PID. * @returns Result of the tool execution. */ execute(signal: AbortSignal, updateOutput?: (output: string | AnsiOutput) => void, terminalColumns?: number, terminalRows?: number, setPidCallback?: (pid: number) => void): Promise; } /** * Options for policy updates that can be customized by tool invocations. */ export interface PolicyUpdateOptions { commandPrefix?: string | string[]; mcpName?: string; } /** * A convenience base class for ToolInvocation. */ export declare abstract class BaseToolInvocation implements ToolInvocation { readonly params: TParams; protected readonly messageBus?: MessageBus | undefined; readonly _toolName?: string | undefined; readonly _toolDisplayName?: string | undefined; readonly _serverName?: string | undefined; constructor(params: TParams, messageBus?: MessageBus | undefined, _toolName?: string | undefined, _toolDisplayName?: string | undefined, _serverName?: string | undefined); abstract getDescription(): string; toolLocations(): ToolLocation[]; /** * Returns confirmation details for this tool invocation. * Tools that require confirmation should override this method. * @returns Confirmation details or null if no confirmation needed. */ /** * Returns tool-specific options for policy updates. * Subclasses can override this to provide additional options like * commandPrefix (for shell) or mcpName (for MCP tools). */ protected getPolicyUpdateOptions(_outcome: ToolConfirmationOutcome): PolicyUpdateOptions | undefined; /** * Helper method to publish a policy update when user selects * ProceedAlways or ProceedAlwaysAndSave. */ protected publishPolicyUpdate(outcome: ToolConfirmationOutcome): Promise; protected getConfirmationDetails(): ToolCallConfirmationDetails | null; /** * Attempts to obtain a policy decision via message bus. * * Semantics: * - `'ALLOW'`: auto-proceed * - `'DENY'`: tool must not execute * - `'ASK_USER'`: fall back to legacy tool confirmation UI */ protected getMessageBusDecision(abortSignal: AbortSignal): Promise<'ALLOW' | 'DENY' | 'ASK_USER'>; /** * Returns the tool name for this invocation. * Subclasses can override to provide a specific tool name. */ protected getToolName(): string; /** * Returns the server name for MCP tools. * Regular tools should return undefined. */ protected getServerName(): string | undefined; /** * Returns metadata used by the policy engine/message bus. */ getPolicyContext(): { toolName: string; args: Record; serverName?: string; }; shouldConfirmExecute(_abortSignal: AbortSignal): Promise; abstract execute(signal: AbortSignal, updateOutput?: (output: string | AnsiOutput) => void, terminalColumns?: number, terminalRows?: number, setPidCallback?: (pid: number) => void): Promise; } /** * A type alias for a tool invocation where the specific parameter and result types are not known. */ export type AnyToolInvocation = ToolInvocation; /** * Interface for a tool builder that validates parameters and creates invocations. */ export interface ToolBuilder { /** * The internal name of the tool (used for API calls). */ name: string; /** * The user-friendly display name of the tool. */ displayName: string; /** * Description of what the tool does. */ description: string; /** * The kind of tool for categorization and permissions */ kind: Kind; /** * Function declaration schema from @google/genai. */ schema: FunctionDeclaration; /** * Whether the tool's output should be rendered as markdown. */ isOutputMarkdown: boolean; /** * Whether the tool supports live (streaming) output. */ canUpdateOutput: boolean; /** * Validates raw parameters and builds a ready-to-execute invocation. * @param params The raw, untrusted parameters from the model. * @returns A valid `ToolInvocation` if successful. Throws an error if validation fails. */ build(params: TParams): ToolInvocation; } /** * New base class for tools that separates validation from execution. * New tools should extend this class. */ export declare abstract class DeclarativeTool implements ToolBuilder { readonly name: string; readonly displayName: string; readonly description: string; readonly kind: Kind; readonly parameterSchema: unknown; readonly isOutputMarkdown: boolean; readonly canUpdateOutput: boolean; protected messageBus?: MessageBus; constructor(name: string, displayName: string, description: string, kind: Kind, parameterSchema: unknown, isOutputMarkdown?: boolean, canUpdateOutput?: boolean, messageBus?: MessageBus); /** * Sets the message bus for this tool. * Called by ToolRegistry after tool construction. */ setMessageBus(messageBus: MessageBus): void; get schema(): FunctionDeclaration; /** * Validates the raw tool parameters. * Subclasses should override this to add custom validation logic * beyond the JSON schema check. * @param params The raw parameters from the model. * @returns An error message string if invalid, null otherwise. */ validateToolParams(_params: TParams): string | null; /** * The core of the new pattern. It validates parameters and, if successful, * returns a `ToolInvocation` object that encapsulates the logic for the * specific, validated call. * @param params The raw, untrusted parameters from the model. * @returns A `ToolInvocation` instance. */ abstract build(params: TParams): ToolInvocation; /** * A convenience method that builds and executes the tool in one step. * Throws an error if validation fails. * @param params The raw, untrusted parameters from the model. * @param signal AbortSignal for tool cancellation. * @param updateOutput Optional callback to stream output. * @returns The result of the tool execution. */ buildAndExecute(params: TParams, signal: AbortSignal, updateOutput?: (output: string | AnsiOutput) => void): Promise; /** * Similar to `build` but never throws. * @param params The raw, untrusted parameters from the model. * @returns A `ToolInvocation` instance. */ private silentBuild; /** * A convenience method that builds and executes the tool in one step. * Never throws. * @param params The raw, untrusted parameters from the model. * @params abortSignal a signal to abort. * @returns The result of the tool execution. */ validateBuildAndExecute(params: TParams, abortSignal: AbortSignal): Promise; } /** * New base class for declarative tools that separates validation from execution. * New tools should extend this class, which provides a `build` method that * validates parameters before deferring to a `createInvocation` method for * the final `ToolInvocation` object instantiation. */ export declare abstract class BaseDeclarativeTool extends DeclarativeTool { build(params: TParams): ToolInvocation; validateToolParams(params: TParams): string | null; protected validateToolParamValues(_params: TParams): string | null; protected abstract createInvocation(params: TParams, messageBus?: MessageBus): ToolInvocation; } /** * A type alias for a declarative tool where the specific parameter and result types are not known. */ export type AnyDeclarativeTool = DeclarativeTool; /** * Type guard to check if an object is a Tool. * @param obj The object to check. * @returns True if the object is a Tool, false otherwise. */ export declare function isTool(obj: unknown): obj is AnyDeclarativeTool; export interface ToolResult { /** * Content meant to be included in LLM history. * This should represent the factual outcome of the tool execution. */ llmContent: PartListUnion; /** * Markdown string for user display. * This provides a user-friendly summary or visualization of the result. * NOTE: This might also be considered UI-specific and could potentially be * removed or modified in a further refactor if the server becomes purely API-driven. * For now, we keep it as the core logic in ReadFileTool currently produces it. */ returnDisplay: ToolResultDisplay; /** * Optional metadata about the tool execution */ metadata?: Record; /** * If this property is present, the tool call is considered a failure. */ error?: { message: string; type?: ToolErrorType; }; /** * Optional flag to suppress display of this tool result * @requirement:HOOK-132 - AfterTool suppressOutput support */ suppressDisplay?: boolean; } /** * Detects cycles in a JSON schemas due to `$ref`s. * @param schema The root of the JSON schema. * @returns `true` if a cycle is detected, `false` otherwise. */ export declare function hasCycleInSchema(schema: object): boolean; export interface FileRead { content: string; fileName: string; filePath: string; metadata?: Record; } export type ToolResultDisplay = string | FileDiff | FileRead | AnsiOutput; export interface FileDiff { fileDiff: string; fileName: string; originalContent: string | null; newContent: string; diffStat?: DiffStat; metadata?: Record; applied?: boolean; } export interface DiffStat { ai_removed_lines: number; ai_added_lines: number; user_added_lines: number; user_removed_lines: number; } export interface ToolEditConfirmationDetails { type: 'edit'; title: string; onConfirm: (outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => Promise; fileName: string; filePath: string; fileDiff: string; originalContent: string | null; newContent: string; isModifying?: boolean; ideConfirmation?: Promise; correlationId?: string; metadata?: Record; } export interface ToolExecuteConfirmationDetails { type: 'exec'; title: string; onConfirm: (outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => Promise; command: string; rootCommand: string; correlationId?: string; } export interface ToolMcpConfirmationDetails { type: 'mcp'; title: string; serverName: string; toolName: string; toolDisplayName: string; onConfirm: (outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => Promise; correlationId?: string; } export interface ToolInfoConfirmationDetails { type: 'info'; title: string; onConfirm: (outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => Promise; prompt: string; urls?: string[]; correlationId?: string; } export type ToolCallConfirmationDetails = ToolEditConfirmationDetails | ToolExecuteConfirmationDetails | ToolMcpConfirmationDetails | ToolInfoConfirmationDetails; export declare enum Kind { Read = "read", Edit = "edit", Delete = "delete", Move = "move", Search = "search", Execute = "execute", Think = "think", Fetch = "fetch", Other = "other" } export interface ToolLocation { path: string; line?: number; } /** * Legacy BaseTool class for backward compatibility with existing LLxprt tools. * New tools should use BaseDeclarativeTool instead. * @deprecated Use BaseDeclarativeTool for new tools */ export declare abstract class BaseTool extends DeclarativeTool implements ContextAwareTool { context?: ToolContext; constructor(name: string, displayName: string, description: string, kind: Kind, parameterSchema: unknown, isOutputMarkdown?: boolean, canUpdateOutput?: boolean); /** * Get the schema for this tool. Maintains backward compatibility. */ get schema(): FunctionDeclaration; /** * Legacy method signature for getDescription. * Subclasses can override this method. */ getDescription(_params: TParams): string; /** * Legacy method signature for validateToolParams. * Subclasses can override this method. * Note: The base class expects TParams, but legacy tools pass unknown. */ validateToolParams(params: TParams): string | null; /** * Legacy validateToolParams method that accepts unknown params. * This maintains compatibility with existing tool implementations. */ validateToolParamsLegacy?(params: unknown): string | null; /** * Legacy execute method signature. * Subclasses should implement this method. */ abstract execute(params: TParams, signal: AbortSignal, updateOutput?: (output: string) => void): Promise; /** * Implementation of the new declarative pattern. * Creates a tool invocation that bridges to the legacy execute method. */ build(params: TParams): ToolInvocation; }