| ... | @@ -26,6 +26,11 @@ import { runProcess } from "./processRunner"; | ... | @@ -26,6 +26,11 @@ import { runProcess } from "./processRunner"; |
| 26 | const DEFAULT_HISTORY_LINE_LIMIT = 5_000; | 26 | const DEFAULT_HISTORY_LINE_LIMIT = 5_000; |
| 27 | const DEFAULT_PERSIST_DEBOUNCE_MS = 40; | 27 | const DEFAULT_PERSIST_DEBOUNCE_MS = 40; |
| 28 | const DEFAULT_SUBPROCESS_POLL_INTERVAL_MS = 1_000; | 28 | const DEFAULT_SUBPROCESS_POLL_INTERVAL_MS = 1_000; |
| | 29 | const TERMINAL_ENV_BLOCKLIST = new Set([ |
| | 30 | "PORT", |
| | 31 | "ELECTRON_RENDERER_PORT", |
| | 32 | "ELECTRON_RUN_AS_NODE", |
| | 33 | ]); |
| 29 | | 34 | |
| 30 | type TerminalSubprocessChecker = (terminalPid: number) => Promise<boolean>; | 35 | type TerminalSubprocessChecker = (terminalPid: number) => Promise<boolean>; |
| 31 | | 36 | |
| ... | @@ -234,6 +239,27 @@ function toSessionKey(threadId: string, terminalId: string): string { | ... | @@ -234,6 +239,27 @@ function toSessionKey(threadId: string, terminalId: string): string { |
| 234 | return `${threadId}\u0000${terminalId}`; | 239 | return `${threadId}\u0000${terminalId}`; |
| 235 | } | 240 | } |
| 236 | | 241 | |
| | 242 | function shouldExcludeTerminalEnvKey(key: string): boolean { |
| | 243 | const normalizedKey = key.toUpperCase(); |
| | 244 | if (normalizedKey.startsWith("T3CODE_")) { |
| | 245 | return true; |
| | 246 | } |
| | 247 | if (normalizedKey.startsWith("VITE_")) { |
| | 248 | return true; |
| | 249 | } |
| | 250 | return TERMINAL_ENV_BLOCKLIST.has(normalizedKey); |
| | 251 | } |
| | 252 | |
| | 253 | function createTerminalSpawnEnv(baseEnv: NodeJS.ProcessEnv): NodeJS.ProcessEnv { |
| | 254 | const spawnEnv: NodeJS.ProcessEnv = {}; |
| | 255 | for (const [key, value] of Object.entries(baseEnv)) { |
| | 256 | if (value === undefined) continue; |
| | 257 | if (shouldExcludeTerminalEnvKey(key)) continue; |
| | 258 | spawnEnv[key] = value; |
| | 259 | } |
| | 260 | return spawnEnv; |
| | 261 | } |
| | 262 | |
| 237 | export class TerminalManager extends EventEmitter<TerminalManagerEvents> { | 263 | export class TerminalManager extends EventEmitter<TerminalManagerEvents> { |
| 238 | private readonly sessions = new Map<string, TerminalSessionState>(); | 264 | private readonly sessions = new Map<string, TerminalSessionState>(); |
| 239 | private readonly logsDir: string; | 265 | private readonly logsDir: string; |
| ... | @@ -467,6 +493,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { | ... | @@ -467,6 +493,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { |
| 467 | let startedShell: string | null = null; | 493 | let startedShell: string | null = null; |
| 468 | try { | 494 | try { |
| 469 | const shellCandidates = resolveShellCandidates(this.shellResolver); | 495 | const shellCandidates = resolveShellCandidates(this.shellResolver); |
| | 496 | const terminalEnv = createTerminalSpawnEnv(process.env); |
| 470 | let lastSpawnError: unknown = null; | 497 | let lastSpawnError: unknown = null; |
| 471 | | 498 | |
| 472 | for (const shell of shellCandidates) { | 499 | for (const shell of shellCandidates) { |
| ... | @@ -476,7 +503,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { | ... | @@ -476,7 +503,7 @@ export class TerminalManager extends EventEmitter<TerminalManagerEvents> { |
| 476 | cwd: session.cwd, | 503 | cwd: session.cwd, |
| 477 | cols: session.cols, | 504 | cols: session.cols, |
| 478 | rows: session.rows, | 505 | rows: session.rows, |
| 479 | env: process.env, | 506 | env: terminalEnv, |
| 480 | }); | 507 | }); |
| 481 | startedShell = shell; | 508 | startedShell = shell; |
| 482 | break; | 509 | break; |