(input: BashToolInput, toolUseContext, _canUseTool?: CanUseToolFn, parentMessage?: AssistantMessage, onProgress?: ToolCallProgress<BashProgress>)
| 622 | }; |
| 623 | }, |
| 624 | async call(input: BashToolInput, toolUseContext, _canUseTool?: CanUseToolFn, parentMessage?: AssistantMessage, onProgress?: ToolCallProgress<BashProgress>) { |
| 625 | // Handle simulated sed edit - apply directly instead of running sed |
| 626 | // This ensures what the user previewed is exactly what gets written |
| 627 | if (input._simulatedSedEdit) { |
| 628 | return applySedEdit(input._simulatedSedEdit, toolUseContext, parentMessage); |
| 629 | } |
| 630 | const { |
| 631 | abortController, |
| 632 | getAppState, |
| 633 | setAppState, |
| 634 | setToolJSX |
| 635 | } = toolUseContext; |
| 636 | const stdoutAccumulator = new EndTruncatingAccumulator(); |
| 637 | let stderrForShellReset = ''; |
| 638 | let interpretationResult: ReturnType<typeof interpretCommandResult> | undefined; |
| 639 | let progressCounter = 0; |
| 640 | let wasInterrupted = false; |
| 641 | let result: ExecResult; |
| 642 | const isMainThread = !toolUseContext.agentId; |
| 643 | const preventCwdChanges = !isMainThread; |
| 644 | try { |
| 645 | // Use the new async generator version of runShellCommand |
| 646 | const commandGenerator = runShellCommand({ |
| 647 | input, |
| 648 | abortController, |
| 649 | // Use the always-shared task channel so async agents' background |
| 650 | // bash tasks are actually registered (and killable on agent exit). |
| 651 | setAppState: toolUseContext.setAppStateForTasks ?? setAppState, |
| 652 | setToolJSX, |
| 653 | preventCwdChanges, |
| 654 | isMainThread, |
| 655 | toolUseId: toolUseContext.toolUseId, |
| 656 | agentId: toolUseContext.agentId |
| 657 | }); |
| 658 | |
| 659 | // Consume the generator and capture the return value |
| 660 | let generatorResult; |
| 661 | do { |
| 662 | generatorResult = await commandGenerator.next(); |
| 663 | if (!generatorResult.done && onProgress) { |
| 664 | const progress = generatorResult.value; |
| 665 | onProgress({ |
| 666 | toolUseID: `bash-progress-${progressCounter++}`, |
| 667 | data: { |
| 668 | type: 'bash_progress', |
| 669 | output: progress.output, |
| 670 | fullOutput: progress.fullOutput, |
| 671 | elapsedTimeSeconds: progress.elapsedTimeSeconds, |
| 672 | totalLines: progress.totalLines, |
| 673 | totalBytes: progress.totalBytes, |
| 674 | taskId: progress.taskId, |
| 675 | timeoutMs: progress.timeoutMs |
| 676 | } |
| 677 | }); |
| 678 | } |
| 679 | } while (!generatorResult.done); |
| 680 | |
| 681 | // Get the final result from the generator's return value |
nothing calls this directly
no test coverage detected