Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/integrations/terminal/ExecaTerminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import process from "process"
import type { RooTerminal } from "./types"
import { BaseTerminal } from "./BaseTerminal"
import { BaseTerminalProcess } from "./BaseTerminalProcess"
import { getShell } from "../../utils/shell"

export class ExecaTerminalProcess extends BaseTerminalProcess {
private terminalRef: WeakRef<RooTerminal>
Expand Down Expand Up @@ -40,7 +41,7 @@ export class ExecaTerminalProcess extends BaseTerminalProcess {
this.isHot = true

this.subprocess = execa({
shell: BaseTerminal.getExecaShellPath() || true,
shell: BaseTerminal.getExecaShellPath() || getShell(),
cwd: this.terminal.getCurrentWorkingDirectory(),
all: true,
// Ignore stdin to ensure non-interactive mode and prevent hanging
Expand Down Expand Up @@ -111,7 +112,7 @@ export class ExecaTerminalProcess extends BaseTerminalProcess {
timeoutId = setTimeout(() => {
try {
this.subprocess?.kill("SIGKILL")
} catch (e) {}
} catch (e) { }

resolve()
}, 5_000)
Expand Down
3 changes: 2 additions & 1 deletion src/integrations/terminal/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BaseTerminal } from "./BaseTerminal"
import { TerminalProcess } from "./TerminalProcess"
import { ShellIntegrationManager } from "./ShellIntegrationManager"
import { mergePromise } from "./mergePromise"
import { getShell } from "../../utils/shell"

export class Terminal extends BaseTerminal {
public terminal: vscode.Terminal
Expand All @@ -17,7 +18,7 @@ export class Terminal extends BaseTerminal {

const env = Terminal.getEnv()
const iconPath = new vscode.ThemeIcon("rocket")
this.terminal = terminal ?? vscode.window.createTerminal({ cwd, name: "Roo Code", iconPath, env })
this.terminal = terminal ?? vscode.window.createTerminal({ cwd, name: "Roo Code", iconPath, env, shellPath: getShell() })

if (Terminal.getTerminalZdotdir()) {
ShellIntegrationManager.terminalTmpDirs.set(id, env.ZDOTDIR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { execa } from "execa"
import { ExecaTerminalProcess } from "../ExecaTerminalProcess"
import { BaseTerminal } from "../BaseTerminal"
import type { RooTerminal } from "../types"
import * as shellUtils from "../../../utils/shell"

describe("ExecaTerminalProcess", () => {
let mockTerminal: RooTerminal
Expand All @@ -34,6 +35,7 @@ describe("ExecaTerminalProcess", () => {
beforeEach(() => {
originalEnv = { ...process.env }
BaseTerminal.setExecaShellPath(undefined)
vitest.spyOn(shellUtils, "getShell").mockReturnValue("/mock/fallback-shell")
mockTerminal = {
provider: "execa",
id: 1,
Expand All @@ -54,7 +56,7 @@ describe("ExecaTerminalProcess", () => {

afterEach(() => {
process.env = originalEnv
vitest.clearAllMocks()
vitest.restoreAllMocks()
})

describe("UTF-8 encoding fix", () => {
Expand All @@ -63,7 +65,7 @@ describe("ExecaTerminalProcess", () => {
const execaMock = vitest.mocked(execa)
expect(execaMock).toHaveBeenCalledWith(
expect.objectContaining({
shell: true,
shell: "/mock/fallback-shell",
cwd: "/test/cwd",
all: true,
env: expect.objectContaining({
Expand Down Expand Up @@ -105,13 +107,13 @@ describe("ExecaTerminalProcess", () => {
)
})

it("should fall back to shell=true when execaShellPath is undefined", async () => {
it("should fall back to getShell() when execaShellPath is undefined", async () => {
BaseTerminal.setExecaShellPath(undefined)
await terminalProcess.run("echo test")
const execaMock = vitest.mocked(execa)
expect(execaMock).toHaveBeenCalledWith(
expect.objectContaining({
shell: true,
shell: "/mock/fallback-shell",
}),
)
})
Expand Down
19 changes: 15 additions & 4 deletions src/integrations/terminal/__tests__/TerminalRegistry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as vscode from "vscode"
import { Terminal } from "../Terminal"
import { TerminalRegistry } from "../TerminalRegistry"
import * as shellUtils from "../../../utils/shell"

const PAGER = process.platform === "win32" ? "" : "cat"

Expand Down Expand Up @@ -34,6 +35,12 @@ describe("TerminalRegistry", () => {
},
}) as any,
)

vi.spyOn(shellUtils, "getShell").mockReturnValue("/mock/fallback-shell")
})

afterEach(() => {
vi.restoreAllMocks()
})

describe("createTerminal", () => {
Expand All @@ -43,13 +50,14 @@ describe("TerminalRegistry", () => {
expect(mockCreateTerminal).toHaveBeenCalledWith({
cwd: "/test/path",
name: "Roo Code",
iconPath: expect.any(Object),
iconPath: expect.objectContaining({ id: expect.any(String) }),
env: {
PAGER,
ROO_ACTIVE: "true",
VTE_VERSION: "0",
PROMPT_EOL_MARK: "",
},
shellPath: "/mock/fallback-shell",
})
})

Expand All @@ -64,14 +72,15 @@ describe("TerminalRegistry", () => {
expect(mockCreateTerminal).toHaveBeenCalledWith({
cwd: "/test/path",
name: "Roo Code",
iconPath: expect.any(Object),
iconPath: expect.objectContaining({ id: expect.any(String) }),
env: {
PAGER,
ROO_ACTIVE: "true",
PROMPT_COMMAND: "sleep 0.05",
VTE_VERSION: "0",
PROMPT_EOL_MARK: "",
},
shellPath: "/mock/fallback-shell",
})
} finally {
// Restore original delay
Expand All @@ -87,14 +96,15 @@ describe("TerminalRegistry", () => {
expect(mockCreateTerminal).toHaveBeenCalledWith({
cwd: "/test/path",
name: "Roo Code",
iconPath: expect.any(Object),
iconPath: expect.objectContaining({ id: expect.any(String) }),
env: {
PAGER,
ROO_ACTIVE: "true",
VTE_VERSION: "0",
PROMPT_EOL_MARK: "",
ITERM_SHELL_INTEGRATION_INSTALLED: "Yes",
},
shellPath: "/mock/fallback-shell",
})
} finally {
Terminal.setTerminalZshOhMy(false)
Expand All @@ -109,14 +119,15 @@ describe("TerminalRegistry", () => {
expect(mockCreateTerminal).toHaveBeenCalledWith({
cwd: "/test/path",
name: "Roo Code",
iconPath: expect.any(Object),
iconPath: expect.objectContaining({ id: expect.any(String) }),
env: {
PAGER,
ROO_ACTIVE: "true",
VTE_VERSION: "0",
PROMPT_EOL_MARK: "",
POWERLEVEL9K_TERM_SHELL_INTEGRATION: "true",
},
shellPath: "/mock/fallback-shell",
})
} finally {
Terminal.setTerminalZshP10k(false)
Expand Down
Loading