Просмотр исходного кода

Merge pull request #728 from nissa-seru/add-command-fixes-from-cline

Add command fixes
Matt Rubens 11 месяцев назад
Родитель
Сommit
8472ae093a

+ 22 - 22
src/core/prompts/__tests__/__snapshots__/system.test.ts.snap

@@ -132,7 +132,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -291,7 +291,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -455,7 +455,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -614,7 +614,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -778,7 +778,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -937,7 +937,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -1147,7 +1147,7 @@ Example: Requesting to click on the element at coordinates 450,300
 </browser_action>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -1309,7 +1309,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -1473,7 +1473,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -2045,7 +2045,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -2255,7 +2255,7 @@ Example: Requesting to click on the element at coordinates 450,300
 </browser_action>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -2417,7 +2417,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -2641,7 +2641,7 @@ Your search/replace content here
 </apply_diff>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -2802,7 +2802,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -2966,7 +2966,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -3125,7 +3125,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -3331,7 +3331,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -3549,7 +3549,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -3873,7 +3873,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -4182,7 +4182,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 
@@ -4376,7 +4376,7 @@ Example: Requesting to write to frontend-config.json
 </write_to_file>
 
 ## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: /test/path
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:
@@ -4948,7 +4948,7 @@ RULES
 SYSTEM INFORMATION
 
 Operating System: Linux
-Default Shell: /bin/bash
+Default Shell: /bin/zsh
 Home Directory: /home/user
 Current Working Directory: /test/path
 

+ 5 - 1
src/core/prompts/__tests__/system.test.ts

@@ -65,10 +65,14 @@ jest.mock("os", () => ({
 	homedir: () => "/home/user",
 }))
 
-jest.mock("default-shell", () => "/bin/bash")
+jest.mock("default-shell", () => "/bin/zsh")
 
 jest.mock("os-name", () => () => "Linux")
 
