Skip to content

Commit e3cf648

Browse files
Add OpenCode install method detection and improve process termination handling
1 parent bdd0408 commit e3cf648

2 files changed

Lines changed: 41 additions & 6 deletions

File tree

backend/src/routes/settings.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Hono } from 'hono'
22
import { z } from 'zod'
33
import { execSync } from 'child_process'
4+
import { existsSync } from 'fs'
5+
import { resolve, dirname } from 'path'
46
import type { Database } from 'bun:sqlite'
57
import { SettingsService } from '../services/settings'
68
import { writeFileContent, readFileContent, fileExists } from '../services/file-operations'
@@ -27,6 +29,27 @@ function compareVersions(v1: string, v2: string): number {
2729
return 0
2830
}
2931

32+
function getOpenCodeInstallMethod(): string {
33+
const homePath = process.env.HOME || ''
34+
const opencodePath = process.env.OPENCOD_PATH || resolve(homePath, '.opencode', 'bin', 'opencode')
35+
36+
if (!existsSync(opencodePath)) return 'curl'
37+
38+
try {
39+
const opencodeDir = dirname(opencodePath)
40+
if (opencodeDir.includes('.opencode')) return 'curl'
41+
42+
if (opencodePath.includes('/homebrew/') || opencodePath.includes('/HOMEBREW/')) return 'brew'
43+
if (opencodePath.includes('/.npm/') || opencodePath.includes('/node_modules/')) return 'npm'
44+
if (opencodePath.includes('/.pnpm/')) return 'pnpm'
45+
if (opencodePath.includes('/.bun/')) return 'bun'
46+
} catch {
47+
return 'curl'
48+
}
49+
50+
return 'curl'
51+
}
52+
3053
function execWithTimeout(command: string, timeoutMs: number): { output: string; timedOut: boolean } {
3154
try {
3255
const output = execSync(command, {
@@ -396,8 +419,9 @@ export function createSettingsRoutes(db: Database) {
396419
logger.info(`Current OpenCode version: ${oldVersion}`)
397420

398421
try {
399-
logger.info('Running opencode upgrade with 90s timeout...')
400-
const { output: upgradeOutput, timedOut } = execWithTimeout('opencode upgrade 2>&1', 90000)
422+
const installMethod = getOpenCodeInstallMethod()
423+
logger.info(`Running opencode upgrade --method ${installMethod} with 90s timeout...`)
424+
const { output: upgradeOutput, timedOut } = execWithTimeout(`opencode upgrade --method ${installMethod} 2>&1`, 90000)
401425
logger.info(`Upgrade output: ${upgradeOutput}`)
402426

403427
if (timedOut) {
@@ -546,9 +570,10 @@ export function createSettingsRoutes(db: Database) {
546570

547571
logger.info(`Installing OpenCode version: ${version}`)
548572
const versionArg = version.startsWith('v') ? version : `v${version}`
549-
logger.info(`Running opencode upgrade ${versionArg} with 90s timeout...`)
573+
const installMethod = getOpenCodeInstallMethod()
574+
logger.info(`Running opencode upgrade ${versionArg} --method ${installMethod} with 90s timeout...`)
550575

551-
const { output: upgradeOutput, timedOut } = execWithTimeout(`opencode upgrade ${versionArg} 2>&1`, 90000)
576+
const { output: upgradeOutput, timedOut } = execWithTimeout(`opencode upgrade ${versionArg} --method ${installMethod} 2>&1`, 90000)
552577
logger.info(`Upgrade output: ${upgradeOutput}`)
553578

554579
if (timedOut) {

backend/src/services/opencode-single-server.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,25 @@ class OpenCodeServerManager {
185185
try {
186186
process.kill(this.serverPid, 'SIGTERM')
187187
} catch (error) {
188-
logger.warn(`Failed to send SIGTERM to ${this.serverPid}:`, error)
188+
const errorCode = error && typeof error === 'object' && 'code' in error ? (error as { code: string }).code : ''
189+
if (errorCode === 'ESRCH') {
190+
logger.debug(`Process ${this.serverPid} already stopped`)
191+
} else {
192+
logger.warn(`Failed to send SIGTERM to ${this.serverPid}:`, error)
193+
}
189194
}
190195

191196
await new Promise(r => setTimeout(r, 2000))
192197

193198
try {
194199
process.kill(this.serverPid, 'SIGKILL')
195200
} catch (error) {
196-
logger.warn(`Failed to send SIGKILL to ${this.serverPid}:`, error)
201+
const errorCode = error && typeof error === 'object' && 'code' in error ? (error as { code: string }).code : ''
202+
if (errorCode === 'ESRCH') {
203+
logger.debug(`Process ${this.serverPid} already stopped`)
204+
} else {
205+
logger.warn(`Failed to send SIGKILL to ${this.serverPid}:`, error)
206+
}
197207
}
198208

199209
this.serverPid = null

0 commit comments

Comments
 (0)