Skip to content

Commit d1612f4

Browse files
committed
fix: preserve existing environment variables when creating terminals
- Modified Terminal.getEnv() to spread process.env first, preserving nix-shell and other environment variables - Updated TerminalRegistry tests to use expect.objectContaining() for environment checks - Added comprehensive tests for environment preservation in Terminal.env-preservation.spec.ts Fixes #7021
1 parent 245bc2a commit d1612f4

File tree

3 files changed

+135
-8
lines changed

3 files changed

+135
-8
lines changed

src/integrations/terminal/Terminal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ export class Terminal extends BaseTerminal {
151151
}
152152

153153
public static getEnv(): Record<string, string> {
154+
// Start with the existing process environment to preserve nix-shell and other environment variables
154155
const env: Record<string, string> = {
156+
...process.env,
155157
PAGER: process.platform === "win32" ? "" : "cat",
156158

157159
// VTE must be disabled because it prevents the prompt command from executing
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// npx vitest run src/integrations/terminal/__tests__/Terminal.env-preservation.spec.ts
2+
3+
import { Terminal } from "../Terminal"
4+
5+
describe("Terminal.getEnv() - Environment Preservation", () => {
6+
let originalEnv: NodeJS.ProcessEnv
7+
8+
beforeEach(() => {
9+
// Save original environment
10+
originalEnv = { ...process.env }
11+
})
12+
13+
afterEach(() => {
14+
// Restore original environment
15+
process.env = originalEnv
16+
})
17+
18+
it("should preserve existing environment variables", () => {
19+
// Set up test environment variables (simulating nix-shell)
20+
process.env.NIX_BUILD_CORES = "4"
21+
process.env.NIX_STORE = "/nix/store"
22+
process.env.IN_NIX_SHELL = "impure"
23+
process.env.CUSTOM_VAR = "custom_value"
24+
25+
const env = Terminal.getEnv()
26+
27+
// Check that nix-shell variables are preserved
28+
expect(env.NIX_BUILD_CORES).toBe("4")
29+
expect(env.NIX_STORE).toBe("/nix/store")
30+
expect(env.IN_NIX_SHELL).toBe("impure")
31+
expect(env.CUSTOM_VAR).toBe("custom_value")
32+
33+
// Check that Roo Code specific variables are still set
34+
expect(env.PAGER).toBe(process.platform === "win32" ? "" : "cat")
35+
expect(env.VTE_VERSION).toBe("0")
36+
})
37+
38+
it("should override specific environment variables when needed", () => {
39+
// Set conflicting environment variables
40+
process.env.PAGER = "less"
41+
process.env.VTE_VERSION = "6003"
42+
43+
const env = Terminal.getEnv()
44+
45+
// Check that Roo Code overrides take precedence
46+
expect(env.PAGER).toBe(process.platform === "win32" ? "" : "cat")
47+
expect(env.VTE_VERSION).toBe("0")
48+
})
49+
50+
it("should preserve PATH and other critical environment variables", () => {
51+
// Set critical environment variables
52+
process.env.PATH = "/usr/local/bin:/usr/bin:/bin"
53+
process.env.HOME = "/home/user"
54+
process.env.USER = "testuser"
55+
process.env.SHELL = "/bin/zsh"
56+
57+
const env = Terminal.getEnv()
58+
59+
// Check that critical variables are preserved
60+
expect(env.PATH).toBe("/usr/local/bin:/usr/bin:/bin")
61+
expect(env.HOME).toBe("/home/user")
62+
expect(env.USER).toBe("testuser")
63+
expect(env.SHELL).toBe("/bin/zsh")
64+
})
65+
66+
it("should handle undefined environment variables gracefully", () => {
67+
// Clear some environment variables
68+
delete process.env.SOME_UNDEFINED_VAR
69+
70+
const env = Terminal.getEnv()
71+
72+
// Should not throw and should not include undefined values
73+
expect(env.SOME_UNDEFINED_VAR).toBeUndefined()
74+
})
75+
76+
it("should preserve nix-shell specific environment modifications", () => {
77+
// Simulate a comprehensive nix-shell environment
78+
process.env.NIX_BUILD_CORES = "8"
79+
process.env.NIX_STORE = "/nix/store"
80+
process.env.IN_NIX_SHELL = "impure"
81+
process.env.NIX_ENFORCE_NO_NATIVE = "1"
82+
process.env.PKG_CONFIG_PATH = "/nix/store/xxx/lib/pkgconfig"
83+
process.env.NODE_PATH = "/nix/store/yyy/lib/node_modules"
84+
process.env.buildInputs = "/nix/store/aaa /nix/store/bbb"
85+
process.env.nativeBuildInputs = "/nix/store/ccc /nix/store/ddd"
86+
87+
const env = Terminal.getEnv()
88+
89+
// All nix-shell variables should be preserved
90+
expect(env.NIX_BUILD_CORES).toBe("8")
91+
expect(env.NIX_STORE).toBe("/nix/store")
92+
expect(env.IN_NIX_SHELL).toBe("impure")
93+
expect(env.NIX_ENFORCE_NO_NATIVE).toBe("1")
94+
expect(env.PKG_CONFIG_PATH).toBe("/nix/store/xxx/lib/pkgconfig")
95+
expect(env.NODE_PATH).toBe("/nix/store/yyy/lib/node_modules")
96+
expect(env.buildInputs).toBe("/nix/store/aaa /nix/store/bbb")
97+
expect(env.nativeBuildInputs).toBe("/nix/store/ccc /nix/store/ddd")
98+
})
99+
100+
it("should add PROMPT_EOL_MARK when Terminal.getTerminalZshClearEolMark() is true", () => {
101+
// This is the default behavior
102+
const originalValue = Terminal.getTerminalZshClearEolMark()
103+
Terminal.setTerminalZshClearEolMark(true)
104+
105+
try {
106+
const env = Terminal.getEnv()
107+
expect(env.PROMPT_EOL_MARK).toBe("")
108+
} finally {
109+
Terminal.setTerminalZshClearEolMark(originalValue)
110+
}
111+
})
112+
113+
it("should not override PROMPT_EOL_MARK when Terminal.getTerminalZshClearEolMark() is false", () => {
114+
const originalValue = Terminal.getTerminalZshClearEolMark()
115+
Terminal.setTerminalZshClearEolMark(false)
116+
process.env.PROMPT_EOL_MARK = "%"
117+
118+
try {
119+
const env = Terminal.getEnv()
120+
expect(env.PROMPT_EOL_MARK).toBe("%")
121+
} finally {
122+
Terminal.setTerminalZshClearEolMark(originalValue)
123+
}
124+
})
125+
})

src/integrations/terminal/__tests__/TerminalRegistry.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ describe("TerminalRegistry", () => {
4444
cwd: "/test/path",
4545
name: "Roo Code",
4646
iconPath: expect.any(Object),
47-
env: {
47+
env: expect.objectContaining({
4848
PAGER,
4949
VTE_VERSION: "0",
5050
PROMPT_EOL_MARK: "",
51-
},
51+
}),
5252
})
5353
})
5454

