工具与执行引擎
const BashToolDefinition: ToolDefinition = { name: 'BashTool', description: 'Execute shell commands with streaming output', inputSchema: z.object({ command: z.string(), timeout: z.number().optional().default(30000), description: z.string().optional(), sandbox: z.boolean().optional(), shellExecutable: z.string().optional() }), async checkPermissions(input, context, permContext) { const { command, sandbox } = input; const parsed = ShellParser.parse(command, process.env); const baseCommand = parsed[0]; const FORBIDDEN = ['find', 'grep', 'cat', 'head', 'tail', 'ls']; if (FORBIDDEN.includes(baseCommand) && !permContext.mode.includes('bypass')) { return { behavior: 'deny', message: `Use dedicated tools instead of ${baseCommand}` }; } const DANGEROUS = ['rm', 'dd', 'mkfs', 'fdisk', 'kill']; if (DANGEROUS.some(cmd => command.includes(cmd))) { return { behavior: 'ask', message: 'This command could be dangerous', ruleSuggestions: [`BashTool(${baseCommand}/*)`] }; } if (sandbox === true) { const SANDBOX_SAFE = ['echo', 'pwd', 'env', 'date', 'which']; if (SANDBOX_SAFE.includes(baseCommand)) { return { behavior: 'allow' }; } } return await super.checkPermissions(input, context, permContext); }, async *call(input, context) { const { command, timeout, sandbox = false } = input; yield { type: 'progress', toolUseID: context.currentToolUseId, data: { status: 'Preparing command execution...', command: command.substring(0, 100), sandbox } }; const execOptions = { cwd: context.cwd, env: { ...process.env, CLAUDE_CODE: 'true' }, timeout, maxBuffer: 10 * 1024 * 1024, killSignal: 'SIGTERM' }; if (sandbox && process.platform === 'darwin') { const profile = this.generateSandboxProfile(); const sandboxedCommand = `sandbox-exec -p '${profile}' ${command}`; return yield* this.executeCommand(sandboxedCommand, execOptions, context); } yield* this.executeCommand(command, execOptions, context); }, async *executeCommand(command, options, context) { const startTime = Date.now(); const child = spawn('bash', ['-c', command], options); let stdout =...