mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
227 lines
6.6 KiB
TypeScript
227 lines
6.6 KiB
TypeScript
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
|
||
}
|