@@ -64,12 +64,12 @@ describe("TerminalRegistry", () => {
6464
cwd: "/test/path",
6565
name: "Roo Code",
6666
iconPath: expect.any(Object),
67-
env: {
67+
env: expect.objectContaining({
6868
PAGER,
6969
PROMPT_COMMAND: "sleep 0.05",
7070
VTE_VERSION: "0",
7171
PROMPT_EOL_MARK: "",
72-
},
72+
}),
7373
})
7474
} finally {
7575
// Restore original delay
@@ -86,12 +86,12 @@ describe("TerminalRegistry", () => {
8686
cwd: "/test/path",
8787
name: "Roo Code",
8888
iconPath: expect.any(Object),
89-
env: {
89+
env: expect.objectContaining({
9090
PAGER,
9191
VTE_VERSION: "0",
9292
PROMPT_EOL_MARK: "",
9393
ITERM_SHELL_INTEGRATION_INSTALLED: "Yes",
94-
},
94+
}),
9595
})
9696
} finally {
9797
Terminal.setTerminalZshOhMy(false)
@@ -107,12 +107,12 @@ describe("TerminalRegistry", () => {
107107
cwd: "/test/path",
108108
name: "Roo Code",
109109
iconPath: expect.any(Object),
110-
env: {
110+
env: expect.objectContaining({
111111
PAGER,
112112
VTE_VERSION: "0",
113113
PROMPT_EOL_MARK: "",
114114
POWERLEVEL9K_TERM_SHELL_INTEGRATION: "true",
115-
},
115+
}),
116116
})
117117
} finally {
118118
Terminal.setTerminalZshP10k(false)

0 commit comments

Comments
 (0)