shell tweaks, better handling for windows (#5455)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Aiden Cline
2025-12-12 14:11:07 -08:00
committed by GitHub
parent 91ab966921
commit 15caecdb45
6 changed files with 116 additions and 80 deletions

View File

@@ -50,6 +50,7 @@ import { fn } from "@/util/fn"
import { SessionProcessor } from "./processor"
import { TaskTool } from "@/tool/task"
import { SessionStatus } from "./status"
import { Shell } from "@/shell/shell"
// @ts-ignore
globalThis.AI_SDK_LOG_WARNINGS = false
@@ -1172,6 +1173,12 @@ export namespace SessionPrompt {
})
export type ShellInput = z.infer<typeof ShellInput>
export async function shell(input: ShellInput) {
const abort = start(input.sessionID)
if (!abort) {
throw new Session.BusyError(input.sessionID)
}
using _ = defer(() => cancel(input.sessionID))
const session = await Session.get(input.sessionID)
if (session.revert) {
SessionRevert.cleanup(session)
@@ -1244,8 +1251,10 @@ export namespace SessionPrompt {
},
}
await Session.updatePart(part)
const shell = process.env["SHELL"] ?? (process.platform === "win32" ? process.env["COMSPEC"] || "cmd.exe" : "bash")
const shellName = path.basename(shell).toLowerCase()
const shell = Shell.preferred()
const shellName = (
process.platform === "win32" ? path.win32.basename(shell, ".exe") : path.basename(shell)
).toLowerCase()
const invocations: Record<string, { args: string[] }> = {
nu: {
@@ -1275,12 +1284,15 @@ export namespace SessionPrompt {
`,
],
},
// Windows cmd.exe
"cmd.exe": {
// Windows cmd
cmd: {
args: ["/c", input.command],
},
// Windows PowerShell
"powershell.exe": {
powershell: {
args: ["-NoProfile", "-Command", input.command],
},
pwsh: {
args: ["-NoProfile", "-Command", input.command],
},
// Fallback: any shell that doesn't match those above
@@ -1327,11 +1339,34 @@ export namespace SessionPrompt {
}
})
let aborted = false
let exited = false
const kill = () => Shell.killTree(proc, { exited: () => exited })
if (abort.aborted) {
aborted = true
await kill()
}
const abortHandler = () => {
aborted = true
void kill()
}
abort.addEventListener("abort", abortHandler, { once: true })
await new Promise<void>((resolve) => {
proc.on("close", () => {
exited = true
abort.removeEventListener("abort", abortHandler)
resolve()
})
})
if (aborted) {
output += "\n\n" + ["<metadata>", "User aborted the command", "</metadata>"].join("\n")
}
msg.time.completed = Date.now()
await Session.updateMessage(msg)
if (part.state.status === "running") {