mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-15 07:48:24 -04:00
refactor(desktop): run local server from source (#42194)
This commit is contained in:
@@ -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[]) {
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user