Finish manually fixing linter errors for tools dir (partial).

- More changes are to come, this is truly a partial change in order to not disrupt as many people as possible.

Part of https://b.corp.google.com/issues/411384603
This commit is contained in:
Taylor Mullen 2025-04-18 14:34:34 -04:00 committed by N. Taylor Mullen
parent 328846c6e3
commit abb60a4d10
4 changed files with 52 additions and 99 deletions

View File

@ -49,30 +49,10 @@ export interface FileEntry {
modifiedTime: Date; modifiedTime: Date;
} }
/**
* Result from the LS tool
*/
export interface LSToolResult extends ToolResult {
/**
* List of file entries
*/
entries: FileEntry[];
/**
* The directory that was listed
*/
listedPath: string;
/**
* Total number of entries found
*/
totalEntries: number;
}
/** /**
* Implementation of the LS tool that lists directory contents * Implementation of the LS tool that lists directory contents
*/ */
export class LSTool extends BaseTool<LSToolParams, LSToolResult> { export class LSTool extends BaseTool<LSToolParams, ToolResult> {
/** /**
* The root directory that this tool is grounded in. * The root directory that this tool is grounded in.
* All path operations will be restricted to this directory. * All path operations will be restricted to this directory.
@ -184,12 +164,9 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
return shortenPath(relativePath); return shortenPath(relativePath);
} }
private errorResult(params: LSToolParams, llmContent: string, returnDisplay: string): LSToolResult { private errorResult(llmContent: string, returnDisplay: string): ToolResult {
return { return {
entries: [], llmContent,
listedPath: params.path,
totalEntries: 0,
llmContent: llmContent,
returnDisplay: `**Error:** ${returnDisplay}`, returnDisplay: `**Error:** ${returnDisplay}`,
}; };
} }
@ -199,11 +176,10 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
* @param params Parameters for the LS operation * @param params Parameters for the LS operation
* @returns Result of the LS operation * @returns Result of the LS operation
*/ */
async execute(params: LSToolParams): Promise<LSToolResult> { async execute(params: LSToolParams): Promise<ToolResult> {
const validationError = this.validateToolParams(params); const validationError = this.validateToolParams(params);
if (validationError) { if (validationError) {
return this.errorResult( return this.errorResult(
params,
`Error: Invalid parameters provided. Reason: ${validationError}`, `Error: Invalid parameters provided. Reason: ${validationError}`,
`Failed to execute tool.`); `Failed to execute tool.`);
} }
@ -212,13 +188,11 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
const stats = fs.statSync(params.path); const stats = fs.statSync(params.path);
if (!stats) { if (!stats) {
return this.errorResult( return this.errorResult(
params,
`Directory does not exist: ${params.path}`, `Directory does not exist: ${params.path}`,
`Directory does not exist.`); `Directory does not exist.`);
} }
if (!stats.isDirectory()) { if (!stats.isDirectory()) {
return this.errorResult( return this.errorResult(
params,
`Path is not a directory: ${params.path}`, `Path is not a directory: ${params.path}`,
`Path is not a directory.`); `Path is not a directory.`);
} }
@ -227,7 +201,6 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
const entries: FileEntry[] = []; const entries: FileEntry[] = [];
if (files.length === 0) { if (files.length === 0) {
return this.errorResult( return this.errorResult(
params,
`Directory is empty: ${params.path}`, `Directory is empty: ${params.path}`,
`Directory is empty.`); `Directory is empty.`);
} }
@ -270,15 +243,11 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
.join('\n'); .join('\n');
return { return {
entries,
listedPath: params.path,
totalEntries: entries.length,
llmContent: `Directory listing for ${params.path}:\n${directoryContent}`, llmContent: `Directory listing for ${params.path}:\n${directoryContent}`,
returnDisplay: `Found ${entries.length} item(s).`, returnDisplay: `Found ${entries.length} item(s).`,
}; };
} catch (error) { } catch (error) {
return this.errorResult( return this.errorResult(
params,
`Error listing directory: ${error instanceof Error ? error.message : String(error)}`, `Error listing directory: ${error instanceof Error ? error.message : String(error)}`,
'Failed to list directory.'); 'Failed to list directory.');
} }

View File

@ -2,7 +2,6 @@ import {
spawn, spawn,
SpawnOptions, SpawnOptions,
ChildProcessWithoutNullStreams, ChildProcessWithoutNullStreams,
exec,
} from 'child_process'; // Added 'exec' } from 'child_process'; // Added 'exec'
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';
@ -16,6 +15,7 @@ import {
ToolExecuteConfirmationDetails, ToolExecuteConfirmationDetails,
} from '../ui/types.js'; // Adjust path as needed } from '../ui/types.js'; // Adjust path as needed
import { BackgroundTerminalAnalyzer } from '../utils/BackgroundTerminalAnalyzer.js'; import { BackgroundTerminalAnalyzer } from '../utils/BackgroundTerminalAnalyzer.js';
import { getErrorMessage, isNodeError } from '../utils/errors.js';
// --- Interfaces --- // --- Interfaces ---
export interface TerminalToolParams { export interface TerminalToolParams {
@ -25,19 +25,11 @@ export interface TerminalToolParams {
runInBackground?: boolean; runInBackground?: boolean;
} }
export interface TerminalToolResult extends ToolResult {
// Add specific fields if needed for structured output from polling/LLM
// finalStdout?: string;
// finalStderr?: string;
// llmAnalysis?: string;
}
// --- Constants --- // --- Constants ---
const MAX_OUTPUT_LENGTH = 10000; // Default max output length const MAX_OUTPUT_LENGTH = 10000; // Default max output length
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes (for foreground commands) const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes (for foreground commands)
const MAX_TIMEOUT_OVERRIDE_MS = 10 * 60 * 1000; // 10 minutes (max override for foreground) const MAX_TIMEOUT_OVERRIDE_MS = 10 * 60 * 1000; // 10 minutes (max override for foreground)
const BACKGROUND_LAUNCH_TIMEOUT_MS = 15 * 1000; // 15 seconds timeout for *launching* background tasks const BACKGROUND_LAUNCH_TIMEOUT_MS = 15 * 1000; // 15 seconds timeout for *launching* background tasks
const BACKGROUND_POLL_INTERVAL_MS = 5000; // 5 seconds interval for checking background process status
const BACKGROUND_POLL_TIMEOUT_MS = 30000; // 30 seconds total polling time for background process status const BACKGROUND_POLL_TIMEOUT_MS = 30000; // 30 seconds total polling time for background process status
const BANNED_COMMAND_ROOTS = [ const BANNED_COMMAND_ROOTS = [
@ -115,7 +107,7 @@ const BANNED_COMMAND_ROOTS = [
// --- Helper Type for Command Queue --- // --- Helper Type for Command Queue ---
interface QueuedCommand { interface QueuedCommand {
params: TerminalToolParams; params: TerminalToolParams;
resolve: (result: TerminalToolResult) => void; resolve: (result: ToolResult) => void;
reject: (error: Error) => void; reject: (error: Error) => void;
confirmationDetails: ToolExecuteConfirmationDetails | false; // Kept for potential future use confirmationDetails: ToolExecuteConfirmationDetails | false; // Kept for potential future use
} }
@ -125,7 +117,7 @@ interface QueuedCommand {
*/ */
export class TerminalTool extends BaseTool< export class TerminalTool extends BaseTool<
TerminalToolParams, TerminalToolParams,
TerminalToolResult ToolResult
> { > {
static Name: string = 'execute_bash_command'; static Name: string = 'execute_bash_command';
@ -139,7 +131,7 @@ export class TerminalTool extends BaseTool<
private shouldAlwaysExecuteCommands: Map<string, boolean> = new Map(); // Track confirmation per root command private shouldAlwaysExecuteCommands: Map<string, boolean> = new Map(); // Track confirmation per root command
private shellReady: Promise<void>; private shellReady: Promise<void>;
private resolveShellReady: (() => void) | undefined; // Definite assignment assertion private resolveShellReady: (() => void) | undefined; // Definite assignment assertion
private rejectShellReady: ((reason?: any) => void) | undefined; // Definite assignment assertion private rejectShellReady: ((reason?: unknown) => void) | undefined; // Definite assignment assertion
private readonly backgroundTerminalAnalyzer: BackgroundTerminalAnalyzer; private readonly backgroundTerminalAnalyzer: BackgroundTerminalAnalyzer;
constructor( constructor(
@ -238,7 +230,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
if (this.bashProcess) { if (this.bashProcess) {
try { try {
this.bashProcess.kill(); this.bashProcess.kill();
} catch (e) { } catch {
/* Ignore */ /* Ignore */
} }
} }
@ -306,12 +298,12 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
); );
} }
}, 1000); // Increase readiness check timeout slightly }, 1000); // Increase readiness check timeout slightly
} catch (error: any) { } catch (error: unknown) {
console.error('Failed to spawn persistent bash:', error); console.error('Failed to spawn persistent bash:', error);
this.rejectShellReady?.(error); // Use optional chaining this.rejectShellReady?.(error); // Use optional chaining
this.bashProcess = null; this.bashProcess = null;
this.clearQueue( this.clearQueue(
new Error(`Failed to spawn persistent bash: ${error.message}`), new Error(`Failed to spawn persistent bash: ${getErrorMessage(error)}`),
); );
} }
} }
@ -331,7 +323,6 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
if (!commandOriginal) { if (!commandOriginal) {
return 'Command cannot be empty.'; return 'Command cannot be empty.';
} }
const commandLower = commandOriginal.toLowerCase();
const commandParts = commandOriginal.split(/[\s;&&|]+/); const commandParts = commandOriginal.split(/[\s;&&|]+/);
for (const part of commandParts) { for (const part of commandParts) {
@ -340,7 +331,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
const cleanPart = const cleanPart =
part part
.replace(/^[^a-zA-Z0-9]+/, '') .replace(/^[^a-zA-Z0-9]+/, '')
.split(/[\/\\]/) .split(/[/\\]/)
.pop() || part.replace(/^[^a-zA-Z0-9]+/, ''); .pop() || part.replace(/^[^a-zA-Z0-9]+/, '');
if (cleanPart && BANNED_COMMAND_ROOTS.includes(cleanPart.toLowerCase())) { if (cleanPart && BANNED_COMMAND_ROOTS.includes(cleanPart.toLowerCase())) {
return `Command contains a banned keyword: '${cleanPart}'. Banned list includes network tools, session control, etc.`; return `Command contains a banned keyword: '${cleanPart}'. Banned list includes network tools, session control, etc.`;
@ -354,12 +345,6 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
return 'Timeout must be a positive number of milliseconds.'; return 'Timeout must be a positive number of milliseconds.';
} }
// Relax the absolute path restriction slightly if needed, but generally good practice
// const firstCommandPart = commandParts[0];
// if (firstCommandPart && (firstCommandPart.startsWith('/') || firstCommandPart.startsWith('\\'))) {
// return 'Executing commands via absolute paths (starting with \'/\' or \'\\\') is restricted. Use commands available in PATH or relative paths.';
// }
return null; // Parameters are valid return null; // Parameters are valid
} }
@ -375,7 +360,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
params.command params.command
.trim() .trim()
.split(/[\s;&&|]+/)[0] .split(/[\s;&&|]+/)[0]
?.split(/[\/\\]/) ?.split(/[/\\]/)
.pop() || 'unknown'; .pop() || 'unknown';
if (this.shouldAlwaysExecuteCommands.get(rootCommand)) { if (this.shouldAlwaysExecuteCommands.get(rootCommand)) {
@ -399,7 +384,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
} }
// --- Command Execution and Queueing (unchanged structure) --- // --- Command Execution and Queueing (unchanged structure) ---
async execute(params: TerminalToolParams): Promise<TerminalToolResult> { async execute(params: TerminalToolParams): Promise<ToolResult> {
const validationError = this.validateToolParams(params); const validationError = this.validateToolParams(params);
if (validationError) { if (validationError) {
return { return {
@ -447,9 +432,14 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
// **** Core execution logic call **** // **** Core execution logic call ****
const result = await this.executeCommandInShell(params); const result = await this.executeCommandInShell(params);
resolve(result); // Resolve the specific command's promise resolve(result); // Resolve the specific command's promise
} catch (error: any) { } catch (error: unknown) {
console.error(`Error executing command "${params.command}":`, error); console.error(`Error executing command "${params.command}":`, error);
reject(error); // Use the specific command's reject handler
if (error instanceof Error) {
reject(error);
} else {
reject(new Error('Unknown error occurred: ' + JSON.stringify(error)));
}
} finally { } finally {
this.isExecuting = false; this.isExecuting = false;
// Use setImmediate to avoid potential deep recursion // Use setImmediate to avoid potential deep recursion
@ -460,16 +450,16 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
// --- **** MODIFIED: Core Command Execution Logic **** --- // --- **** MODIFIED: Core Command Execution Logic **** ---
private executeCommandInShell( private executeCommandInShell(
params: TerminalToolParams, params: TerminalToolParams,
): Promise<TerminalToolResult> { ): Promise<ToolResult> {
// Define temp file paths here to be accessible throughout // Define temp file paths here to be accessible throughout
let tempStdoutPath: string | null = null; let tempStdoutPath: string | null = null;
let tempStderrPath: string | null = null; let tempStderrPath: string | null = null;
let originalResolve: ( let originalResolve: (
value: TerminalToolResult | PromiseLike<TerminalToolResult>, value: ToolResult | PromiseLike<ToolResult>,
) => void; // To pass to polling ) => void; // To pass to polling
let originalReject: (reason?: any) => void; let originalReject: (reason?: unknown) => void;
const promise = new Promise<TerminalToolResult>((resolve, reject) => { const promise = new Promise<ToolResult>((resolve, reject) => {
originalResolve = resolve; // Assign outer scope resolve originalResolve = resolve; // Assign outer scope resolve
originalReject = reject; // Assign outer scope reject originalReject = reject; // Assign outer scope reject
@ -492,11 +482,11 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
const tempDir = os.tmpdir(); const tempDir = os.tmpdir();
tempStdoutPath = path.join(tempDir, `term_out_${commandUUID}.log`); tempStdoutPath = path.join(tempDir, `term_out_${commandUUID}.log`);
tempStderrPath = path.join(tempDir, `term_err_${commandUUID}.log`); tempStderrPath = path.join(tempDir, `term_err_${commandUUID}.log`);
} catch (err: any) { } catch (err: unknown) {
// If temp dir setup fails, reject immediately // If temp dir setup fails, reject immediately
return reject( return reject(
new Error( new Error(
`Failed to determine temporary directory: ${err.message}`, `Failed to determine temporary directory: ${getErrorMessage(err)}`,
), ),
); );
} }
@ -530,7 +520,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
if (!isBackgroundTask && this.bashProcess && !this.bashProcess.killed) { if (!isBackgroundTask && this.bashProcess && !this.bashProcess.killed) {
try { try {
this.bashProcess.stdin.write('\x03'); // Ctrl+C for foreground timeout this.bashProcess.stdin.write('\x03'); // Ctrl+C for foreground timeout
} catch (e: any) { } catch (e: unknown) {
console.error('Error writing SIGINT on timeout:', e); console.error('Error writing SIGINT on timeout:', e);
} }
} }
@ -664,8 +654,8 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
// --- Cleanup Logic --- // --- Cleanup Logic ---
// Pass listeners to allow cleanup even if they are nullified later // Pass listeners to allow cleanup even if they are nullified later
const cleanupListeners = (listeners?: { const cleanupListeners = (listeners?: {
onStdoutData: any; onStdoutData: ((data: Buffer) => void) | null;
onStderrData: any; onStderrData: ((data: Buffer) => void) | null;
}) => { }) => {
if (launchTimeoutId) clearTimeout(launchTimeoutId); if (launchTimeoutId) clearTimeout(launchTimeoutId);
launchTimeoutId = null; launchTimeoutId = null;
@ -750,10 +740,10 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
if (this.currentCwd !== latestCwd) { if (this.currentCwd !== latestCwd) {
this.currentCwd = latestCwd; this.currentCwd = latestCwd;
} }
} catch (e: any) { } catch (e: unknown) {
if (exitCode === 0) { if (exitCode === 0) {
// Only warn if the command itself succeeded // Only warn if the command itself succeeded
cwdUpdateError = `\nWarning: Failed to verify/update current working directory after command: ${e.message}`; cwdUpdateError = `\nWarning: Failed to verify/update current working directory after command: ${getErrorMessage(e)}`;
console.error( console.error(
'Failed to update CWD after successful command:', 'Failed to update CWD after successful command:',
e, e,
@ -916,7 +906,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
'Shell stdin is not writable or process closed when attempting to write command.', 'Shell stdin is not writable or process closed when attempting to write command.',
); );
} }
} catch (e: any) { } catch (e: unknown) {
console.error( console.error(
`Error writing command "${params.command}" to bash stdin (sync):`, `Error writing command "${params.command}" to bash stdin (sync):`,
e, e,
@ -931,7 +921,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
} }
originalReject( originalReject(
new Error( new Error(
`Shell stdin write exception: ${e.message}. Command likely did not execute.`, `Shell stdin write exception: ${getErrorMessage(e)}. Command likely did not execute.`,
), ),
); );
} }
@ -950,7 +940,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
tempStdoutPath: string, // Path to redirected stdout tempStdoutPath: string, // Path to redirected stdout
tempStderrPath: string, // Path to redirected stderr tempStderrPath: string, // Path to redirected stderr
resolve: ( resolve: (
value: TerminalToolResult | PromiseLike<TerminalToolResult>, value: ToolResult | PromiseLike<ToolResult>,
) => void, // The original promise's resolve ) => void, // The original promise's resolve
): Promise<void> { ): Promise<void> {
// This function manages its own lifecycle but resolves the outer promise // This function manages its own lifecycle but resolves the outer promise
@ -969,21 +959,21 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
); );
if (status === 'Unknown') llmAnalysis = `LLM analysis failed: ${summary}`; if (status === 'Unknown') llmAnalysis = `LLM analysis failed: ${summary}`;
else llmAnalysis = summary; else llmAnalysis = summary;
} catch (llmError: any) { } catch (llmerror: unknown) {
console.error( console.error(
`LLM analysis failed for PID ${pid} command "${command}":`, `LLM analysis failed for PID ${pid} command "${command}":`,
llmError, llmerror,
); );
llmAnalysis = `LLM analysis failed: ${llmError.message}`; // Include error in analysis placeholder llmAnalysis = `LLM analysis failed: ${getErrorMessage(llmerror)}`; // Include error in analysis placeholder
} }
// --- End LLM Call --- // --- End LLM Call ---
try { try {
finalStdout = await fs.readFile(tempStdoutPath, 'utf-8'); finalStdout = await fs.readFile(tempStdoutPath, 'utf-8');
finalStderr = await fs.readFile(tempStderrPath, 'utf-8'); finalStderr = await fs.readFile(tempStderrPath, 'utf-8');
} catch (err: any) { } catch (err: unknown) {
console.error(`Error reading temp output files for PID ${pid}:`, err); console.error(`Error reading temp output files for PID ${pid}:`, err);
fileReadError = `\nWarning: Failed to read temporary output files (${err.message}). Final output may be incomplete.`; fileReadError = `\nWarning: Failed to read temporary output files (${getErrorMessage(err)}). Final output may be incomplete.`;
} }
// --- Clean up temp files --- // --- Clean up temp files ---
@ -1009,13 +999,12 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
if (!filePath) return; if (!filePath) return;
try { try {
await fs.unlink(filePath); await fs.unlink(filePath);
} catch (err: any) { } catch (err: unknown) {
// Ignore errors like file not found (it might have been deleted already or failed to create) // Ignore errors like file not found (it might have been deleted already or failed to create)
if (err.code !== 'ENOENT') { if (!isNodeError(err) || err.code !== 'ENOENT') {
console.warn( console.warn(
`Failed to delete temporary file '${filePath}': ${err.message}`, `Failed to delete temporary file '${filePath}': ${getErrorMessage(err)}`,
); );
} else {
} }
} }
}; };
@ -1122,10 +1111,10 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
} else { } else {
throw new Error('Shell stdin not writable for pwd command.'); throw new Error('Shell stdin not writable for pwd command.');
} }
} catch (e: any) { } catch (e: unknown) {
console.error('Exception writing pwd command:', e); console.error('Exception writing pwd command:', e);
cleanupPwdListeners( cleanupPwdListeners(
new Error(`Exception writing pwd command: ${e.message}`), new Error(`Exception writing pwd command: ${getErrorMessage(e)}`),
); );
} }
}); });
@ -1145,7 +1134,6 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
// --- Clear Queue (unchanged) --- // --- Clear Queue (unchanged) ---
private clearQueue(error: Error) { private clearQueue(error: Error) {
const queuedCount = this.commandQueue.length;
const queue = this.commandQueue; const queue = this.commandQueue;
this.commandQueue = []; this.commandQueue = [];
queue.forEach(({ resolve, params }) => queue.forEach(({ resolve, params }) =>
@ -1196,13 +1184,12 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es
proc.kill('SIGKILL'); // Force kill if needed proc.kill('SIGKILL'); // Force kill if needed
} }
}, 500); // 500ms grace period }, 500); // 500ms grace period
} catch (e: any) { } catch (e: unknown) {
// Catch errors if process already exited etc. // Catch errors if process already exited etc.
console.warn( console.warn(
`Error trying to kill bash process PID: ${pid}: ${e.message}`, `Error trying to kill bash process PID: ${pid}: ${getErrorMessage(e)}`,
); );
} }
} else {
} }
// Note: We cannot reliably clean up temp files for background tasks // Note: We cannot reliably clean up temp files for background tasks