+jest.mock("../../../utils/shell", () => ({
+	getShell: () => "/bin/zsh",
+}))
+
 // Create a mock ExtensionContext
 const mockContext = {
 	extensionPath: "/mock/extension/path",

+ 2 - 1
src/core/prompts/sections/system-info.ts

@@ -2,6 +2,7 @@ import defaultShell from "default-shell"
 import os from "os"
 import osName from "os-name"
 import { Mode, ModeConfig, getModeBySlug, defaultModeSlug, isToolAllowedForMode } from "../../../shared/modes"
+import { getShell } from "../../../utils/shell"
 
 export function getSystemInfoSection(cwd: string, currentMode: Mode, customModes?: ModeConfig[]): string {
 	const findModeBySlug = (slug: string, modes?: ModeConfig[]) => modes?.find((m) => m.slug === slug)
@@ -14,7 +15,7 @@ export function getSystemInfoSection(cwd: string, currentMode: Mode, customModes
 SYSTEM INFORMATION
 
 Operating System: ${osName()}
-Default Shell: ${defaultShell}
+Default Shell: ${getShell()}
 Home Directory: ${os.homedir().toPosix()}
 Current Working Directory: ${cwd.toPosix()}
 

+ 1 - 1
src/core/prompts/tools/execute-command.ts

@@ -2,7 +2,7 @@ import { ToolArgs } from "./types"
 
 export function getExecuteCommandDescription(args: ToolArgs): string | undefined {
 	return `## execute_command
-Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: ${args.cwd}
+Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: ${args.cwd}
 Parameters:
 - command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
 Usage:

+ 222 - 0
src/utils/__tests__/shell.test.ts

@@ -0,0 +1,222 @@
+import * as vscode from "vscode"
+import { userInfo } from "os"
+import { getShell } from "../shell"
+
+describe("Shell Detection Tests", () => {
+	let originalPlatform: string
+	let originalEnv: NodeJS.ProcessEnv
+	let originalGetConfig: any
+	let originalUserInfo: any
+
+	// Helper to mock VS Code configuration
+	function mockVsCodeConfig(platformKey: string, defaultProfileName: string | null, profiles: Record<string, any>) {
+		vscode.workspace.getConfiguration = () =>
+			({
+				get: (key: string) => {
+					if (key === `defaultProfile.${platformKey}`) {
+						return defaultProfileName
+					}
+					if (key === `profiles.${platformKey}`) {
+						return profiles
+					}
+					return undefined
+				},
+			}) as any
+	}
+
+	beforeEach(() => {
+		// Store original references
+		originalPlatform = process.platform
+		originalEnv = { ...process.env }
+		originalGetConfig = vscode.workspace.getConfiguration
+		originalUserInfo = userInfo
+
+		// Clear environment variables for a clean test
+		delete process.env.SHELL
+		delete process.env.COMSPEC
+
+		// Default userInfo() mock
+		;(userInfo as any) = () => ({ shell: null })
+	})
+
+	afterEach(() => {
+		// Restore everything
+		Object.defineProperty(process, "platform", { value: originalPlatform })
+		process.env = originalEnv
+		vscode.workspace.getConfiguration = originalGetConfig
+		;(userInfo as any) = originalUserInfo
+	})
+
+	// --------------------------------------------------------------------------
+	// Windows Shell Detection
+	// --------------------------------------------------------------------------
+	describe("Windows Shell Detection", () => {
+		beforeEach(() => {
+			Object.defineProperty(process, "platform", { value: "win32" })
+		})
+
+		it("uses explicit PowerShell 7 path from VS Code config (profile path)", () => {
+			mockVsCodeConfig("windows", "PowerShell", {
+				PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" },
+			})
+			expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
+		})
+
+		it("uses PowerShell 7 path if source is 'PowerShell' but no explicit path", () => {
+			mockVsCodeConfig("windows", "PowerShell", {
+				PowerShell: { source: "PowerShell" },
+			})
+			expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
+		})
+
+		it("falls back to legacy PowerShell if profile includes 'powershell' but no path/source", () => {
+			mockVsCodeConfig("windows", "PowerShell", {
+				PowerShell: {},
+			})
+			expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")
+		})
+
+		it("uses WSL bash when profile indicates WSL source", () => {
+			mockVsCodeConfig("windows", "WSL", {
+				WSL: { source: "WSL" },
+			})
+			expect(getShell()).toBe("/bin/bash")
+		})
+
+		it("uses WSL bash when profile name includes 'wsl'", () => {
+			mockVsCodeConfig("windows", "Ubuntu WSL", {
+				"Ubuntu WSL": {},
+			})
+			expect(getShell()).toBe("/bin/bash")
+		})
+
+		it("defaults to cmd.exe if no special profile is matched", () => {
+			mockVsCodeConfig("windows", "CommandPrompt", {
+				CommandPrompt: {},
+			})
+			expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe")
+		})
+
+		it("respects userInfo() if no VS Code config is available", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			;(userInfo as any) = () => ({ shell: "C:\\Custom\\PowerShell.exe" })
+
+			expect(getShell()).toBe("C:\\Custom\\PowerShell.exe")
+		})
+
+		it("respects an odd COMSPEC if no userInfo shell is available", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			process.env.COMSPEC = "D:\\CustomCmd\\cmd.exe"
+
+			expect(getShell()).toBe("D:\\CustomCmd\\cmd.exe")
+		})
+	})
+
+	// --------------------------------------------------------------------------
+	// macOS Shell Detection
+	// --------------------------------------------------------------------------
+	describe("macOS Shell Detection", () => {
+		beforeEach(() => {
+			Object.defineProperty(process, "platform", { value: "darwin" })
+		})
+
+		it("uses VS Code profile path if available", () => {
+			mockVsCodeConfig("osx", "MyCustomShell", {
+				MyCustomShell: { path: "/usr/local/bin/fish" },
+			})
+			expect(getShell()).toBe("/usr/local/bin/fish")
+		})
+
+		it("falls back to userInfo().shell if no VS Code config is available", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			;(userInfo as any) = () => ({ shell: "/opt/homebrew/bin/zsh" })
+			expect(getShell()).toBe("/opt/homebrew/bin/zsh")
+		})
+
+		it("falls back to SHELL env var if no userInfo shell is found", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			process.env.SHELL = "/usr/local/bin/zsh"
+			expect(getShell()).toBe("/usr/local/bin/zsh")
+		})
+
+		it("falls back to /bin/zsh if no config, userInfo, or env variable is set", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			expect(getShell()).toBe("/bin/zsh")
+		})
+	})
+
+	// --------------------------------------------------------------------------
+	// Linux Shell Detection
+	// --------------------------------------------------------------------------
+	describe("Linux Shell Detection", () => {
+		beforeEach(() => {
+			Object.defineProperty(process, "platform", { value: "linux" })
+		})
+
+		it("uses VS Code profile path if available", () => {
+			mockVsCodeConfig("linux", "CustomProfile", {
+				CustomProfile: { path: "/usr/bin/fish" },
+			})
+			expect(getShell()).toBe("/usr/bin/fish")
+		})
+
+		it("falls back to userInfo().shell if no VS Code config is available", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			;(userInfo as any) = () => ({ shell: "/usr/bin/zsh" })
+			expect(getShell()).toBe("/usr/bin/zsh")
+		})
+
+		it("falls back to SHELL env var if no userInfo shell is found", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			process.env.SHELL = "/usr/bin/fish"
+			expect(getShell()).toBe("/usr/bin/fish")
+		})
+
+		it("falls back to /bin/bash if nothing is set", () => {
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			expect(getShell()).toBe("/bin/bash")
+		})
+	})
+
+	// --------------------------------------------------------------------------
+	// Unknown Platform & Error Handling
+	// --------------------------------------------------------------------------
+	describe("Unknown Platform / Error Handling", () => {
+		it("falls back to /bin/sh for unknown platforms", () => {
+			Object.defineProperty(process, "platform", { value: "sunos" })
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			expect(getShell()).toBe("/bin/sh")
+		})
+
+		it("handles VS Code config errors gracefully, falling back to userInfo shell if present", () => {
+			Object.defineProperty(process, "platform", { value: "linux" })
+			vscode.workspace.getConfiguration = () => {
+				throw new Error("Configuration error")
+			}
+			;(userInfo as any) = () => ({ shell: "/bin/bash" })
+			expect(getShell()).toBe("/bin/bash")
+		})
+
+		it("handles userInfo errors gracefully, falling back to environment variable if present", () => {
+			Object.defineProperty(process, "platform", { value: "darwin" })
+			vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
+			;(userInfo as any) = () => {
+				throw new Error("userInfo error")
+			}
+			process.env.SHELL = "/bin/zsh"
+			expect(getShell()).toBe("/bin/zsh")
+		})
+
+		it("falls back fully to default shell paths if everything fails", () => {
+			Object.defineProperty(process, "platform", { value: "linux" })
+			vscode.workspace.getConfiguration = () => {
+				throw new Error("Configuration error")
+			}
+			;(userInfo as any) = () => {
+				throw new Error("userInfo error")
+			}
+			delete process.env.SHELL
+			expect(getShell()).toBe("/bin/bash")
+		})
+	})
+})

+ 227 - 0
src/utils/shell.ts

@@ -0,0 +1,227 @@
+import * as vscode from "vscode"
+import { userInfo } from "os"
+
+const SHELL_PATHS = {
+	// Windows paths
+	POWERSHELL_7: "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
+	POWERSHELL_LEGACY: "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
+	CMD: "C:\\Windows\\System32\\cmd.exe",
+	WSL_BASH: "/bin/bash",
+	// Unix paths
+	MAC_DEFAULT: "/bin/zsh",
+	LINUX_DEFAULT: "/bin/bash",
+	CSH: "/bin/csh",
+	BASH: "/bin/bash",
+	KSH: "/bin/ksh",
+	SH: "/bin/sh",
+	ZSH: "/bin/zsh",
+	DASH: "/bin/dash",
+	TCSH: "/bin/tcsh",
+	FALLBACK: "/bin/sh",
+} as const
+
+interface MacTerminalProfile {
+	path?: string
+}
+
+type MacTerminalProfiles = Record<string, MacTerminalProfile>
+
+interface WindowsTerminalProfile {
+	path?: string
+	source?: "PowerShell" | "WSL"
+}
+
+type WindowsTerminalProfiles = Record<string, WindowsTerminalProfile>
+
+interface LinuxTerminalProfile {
+	path?: string
+}
+
+type LinuxTerminalProfiles = Record<string, LinuxTerminalProfile>
+
+// -----------------------------------------------------
+// 1) VS Code Terminal Configuration Helpers
+// -----------------------------------------------------
+
+function getWindowsTerminalConfig() {
+	try {
+		const config = vscode.workspace.getConfiguration("terminal.integrated")
+		const defaultProfileName = config.get<string>("defaultProfile.windows")
+		const profiles = config.get<WindowsTerminalProfiles>("profiles.windows") || {}
+		return { defaultProfileName, profiles }
+	} catch {
+		return { defaultProfileName: null, profiles: {} as WindowsTerminalProfiles }
+	}
+}
+
+function getMacTerminalConfig() {
+	try {
+		const config = vscode.workspace.getConfiguration("terminal.integrated")
+		const defaultProfileName = config.get<string>("defaultProfile.osx")
+		const profiles = config.get<MacTerminalProfiles>("profiles.osx") || {}
+		return { defaultProfileName, profiles }
+	} catch {
+		return { defaultProfileName: null, profiles: {} as MacTerminalProfiles }
+	}
+}
+
+function getLinuxTerminalConfig() {
+	try {
+		const config = vscode.workspace.getConfiguration("terminal.integrated")
+		const defaultProfileName = config.get<string>("defaultProfile.linux")
+		const profiles = config.get<LinuxTerminalProfiles>("profiles.linux") || {}
+		return { defaultProfileName, profiles }
+	} catch {
+		return { defaultProfileName: null, profiles: {} as LinuxTerminalProfiles }
+	}
+}
+
+// -----------------------------------------------------
+// 2) Platform-Specific VS Code Shell Retrieval
+// -----------------------------------------------------
+
+/** Attempts to retrieve a shell path from VS Code config on Windows. */
+function getWindowsShellFromVSCode(): string | null {
+	const { defaultProfileName, profiles } = getWindowsTerminalConfig()
+	if (!defaultProfileName) {
+		return null
+	}
+
+	const profile = profiles[defaultProfileName]
+
+	// If the profile name indicates PowerShell, do version-based detection.
+	// In testing it was found these typically do not have a path, and this
+	// implementation manages to deductively get the corect version of PowerShell
+	if (defaultProfileName.toLowerCase().includes("powershell")) {
+		if (profile?.path) {
+			// If there's an explicit PowerShell path, return that
+			return profile.path
+		} else if (profile?.source === "PowerShell") {
+			// If the profile is sourced from PowerShell, assume the newest
+			return SHELL_PATHS.POWERSHELL_7
+		}
+		// Otherwise, assume legacy Windows PowerShell
+		return SHELL_PATHS.POWERSHELL_LEGACY
+	}
+
+	// If there's a specific path, return that immediately
+	if (profile.path) {
+		return profile.path
+	}
+
+	// If the profile indicates WSL
+	if (profile?.source === "WSL" || defaultProfileName.toLowerCase().includes("wsl")) {
+		return SHELL_PATHS.WSL_BASH
+	}
+
+	// If nothing special detected, we assume cmd
+	return SHELL_PATHS.CMD
+}
+
+/** Attempts to retrieve a shell path from VS Code config on macOS. */
+function getMacShellFromVSCode(): string | null {
+	const { defaultProfileName, profiles } = getMacTerminalConfig()
+	if (!defaultProfileName) {
+		return null
+	}
+
+	const profile = profiles[defaultProfileName]
+	return profile?.path || null
+}
+
+/** Attempts to retrieve a shell path from VS Code config on Linux. */
+function getLinuxShellFromVSCode(): string | null {
+	const { defaultProfileName, profiles } = getLinuxTerminalConfig()
+	if (!defaultProfileName) {
+		return null
+	}
+
+	const profile = profiles[defaultProfileName]
+	return profile?.path || null
+}
+
+// -----------------------------------------------------
+// 3) General Fallback Helpers
+// -----------------------------------------------------
+
+/**
+ * Tries to get a user’s shell from os.userInfo() (works on Unix if the
+ * underlying system call is supported). Returns null on error or if not found.
+ */
+function getShellFromUserInfo(): string | null {
+	try {
+		const { shell } = userInfo()
+		return shell || null
+	} catch {
+		return null
+	}
+}
+
+/** Returns the environment-based shell variable, or null if not set. */
+function getShellFromEnv(): string | null {
+	const { env } = process
+
+	if (process.platform === "win32") {
+		// On Windows, COMSPEC typically holds cmd.exe
+		return env.COMSPEC || "C:\\Windows\\System32\\cmd.exe"
+	}
+
+	if (process.platform === "darwin") {
+		// On macOS/Linux, SHELL is commonly the environment variable
+		return env.SHELL || "/bin/zsh"
+	}
+
+	if (process.platform === "linux") {
+		// On Linux, SHELL is commonly the environment variable
+		return env.SHELL || "/bin/bash"
+	}
+	return null
+}
+
+// -----------------------------------------------------
+// 4) Publicly Exposed Shell Getter
+// -----------------------------------------------------
+
+export function getShell(): string {
+	// 1. Check VS Code config first.
+	if (process.platform === "win32") {
+		// Special logic for Windows
+		const windowsShell = getWindowsShellFromVSCode()
+		if (windowsShell) {
+			return windowsShell
+		}
+	} else if (process.platform === "darwin") {
+		// macOS from VS Code
+		const macShell = getMacShellFromVSCode()
+		if (macShell) {
+			return macShell
+		}
+	} else if (process.platform === "linux") {
+		// Linux from VS Code
+		const linuxShell = getLinuxShellFromVSCode()
+		if (linuxShell) {
+			return linuxShell
+		}
+	}
+
+	// 2. If no shell from VS Code, try userInfo()
+	const userInfoShell = getShellFromUserInfo()
+	if (userInfoShell) {
+		return userInfoShell
+	}
+
+	// 3. If still nothing, try environment variable
+	const envShell = getShellFromEnv()
+	if (envShell) {
+		return envShell
+	}
+
+	// 4. Finally, fall back to a default
+	if (process.platform === "win32") {
+		// On Windows, if we got here, we have no config, no COMSPEC, and one very messed up operating system.
+		// Use CMD as a last resort
+		return SHELL_PATHS.CMD
+	}
+	// On macOS/Linux, fallback to a POSIX shell - This is the behavior of our old shell detection method.
+	return SHELL_PATHS.FALLBACK
+}

+ 12 - 3
webview-ui/tsconfig.json

@@ -1,7 +1,11 @@
 {
 	"compilerOptions": {
 		"target": "es5",
-		"lib": ["dom", "dom.iterable", "esnext"],
+		"lib": [
+			"dom",
+			"dom.iterable",
+			"esnext"
+		],
 		"allowJs": true,
 		"skipLibCheck": true,
 		"esModuleInterop": true,
@@ -17,8 +21,13 @@
 		"jsx": "react-jsx",
 		"baseUrl": ".",
 		"paths": {
-			"@/*": ["./src/*"]
+			"@/*": [
+				"./src/*"
+			]
 		}
 	},
-	"include": ["src", "../src/shared"]
+	"include": [
+		"src",
+		"../src/shared",
+	]
 }