| 84 | }; |
| 85 | |
| 86 | function mockExec(name, input) { |
| 87 | switch (name) { |
| 88 | case 'Read': return MOCK_FS[input.file_path] || `Error: File not found: ${input.file_path}`; |
| 89 | case 'Write': { MOCK_FS[input.file_path] = input.content; return `Wrote ${input.content.length} chars`; } |
| 90 | case 'Bash': { |
| 91 | if (input.command?.includes('npm test')) return 'Tests passed: 3/3'; |
| 92 | if (input.command?.includes('tsc')) return 'Compilation successful'; |
| 93 | return `$ ${input.command}\n(ok)`; |
| 94 | } |
| 95 | case 'Grep': { |
| 96 | const results = []; |
| 97 | for (const [fp, c] of Object.entries(MOCK_FS)) { |
| 98 | c.split('\n').forEach((line, i) => { |
| 99 | if (line.toLowerCase().includes((input.pattern || '').toLowerCase())) |
| 100 | results.push(`${fp}:${i + 1}:${line.trim()}`); |
| 101 | }); |
| 102 | } |
| 103 | return results.join('\n') || 'No matches.'; |
| 104 | } |
| 105 | case 'LS': return Object.keys(MOCK_FS).filter(p => p.startsWith(input.path || '/project')).join('\n'); |
| 106 | case 'attempt_completion': return `__DONE__:${input.result}`; |
| 107 | default: return `Executed ${name}`; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // ─── 多轮引擎 ───────────────────────────────────────────────────── |
| 112 | async function runMultiTurn(userMessage, opts = {}) { |