View File

@ -99,6 +99,7 @@ export abstract class BaseTool<
* @param params Parameters to validate * @param params Parameters to validate
* @returns An error message string if invalid, null otherwise * @returns An error message string if invalid, null otherwise
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
validateToolParams(params: TParams): string | null { validateToolParams(params: TParams): string | null {
// Implementation would typically use a JSON Schema validator // Implementation would typically use a JSON Schema validator
// This is a placeholder that should be implemented by derived classes // This is a placeholder that should be implemented by derived classes
@ -121,6 +122,7 @@ export abstract class BaseTool<
* @returns Whether or not execute should be confirmed by the user. * @returns Whether or not execute should be confirmed by the user.
*/ */
shouldConfirmExecute( shouldConfirmExecute(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
params: TParams, params: TParams,
): Promise<ToolCallConfirmationDetails | false> { ): Promise<ToolCallConfirmationDetails | false> {
return Promise.resolve(false); return Promise.resolve(false);

View File

@ -25,17 +25,12 @@ export interface WriteFileToolParams {
content: string; content: string;
} }
/**
* Standardized result from the WriteFile tool
*/
export interface WriteFileToolResult extends ToolResult {}
/** /**
* Implementation of the WriteFile tool that writes files to the filesystem * Implementation of the WriteFile tool that writes files to the filesystem
*/ */
export class WriteFileTool extends BaseTool< export class WriteFileTool extends BaseTool<
WriteFileToolParams, WriteFileToolParams,
WriteFileToolResult ToolResult
> { > {
static readonly Name: string = 'write_file'; static readonly Name: string = 'write_file';
private shouldAlwaysWrite = false; private shouldAlwaysWrite = false;
@ -143,7 +138,7 @@ export class WriteFileTool extends BaseTool<
let currentContent = ''; let currentContent = '';
try { try {
currentContent = fs.readFileSync(params.file_path, 'utf8'); currentContent = fs.readFileSync(params.file_path, 'utf8');
} catch (error) { } catch {
// File may not exist, which is fine // File may not exist, which is fine
} }
@ -184,7 +179,7 @@ export class WriteFileTool extends BaseTool<
* @param params Parameters for the file writing * @param params Parameters for the file writing
* @returns Result of the file writing operation * @returns Result of the file writing operation
*/ */
async execute(params: WriteFileToolParams): Promise<WriteFileToolResult> { async execute(params: WriteFileToolParams): Promise<ToolResult> {
const validationError = this.validateToolParams(params); const validationError = this.validateToolParams(params);
if (validationError) { if (validationError) {
return { return {