Add OpenCode binary selection with version detection
- Add binary selector component with dropdown and validation - Support custom OpenCode binary paths and system PATH binary - Async version checking for all binaries when selector opens - Store recent binaries with timestamps and version info - Enhanced instance creation to use selected binary - Improved storage system for binary preferences - Fixed validation to handle system PATH binaries properly
This commit is contained in:
@@ -50,14 +50,14 @@ class ProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
async spawn(folder: string, instanceId: string): Promise<ProcessInfo> {
|
||||
async spawn(folder: string, instanceId: string, binaryPath?: string): Promise<ProcessInfo> {
|
||||
this.validateFolder(folder)
|
||||
const binaryPath = this.validateOpenCodeBinary()
|
||||
const actualBinaryPath = binaryPath ? this.validateCustomBinary(binaryPath) : this.validateOpenCodeBinary()
|
||||
|
||||
this.sendLog(instanceId, "info", `Starting OpenCode server for ${folder}...`)
|
||||
this.sendLog(instanceId, "info", `Starting OpenCode server for ${folder} using ${actualBinaryPath}...`)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn("opencode", ["serve", "--port", "0", "--print-logs", "--log-level", "DEBUG"], {
|
||||
const child = spawn(actualBinaryPath, ["serve", "--port", "0", "--print-logs", "--log-level", "DEBUG"], {
|
||||
cwd: folder,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
env: process.env,
|
||||
@@ -103,7 +103,7 @@ class ProcessManager {
|
||||
}
|
||||
|
||||
this.processes.set(child.pid!, meta)
|
||||
resolve({ pid: child.pid!, port, binaryPath })
|
||||
resolve({ pid: child.pid!, port, binaryPath: actualBinaryPath })
|
||||
}
|
||||
|
||||
const meta = this.processes.get(child.pid!)
|
||||
@@ -221,6 +221,28 @@ class ProcessManager {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private validateCustomBinary(binaryPath: string): string {
|
||||
if (!existsSync(binaryPath)) {
|
||||
throw new Error(`OpenCode binary not found: ${binaryPath}`)
|
||||
}
|
||||
|
||||
const stats = statSync(binaryPath)
|
||||
if (!stats.isFile()) {
|
||||
throw new Error(`Path is not a file: ${binaryPath}`)
|
||||
}
|
||||
|
||||
// Check if executable (on Unix systems)
|
||||
if (process.platform !== "win32") {
|
||||
try {
|
||||
execSync(`test -x "${binaryPath}"`, { stdio: "pipe" })
|
||||
} catch {
|
||||
throw new Error(`Binary is not executable: ${binaryPath}`)
|
||||
}
|
||||
}
|
||||
|
||||
return binaryPath
|
||||
}
|
||||
}
|
||||
|
||||
export const processManager = new ProcessManager()
|
||||
|
||||
Reference in New Issue
Block a user