diff --git a/packages/desktop/scripts/dev.ts b/packages/desktop/scripts/dev.ts index b4173ca9804..beca28dfb64 100644 --- a/packages/desktop/scripts/dev.ts +++ b/packages/desktop/scripts/dev.ts @@ -1,7 +1,6 @@ import { $ } from "bun" -import { homedir } from "node:os" import { join } from "node:path" -import { buildCliToResources, downloadCliToResources, windowsify } from "./utils" +import { downloadCliToResources, windowsify } from "./utils" type ServerSource = { type: "build" } | { type: "download"; version: string } type DevOptions = { server: ServerSource; electron: string[] } @@ -38,18 +37,9 @@ function selectOptions(): DevOptions { } async function prepareServer(source: ServerSource) { - const destination = windowsify("resources/opencode-cli-dev") - if (source.type === "download") return downloadCliToResources(source.version, destination) - return buildCliToResources(destination, developmentStateHome()) -} - -function developmentStateHome() { - const appData = (() => { - if (process.platform === "darwin") return join(homedir(), "Library", "Application Support") - if (process.platform === "win32") return process.env.APPDATA ?? join(homedir(), "AppData", "Roaming") - return process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config") - })() - return join(appData, "ai.opencode.desktop.dev") + if (source.type === "download") + return downloadCliToResources(source.version, windowsify("resources/opencode-cli-dev")) + process.env.OPENCODE_DESKTOP_CLI_DEV = join(import.meta.dirname, "../../cli") } async function startDesktop(args: string[]) { diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts index 34a215327c9..a5f85e11f5f 100644 --- a/packages/desktop/scripts/utils.ts +++ b/packages/desktop/scripts/utils.ts @@ -86,34 +86,6 @@ export async function downloadCliToResources(version = CLI_VERSION, dest = windo console.log(`Copied ${cli.package}@${version} to ${dest}`) } -export async function buildCliToResources(dest = windowsify("resources/opencode-cli"), stateHome?: string) { - const directory = await mkdtemp(join(tmpdir(), "opencode-cli-")) - const target = `cli-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}` - try { - await $`bun ${join(import.meta.dirname, "../../cli/script/build.ts")} --single --skip-install --skip-web-ui --outdir=${directory}`.env( - { - ...process.env, - OPENCODE_VERSION: process.env.OPENCODE_VERSION, - }, - ) - if (stateHome && (await Bun.file(dest).exists())) { - const child = Bun.spawn([dest, "service", "stop"], { - env: { ...process.env, XDG_STATE_HOME: stateHome }, - stdout: "inherit", - stderr: "inherit", - }) - const exitCode = await child.exited - if (exitCode !== 0) throw new Error(`Failed to stop development service: ${exitCode}`) - } - await copyFile(join(directory, target, "bin", windowsify("opencode2")), dest) - } finally { - await rm(directory, { recursive: true, force: true }) - } - await prepareCli(dest) - - console.log(`Built local CLI at ${dest}`) -} - async function prepareCli(dest: string) { if (process.platform !== "win32") await chmod(dest, 0o755) if (process.platform === "win32" && process.env.GITHUB_ACTIONS === "true") { diff --git a/packages/desktop/src/main/background-cli.ts b/packages/desktop/src/main/background-cli.ts index 9e739bf15cf..65ff6f6a5b4 100644 --- a/packages/desktop/src/main/background-cli.ts +++ b/packages/desktop/src/main/background-cli.ts @@ -17,29 +17,31 @@ type Logger = { export async function startBackgroundCli(logger: Logger) { const isolated = !app.isPackaged && process.env.OPENCODE_DESKTOP_ISOLATED_SERVER === "1" - const bundled = app.isPackaged - ? join(process.resourcesPath, executableName()) - : join(root, "../../resources", isolated ? developmentExecutableName() : executableName()) - logger.log("v2 CLI executable resolved", { bundled, packaged: app.isPackaged }) - const version = parseVersion(await run(bundled, ["--version"], logger)) - const binary = app.isPackaged || isolated ? await installCli(bundled, version, logger) : bundled + const development = !app.isPackaged && process.env.OPENCODE_DESKTOP_CLI_DEV + const cli = development + ? { + version: "local", + command: ["bun", "run", "--cwd", development, "dev", "--"], + binary: undefined, + } + : await resolveBundledCli(isolated, logger) if (isolated) process.env.XDG_STATE_HOME = app.getPath("userData") const service = await Service.ensure({ file: isolated && process.env.OPENCODE_DESKTOP_SERVER_CHANNEL === "local" ? join(app.getPath("userData"), "opencode", "service-local.json") : undefined, - version, - command: [binary, "serve", "--service"], + version: cli.version, + command: [...cli.command, "serve", "--service"], onStart: (reason, previousVersion) => logger.log("v2 CLI background service starting", { reason, previousVersion }), }) if (service.auth?.type !== "basic") throw new Error("V2 CLI background service did not provide authentication") logger.log("v2 CLI background service ready", { username: service.auth.username, - version, + version: cli.version, ...endpoint(service.url), }) - if (isolated) await cleanCliStages(binary, logger) + if (isolated && cli.binary) await cleanCliStages(cli.binary, logger) return { url: service.url, username: service.auth.username, @@ -47,6 +49,16 @@ export async function startBackgroundCli(logger: Logger) { } } +async function resolveBundledCli(isolated: boolean, logger: Logger) { + const bundled = app.isPackaged + ? join(process.resourcesPath, executableName()) + : join(root, "../../resources", isolated ? developmentExecutableName() : executableName()) + logger.log("v2 CLI executable resolved", { bundled, packaged: app.isPackaged }) + const version = parseVersion(await run(bundled, ["--version"], logger)) + const binary = app.isPackaged || isolated ? await installCli(bundled, version, logger) : bundled + return { version, binary, command: [binary] } +} + async function cleanCliStages(binary: string, logger: Logger) { const current = dirname(binary) const root = dirname(current)