Files
neuron/packages/opencode/src/cli/cmd/upgrade.ts
T
Dax Raad 1a734adb4d core: consolidate shared infrastructure into core package
Moves effect logging, observability, runtime utilities, flags, installation
version info, and process utilities from opencode to core package. This
enables better code sharing across packages and establishes core as the
single source of truth for foundational utilities.

All internal imports updated to use @opencode-ai/core paths for consistency.
2026-04-25 13:30:37 -04:00

80 lines
2.8 KiB
TypeScript

import type { Argv } from "yargs"
import { UI } from "../ui"
import * as prompts from "@clack/prompts"
import { AppRuntime } from "@/effect/app-runtime"
import { Installation } from "../../installation"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
export const UpgradeCommand = {
command: "upgrade [target]",
describe: "upgrade opencode to the latest or a specific version",
builder: (yargs: Argv) => {
return yargs
.positional("target", {
describe: "version to upgrade to, for ex '0.1.48' or 'v0.1.48'",
type: "string",
})
.option("method", {
alias: "m",
describe: "installation method to use",
type: "string",
choices: ["curl", "npm", "pnpm", "bun", "brew", "choco", "scoop"],
})
},
handler: async (args: { target?: string; method?: string }) => {
UI.empty()
UI.println(UI.logo(" "))
UI.empty()
prompts.intro("Upgrade")
const detectedMethod = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
const method = (args.method as Installation.Method) ?? detectedMethod
if (method === "unknown") {
prompts.log.error(`opencode is installed to ${process.execPath} and may be managed by a package manager`)
const install = await prompts.select({
message: "Install anyways?",
options: [
{ label: "Yes", value: true },
{ label: "No", value: false },
],
initialValue: false,
})
if (!install) {
prompts.outro("Done")
return
}
}
prompts.log.info("Using method: " + method)
const target = args.target
? args.target.replace(/^v/, "")
: await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest()))
if (InstallationVersion === target) {
prompts.log.warn(`opencode upgrade skipped: ${target} is already installed`)
prompts.outro("Done")
return
}
prompts.log.info(`From ${InstallationVersion}${target}`)
const spinner = prompts.spinner()
spinner.start("Upgrading...")
const err = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, target))).catch(
(err) => err,
)
if (err) {
spinner.stop("Upgrade failed", 1)
if (err instanceof Installation.UpgradeFailedError) {
// necessary because choco only allows install/upgrade in elevated terminals
if (method === "choco" && err.stderr.includes("not running from an elevated command shell")) {
prompts.log.error("Please run the terminal as Administrator and try again")
} else {
prompts.log.error(err.stderr)
}
} else if (err instanceof Error) prompts.log.error(err.message)
prompts.outro("Done")
return
}
spinner.stop("Upgrade complete")
prompts.outro("Done")
},
}