- Split 25+ index.ts files into hook.ts + extracted modules - Rename all catch-all utils.ts/helpers.ts to domain-specific names - Split src/tools/lsp/ into ~15 focused modules - Split src/tools/delegate-task/ into ~18 focused modules - Separate shared types from implementation - 155 files changed, 60+ new files created - All typecheck clean, 61 tests pass
70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
import { existsSync } from "fs"
|
|
import { join } from "path"
|
|
|
|
import { getOpenCodeConfigDir, getDataDir } from "../../shared"
|
|
|
|
export function isServerInstalled(command: string[]): boolean {
|
|
if (command.length === 0) return false
|
|
|
|
const cmd = command[0]
|
|
|
|
// Support absolute paths (e.g., C:\Users\...\server.exe or /usr/local/bin/server)
|
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
if (existsSync(cmd)) return true
|
|
}
|
|
|
|
const isWindows = process.platform === "win32"
|
|
|
|
let exts = [""]
|
|
if (isWindows) {
|
|
const pathExt = process.env.PATHEXT || ""
|
|
if (pathExt) {
|
|
const systemExts = pathExt.split(";").filter(Boolean)
|
|
exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])]
|
|
} else {
|
|
exts = ["", ".exe", ".cmd", ".bat", ".ps1"]
|
|
}
|
|
}
|
|
|
|
let pathEnv = process.env.PATH || ""
|
|
if (isWindows && !pathEnv) {
|
|
pathEnv = process.env.Path || ""
|
|
}
|
|
|
|
const pathSeparator = isWindows ? ";" : ":"
|
|
const paths = pathEnv.split(pathSeparator)
|
|
|
|
for (const p of paths) {
|
|
for (const suffix of exts) {
|
|
if (existsSync(join(p, cmd + suffix))) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
const cwd = process.cwd()
|
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" })
|
|
const dataDir = join(getDataDir(), "opencode")
|
|
const additionalBases = [
|
|
join(cwd, "node_modules", ".bin"),
|
|
join(configDir, "bin"),
|
|
join(configDir, "node_modules", ".bin"),
|
|
join(dataDir, "bin"),
|
|
]
|
|
|
|
for (const base of additionalBases) {
|
|
for (const suffix of exts) {
|
|
if (existsSync(join(base, cmd + suffix))) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Runtime wrappers (bun/node) are always available in oh-my-opencode context
|
|
if (cmd === "bun" || cmd === "node") {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|