From 0e73dc15275f24b7ba94a7c200939907690f70b2 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 18 Feb 2026 08:20:50 +0000 Subject: [PATCH] Fix terminal stability bugs: remove autoFocus from effect deps, stabilize memo, remove dead export - Remove autoFocus from the main terminal setup effect dependency array to prevent full terminal teardown/recreation when switching tabs in split view. Focus is already handled by a dedicated effect. - Change threadTerminalRuntimeEnv memo dependency from activeProject to activeProject?.cwd so unrelated project state changes (e.g. saving scripts) don't trigger terminal re-initialization. - Unexport injectEnvIntoShellCommand which is never imported by production code (env injection is handled server-side), and remove its tests. Applied via @cursor push command --- apps/web/src/components/ChatView.tsx | 2 +- .../src/components/ThreadTerminalDrawer.tsx | 2 +- apps/web/src/projectScripts.test.ts | 20 ------------------- apps/web/src/projectScripts.ts | 2 +- 4 files changed, 3 insertions(+), 23 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 1fd660c88f30f89af30a2078dd0b8190187ffc9c..27904e29e5ba563f60fc0295c6c2f307bf62ecb9 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -552,7 +552,7 @@ export default function ChatView() { }, worktreePath: activeThread?.worktreePath ?? null, }); - }, [activeProject, activeThread?.worktreePath]); + }, [activeProject?.cwd, activeThread?.worktreePath]); // Default true while loading to avoid toolbar flicker. const isGitRepo = branchesQuery.data?.isRepo ?? true; const splitTerminalShortcutLabel = useMemo( diff --git a/apps/web/src/components/ThreadTerminalDrawer.tsx b/apps/web/src/components/ThreadTerminalDrawer.tsx index 5d5c377fa6ee019703bdea67da4889e3d7ac65ea..c065d67a5a3d6868738fb5826fbd64ac64bf6256 100644 --- a/apps/web/src/components/ThreadTerminalDrawer.tsx +++ b/apps/web/src/components/ThreadTerminalDrawer.tsx @@ -372,7 +372,7 @@ function TerminalViewport({ fitAddonRef.current = null; terminal.dispose(); }; - }, [api, autoFocus, cwd, runtimeEnv, terminalId, threadId]); + }, [api, cwd, runtimeEnv, terminalId, threadId]); useEffect(() => { if (!autoFocus) return; diff --git a/apps/web/src/projectScripts.test.ts b/apps/web/src/projectScripts.test.ts index 525513446464e53014c63371894f6c12ceb732c2..dadc22a4710b5358072af807dc364570dcd0cedd 100644 --- a/apps/web/src/projectScripts.test.ts +++ b/apps/web/src/projectScripts.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it } from "vitest"; import { commandForProjectScript, - injectEnvIntoShellCommand, nextProjectScriptId, primaryProjectScript, projectScriptRuntimeEnv, @@ -24,25 +23,6 @@ describe("projectScripts helpers", () => { expect(nextProjectScriptId("!!!", [])).toBe("script"); }); - it("injects environment variables for posix shells", () => { - const command = injectEnvIntoShellCommand("bun install", { T3CODE_PROJECT_ROOT: "/tmp/project" }, "MacIntel"); - expect(command).toBe("env T3CODE_PROJECT_ROOT='/tmp/project' bun install"); - }); - - it("injects environment variables for windows shells", () => { - const command = injectEnvIntoShellCommand("bun install", { T3CODE_PROJECT_ROOT: "C:\\\\repo path" }, "Win32"); - expect(command).toBe('set "T3CODE_PROJECT_ROOT=C:\\\\repo path" && bun install'); - }); - - it("escapes windows env values that trigger interpolation", () => { - const command = injectEnvIntoShellCommand( - "bun install", - { T3CODE_PROJECT_ROOT: '%USERPROFILE%^"repo"' }, - "Win32", - ); - expect(command).toBe('set "T3CODE_PROJECT_ROOT=^%USERPROFILE^%^^""repo""" && bun install'); - }); - it("resolves primary and setup scripts", () => { const scripts = [ { diff --git a/apps/web/src/projectScripts.ts b/apps/web/src/projectScripts.ts index 15d0790a74e99a98077e1401c6aab079e99cdd3f..c09a801237fc3c813fc636f2bf027f6ae1591e1b 100644 --- a/apps/web/src/projectScripts.ts +++ b/apps/web/src/projectScripts.ts @@ -60,7 +60,7 @@ function shellEscapeWindowsSetValue(value: string): string { return value.replace(/\^/g, "^^").replace(/%/g, "^%").replace(/"/g, '""'); } -export function injectEnvIntoShellCommand( +function injectEnvIntoShellCommand( command: string, env: Record, platform = typeof navigator === "undefined" ? "" : navigator.platform, -- 2.54.0