Skip to content
35 changes: 28 additions & 7 deletions packages/opencode/src/altimate/bridge/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import type { BridgeMethod, BridgeMethods } from "./protocol"
import { Telemetry } from "../telemetry"
import { Log } from "../../util/log"

/** Platform-aware path to the python binary inside a venv directory. */
function venvPythonBin(venvDir: string): string {
return process.platform === "win32"
? path.join(venvDir, "Scripts", "python.exe")
: path.join(venvDir, "bin", "python")
}

/** Resolve the Python interpreter to use for the engine sidecar.
* Exported for testing — not part of the public API. */
export function resolvePython(): string {
Expand All @@ -22,17 +29,20 @@ export function resolvePython(): string {

// 2. Check for .venv relative to altimate-engine package (local dev)
const engineDir = path.resolve(__dirname, "..", "..", "..", "altimate-engine")
const venvPython = path.join(engineDir, ".venv", "bin", "python")
const venvPython = venvPythonBin(path.join(engineDir, ".venv"))
if (existsSync(venvPython)) return venvPython

// 3. Check for .venv in cwd
const cwdVenv = path.join(process.cwd(), ".venv", "bin", "python")
if (existsSync(cwdVenv)) return cwdVenv

// 4. Check the managed engine venv (created by ensureEngine)
// 3. Check the managed engine venv (created by ensureEngine)
// This must come before the CWD venv check — ensureEngine() installs
// altimate-engine here, so an unrelated .venv in the user's project
// directory must not shadow it.
const managedPython = enginePythonPath()
if (existsSync(managedPython)) return managedPython

// 4. Check for .venv in cwd
const cwdVenv = venvPythonBin(path.join(process.cwd(), ".venv"))
if (existsSync(cwdVenv)) return cwdVenv

// 5. Fallback
return "python3"
}
Expand All @@ -45,6 +55,8 @@ export namespace Bridge {
const CALL_TIMEOUT_MS = 30_000
const pending = new Map<number, { resolve: (value: any) => void; reject: (reason: any) => void }>()
let buffer = ""
// Mutex to prevent concurrent start() calls from spawning duplicate processes
let pendingStart: Promise<void> | null = null

export async function call<M extends BridgeMethod>(
method: M,
Expand All @@ -53,7 +65,16 @@ export namespace Bridge {
const startTime = Date.now()
if (!child || child.exitCode !== null) {
if (restartCount >= MAX_RESTARTS) throw new Error("Python bridge failed after max restarts")
await start()
if (pendingStart) {
await pendingStart
} else {
pendingStart = start()
try {
await pendingStart
} finally {
pendingStart = null
}
}
}
const id = ++requestId
const request = JSON.stringify({ jsonrpc: "2.0", method, params, id })
Expand Down
18 changes: 16 additions & 2 deletions packages/opencode/src/altimate/bridge/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ declare const OPENCODE_VERSION: string
// Mutex to prevent concurrent ensureEngine/ensureUv calls from corrupting state
let pendingEnsure: Promise<void> | null = null

/** The pip install spec used by ensureEngine — exported for tests. */
export const ENGINE_INSTALL_SPEC = "warehouses"

interface Manifest {
engine_version: string
python_version: string
uv_version: string
cli_version: string
installed_at: string
/** Comma-separated extras that were installed (e.g. "warehouses") */
extras?: string
}

/** Returns path to the engine directory */
Expand Down Expand Up @@ -158,7 +163,12 @@ export async function ensureEngine(): Promise<void> {
async function ensureEngineImpl(): Promise<void> {
const manifest = await readManifest()
const isUpgrade = manifest !== null
if (manifest && manifest.engine_version === ALTIMATE_ENGINE_VERSION) return

// Validate both version AND filesystem state — a matching version in the
// manifest is not enough if the venv or Python binary was deleted.
const pythonExists = existsSync(enginePythonPath())
const extrasMatch = (manifest?.extras ?? "") === ENGINE_INSTALL_SPEC
if (manifest && manifest.engine_version === ALTIMATE_ENGINE_VERSION && pythonExists && extrasMatch) return

const startTime = Date.now()

Expand Down Expand Up @@ -189,7 +199,10 @@ async function ensureEngineImpl(): Promise<void> {
const pythonPath = enginePythonPath()
Log.Default.info("installing altimate-engine", { version: ALTIMATE_ENGINE_VERSION })
try {
execFileSync(uv, ["pip", "install", "--python", pythonPath, `altimate-engine==${ALTIMATE_ENGINE_VERSION}`], { stdio: "pipe" })
const spec = ENGINE_INSTALL_SPEC
? `altimate-engine[${ENGINE_INSTALL_SPEC}]==${ALTIMATE_ENGINE_VERSION}`
: `altimate-engine==${ALTIMATE_ENGINE_VERSION}`
execFileSync(uv, ["pip", "install", "--python", pythonPath, spec], { stdio: "pipe" })
} catch (e: any) {
Telemetry.track({
type: "engine_error",
Expand All @@ -212,6 +225,7 @@ async function ensureEngineImpl(): Promise<void> {
uv_version: uvVersion,
cli_version: typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "local",
installed_at: new Date().toISOString(),
extras: ENGINE_INSTALL_SPEC,
})

Telemetry.track({
Expand Down
Loading
Loading