-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Allow running commands in background automatically #8607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9dea0b5
49964a9
cab2ea7
66ad474
a4fdb06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { ToolArgs } from "./types" | ||
|
|
||
| export function getTerminalKillDescription(args: ToolArgs): string | undefined { | ||
| return `## terminal_kill | ||
| Description: Manage running processes in terminals. | ||
|
|
||
| Parameters: | ||
| - terminal_id: (required) The terminal ID containing the process to kill | ||
|
|
||
| Usage example: Kill a process running in terminal 1 | ||
| <terminal_kill> | ||
| <terminal_id>1</terminal_id> | ||
| </terminal_kill>` | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry" | ||
| import { Terminal } from "../../integrations/terminal/Terminal" | ||
| import { formatResponse } from "../prompts/responses" | ||
| import { Task } from "../task/Task" | ||
| import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools" | ||
|
|
||
| export async function terminalKillTool( | ||
| task: Task, | ||
| block: ToolUse, | ||
| askApproval: AskApproval, | ||
| handleError: HandleError, | ||
| pushToolResult: PushToolResult, | ||
| removeClosingTag: RemoveClosingTag, | ||
| ) { | ||
| const terminalId: string | undefined = block.params.terminal_id | ||
|
|
||
| try { | ||
| if (block.partial) { | ||
| await task.ask("tool", removeClosingTag("terminal_id", terminalId), block.partial).catch(() => {}) | ||
| return | ||
| } | ||
|
|
||
| if (!terminalId) { | ||
| task.consecutiveMistakeCount++ | ||
| task.recordToolError("terminal_kill") | ||
| pushToolResult(await task.sayAndCreateMissingParamError("terminal_kill", "terminal_id")) | ||
| return | ||
| } | ||
|
|
||
| // Get approval for the action | ||
| const didApprove = await askApproval("tool", `Kill process in terminal ${terminalId}`) | ||
| if (!didApprove) { | ||
| return | ||
| } | ||
|
|
||
| try { | ||
| const parsedId = parseInt(terminalId) | ||
| if (isNaN(parsedId)) { | ||
| task.consecutiveMistakeCount++ | ||
| task.recordToolError("terminal_kill") | ||
| pushToolResult(formatResponse.toolError(`Invalid terminal_id "${terminalId}". Must be a number.`)) | ||
| return | ||
| } | ||
|
|
||
| const result = await killTerminalProcess(parsedId) | ||
| pushToolResult(formatResponse.toolResult(result)) | ||
| } catch (error) { | ||
| await handleError("killing terminal process", error) | ||
| } | ||
| } catch (error) { | ||
| await handleError("terminal control operation", error) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Kills a process running in a specific terminal by sending Ctrl+C | ||
| * @param terminalId The terminal ID containing the process to kill | ||
| * @returns Promise<string> Result message | ||
| */ | ||
| async function killTerminalProcess(terminalId: number): Promise<string> { | ||
| const targetTerminal = findTerminal(terminalId) | ||
| if (!targetTerminal) { | ||
| return getTerminalNotFoundMessage(terminalId) | ||
| } | ||
|
|
||
| if (!targetTerminal.busy && !targetTerminal.process) { | ||
| return `Terminal ${terminalId} is not running any process.` | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent null checking for process. The condition at line 74 checks The early return condition should be |
||
|
|
||
| try { | ||
| if (targetTerminal instanceof Terminal) { | ||
| // For VSCode terminals, send Ctrl+C | ||
| targetTerminal.terminal.sendText("\x03") | ||
| return `Sent Ctrl+C to terminal ${terminalId}. Process should terminate shortly.` | ||
| } else { | ||
| // For ExecaTerminal, use the abort method | ||
| if (targetTerminal.process) { | ||
| targetTerminal.process.abort() | ||
| return `Terminated process in terminal ${terminalId}.` | ||
| } else { | ||
| return `No active process found in terminal ${terminalId}.` | ||
| } | ||
| } | ||
| } catch (error) { | ||
| throw new Error( | ||
| `Failed to kill process in terminal ${terminalId}: ${error instanceof Error ? error.message : String(error)}`, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Helper function to find a terminal by ID | ||
| */ | ||
| function findTerminal(terminalId: number) { | ||
| const busyTerminals = TerminalRegistry.getTerminals(true) | ||
| const allTerminals = TerminalRegistry.getTerminals(false) | ||
| const allTerminalsList = [...busyTerminals, ...allTerminals] | ||
|
|
||
| return allTerminalsList.find((t) => t.id === terminalId) | ||
| } | ||
|
|
||
| /** | ||
| * Helper function to get terminal not found message | ||
| */ | ||
| function getTerminalNotFoundMessage(terminalId: number): string { | ||
| const busyTerminals = TerminalRegistry.getTerminals(true) | ||
| const allTerminals = TerminalRegistry.getTerminals(false) | ||
| const allTerminalsList = [...busyTerminals, ...allTerminals] | ||
|
|
||
| return `Terminal ${terminalId} not found. Available terminals: ${allTerminalsList.map((t) => t.id).join(", ")}` | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.