| 278 | |
| 279 | // ─── 工具执行器(模拟真实 Claude Code 工具执行结果)────────────────────── |
| 280 | function executeTool(name, input) { |
| 281 | switch (name) { |
| 282 | case 'LS': { |
| 283 | const path = input.path || '/project'; |
| 284 | const allPaths = Object.keys(VIRTUAL_FS); |
| 285 | const files = allPaths |
| 286 | .filter(p => p.startsWith(path)) |
| 287 | .map(p => p.replace(path, '').replace(/^\//, '')) |
| 288 | .filter(p => p.length > 0); |
| 289 | return files.length > 0 |
| 290 | ? files.join('\n') |
| 291 | : `Directory listing of ${path}:\n(empty)`; |
| 292 | } |
| 293 | |
| 294 | case 'Glob': { |
| 295 | const pattern = input.pattern.replace(/\*\*/g, '').replace(/\*/g, ''); |
| 296 | const ext = pattern.replace(/^\./, ''); |
| 297 | const matches = Object.keys(VIRTUAL_FS).filter(p => |
| 298 | p.endsWith(ext) || p.includes(pattern.replace('*.', '.')) |
| 299 | ); |
| 300 | return matches.length > 0 |
| 301 | ? matches.join('\n') |
| 302 | : `No files matching ${input.pattern}`; |
| 303 | } |
| 304 | |
| 305 | case 'Grep': { |
| 306 | const results = []; |
| 307 | for (const [fp, content] of Object.entries(VIRTUAL_FS)) { |
| 308 | const lines = content.split('\n'); |
| 309 | lines.forEach((line, i) => { |
| 310 | if (line.toLowerCase().includes(input.pattern.toLowerCase())) { |
| 311 | results.push(`${fp}:${i + 1}:${line.trim()}`); |
| 312 | } |
| 313 | }); |
| 314 | } |
| 315 | return results.length > 0 |
| 316 | ? results.join('\n') |
| 317 | : `No matches for "${input.pattern}"`; |
| 318 | } |
| 319 | |
| 320 | case 'Read': { |
| 321 | const content = VIRTUAL_FS[input.file_path]; |
| 322 | if (!content) return `Error: File not found: ${input.file_path}`; |
| 323 | if (input.start_line || input.end_line) { |
| 324 | const lines = content.split('\n'); |
| 325 | const start = (input.start_line || 1) - 1; |
| 326 | const end = input.end_line || lines.length; |
| 327 | return lines.slice(start, end).join('\n'); |
| 328 | } |
| 329 | return content; |
| 330 | } |
| 331 | |
| 332 | case 'Write': { |
| 333 | VIRTUAL_FS[input.file_path] = input.content; |
| 334 | return `Successfully wrote ${input.content.length} characters to ${input.file_path}`; |
| 335 | } |
| 336 | |
| 337 | case 'Edit': { |