86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import { exec } from 'child_process';
|
|
import { promisify } from 'util';
|
|
import { ToolResult } from '../types/index.js';
|
|
import { ConfirmationService } from '../utils/confirmation-service.js';
|
|
|
|
const execAsync = promisify(exec);
|
|
|
|
export class BashTool {
|
|
private currentDirectory: string = process.cwd();
|
|
private confirmationService = ConfirmationService.getInstance();
|
|
|
|
|
|
async execute(command: string, timeout: number = 30000): Promise<ToolResult> {
|
|
try {
|
|
// Check if user has already accepted bash commands for this session
|
|
const sessionFlags = this.confirmationService.getSessionFlags();
|
|
if (!sessionFlags.bashCommands && !sessionFlags.allOperations) {
|
|
// Request confirmation showing the command
|
|
const confirmationResult = await this.confirmationService.requestConfirmation({
|
|
operation: 'Run bash command',
|
|
filename: command,
|
|
showVSCodeOpen: false,
|
|
content: `Command: ${command}\nWorking directory: ${this.currentDirectory}`
|
|
}, 'bash');
|
|
|
|
if (!confirmationResult.confirmed) {
|
|
return {
|
|
success: false,
|
|
error: confirmationResult.feedback || 'Command execution cancelled by user'
|
|
};
|
|
}
|
|
}
|
|
|
|
if (command.startsWith('cd ')) {
|
|
const newDir = command.substring(3).trim();
|
|
try {
|
|
process.chdir(newDir);
|
|
this.currentDirectory = process.cwd();
|
|
return {
|
|
success: true,
|
|
output: `Changed directory to: ${this.currentDirectory}`
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
error: `Cannot change directory: ${error.message}`
|
|
};
|
|
}
|
|
}
|
|
|
|
const { stdout, stderr } = await execAsync(command, {
|
|
cwd: this.currentDirectory,
|
|
timeout,
|
|
maxBuffer: 1024 * 1024
|
|
});
|
|
|
|
const output = stdout + (stderr ? `\nSTDERR: ${stderr}` : '');
|
|
|
|
return {
|
|
success: true,
|
|
output: output.trim() || 'Command executed successfully (no output)'
|
|
};
|
|
} catch (error: any) {
|
|
return {
|
|
success: false,
|
|
error: `Command failed: ${error.message}`
|
|
};
|
|
}
|
|
}
|
|
|
|
getCurrentDirectory(): string {
|
|
return this.currentDirectory;
|
|
}
|
|
|
|
async listFiles(directory: string = '.'): Promise<ToolResult> {
|
|
return this.execute(`ls -la ${directory}`);
|
|
}
|
|
|
|
async findFiles(pattern: string, directory: string = '.'): Promise<ToolResult> {
|
|
return this.execute(`find ${directory} -name "${pattern}" -type f`);
|
|
}
|
|
|
|
async grep(pattern: string, files: string = '.'): Promise<ToolResult> {
|
|
return this.execute(`grep -r "${pattern}" ${files}`);
|
|
}
|
|
} |