summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-04-10 23:26:16 -0400
committerGitHub <[email protected]>2026-04-10 23:26:16 -0400
commit03ce2e5288c8d2ef58e1197f6200b6be8f2797d7 (patch)
treebe6941d5cae5d782ebd88f4ef8ab21553797dbee
parent87e23abb10625bae4194406545e41beebb1b5a06 (diff)
downloadopencode-03ce2e5288c8d2ef58e1197f6200b6be8f2797d7.tar.gz
opencode-03ce2e5288c8d2ef58e1197f6200b6be8f2797d7.zip
refactor(installation): drop facade runtime wrappers (#21984)
-rw-r--r--packages/opencode/src/cli/cmd/uninstall.ts3
-rw-r--r--packages/opencode/src/cli/cmd/upgrade.ts11
-rw-r--r--packages/opencode/src/cli/upgrade.ts7
-rw-r--r--packages/opencode/src/installation/index.ts15
-rw-r--r--packages/opencode/src/server/routes/global.ts54
5 files changed, 50 insertions, 40 deletions
diff --git a/packages/opencode/src/cli/cmd/uninstall.ts b/packages/opencode/src/cli/cmd/uninstall.ts
index de41f32a0..31830f085 100644
--- a/packages/opencode/src/cli/cmd/uninstall.ts
+++ b/packages/opencode/src/cli/cmd/uninstall.ts
@@ -1,6 +1,7 @@
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 { Global } from "../../global"
import fs from "fs/promises"
@@ -57,7 +58,7 @@ export const UninstallCommand = {
UI.empty()
prompts.intro("Uninstall OpenCode")
- const method = await Installation.method()
+ const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
prompts.log.info(`Installation method: ${method}`)
const targets = await collectRemovalTargets(args, method)
diff --git a/packages/opencode/src/cli/cmd/upgrade.ts b/packages/opencode/src/cli/cmd/upgrade.ts
index 018205663..3ffa0f228 100644
--- a/packages/opencode/src/cli/cmd/upgrade.ts
+++ b/packages/opencode/src/cli/cmd/upgrade.ts
@@ -1,6 +1,7 @@
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"
export const UpgradeCommand = {
@@ -24,7 +25,7 @@ export const UpgradeCommand = {
UI.println(UI.logo(" "))
UI.empty()
prompts.intro("Upgrade")
- const detectedMethod = await Installation.method()
+ 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`)
@@ -42,7 +43,9 @@ export const UpgradeCommand = {
}
}
prompts.log.info("Using method: " + method)
- const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest()
+ const target = args.target
+ ? args.target.replace(/^v/, "")
+ : await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest()))
if (Installation.VERSION === target) {
prompts.log.warn(`opencode upgrade skipped: ${target} is already installed`)
@@ -53,7 +56,9 @@ export const UpgradeCommand = {
prompts.log.info(`From ${Installation.VERSION} → ${target}`)
const spinner = prompts.spinner()
spinner.start("Upgrading...")
- const err = await Installation.upgrade(method, target).catch((err) => err)
+ 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) {
diff --git a/packages/opencode/src/cli/upgrade.ts b/packages/opencode/src/cli/upgrade.ts
index 7b7199d4e..e902dcb92 100644
--- a/packages/opencode/src/cli/upgrade.ts
+++ b/packages/opencode/src/cli/upgrade.ts
@@ -1,12 +1,13 @@
import { Bus } from "@/bus"
import { Config } from "@/config/config"
+import { AppRuntime } from "@/effect/app-runtime"
import { Flag } from "@/flag/flag"
import { Installation } from "@/installation"
export async function upgrade() {
const config = await Config.getGlobal()
- const method = await Installation.method()
- const latest = await Installation.latest(method).catch(() => {})
+ const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
+ const latest = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest(method))).catch(() => {})
if (!latest) return
if (Flag.OPENCODE_ALWAYS_NOTIFY_UPDATE) {
@@ -25,7 +26,7 @@ export async function upgrade() {
}
if (method === "unknown") return
- await Installation.upgrade(method, latest)
+ await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, latest)))
.then(() => Bus.publish(Installation.Event.Updated, { version: latest }))
.catch(() => {})
}
diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts
index 06b673217..29f9bf1be 100644
--- a/packages/opencode/src/installation/index.ts
+++ b/packages/opencode/src/installation/index.ts
@@ -1,7 +1,6 @@
import { Effect, Layer, Schema, Context, Stream } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
-import { makeRuntime } from "@/effect/run-service"
import { withTransientReadRetry } from "@/util/effect-http-client"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import path from "path"
@@ -338,18 +337,4 @@ export namespace Installation {
Layer.provide(FetchHttpClient.layer),
Layer.provide(CrossSpawnSpawner.defaultLayer),
)
-
- const { runPromise } = makeRuntime(Service, defaultLayer)
-
- export async function method(): Promise<Method> {
- return runPromise((svc) => svc.method())
- }
-
- export async function latest(installMethod?: Method): Promise<string> {
- return runPromise((svc) => svc.latest(installMethod))
- }
-
- export async function upgrade(m: Method, target: string): Promise<void> {
- return runPromise((svc) => svc.upgrade(m, target))
- }
}
diff --git a/packages/opencode/src/server/routes/global.ts b/packages/opencode/src/server/routes/global.ts
index ec7afcf23..6b0a9a164 100644
--- a/packages/opencode/src/server/routes/global.ts
+++ b/packages/opencode/src/server/routes/global.ts
@@ -1,10 +1,12 @@
import { Hono, type Context } from "hono"
import { describeRoute, resolver, validator } from "hono-openapi"
import { streamSSE } from "hono/streaming"
+import { Effect } from "effect"
import z from "zod"
import { BusEvent } from "@/bus/bus-event"
import { SyncEvent } from "@/sync"
import { GlobalBus } from "@/bus/global"
+import { AppRuntime } from "@/effect/app-runtime"
import { AsyncQueue } from "@/util/queue"
import { Instance } from "../../project/instance"
import { Installation } from "@/installation"
@@ -290,25 +292,41 @@ export const GlobalRoutes = lazy(() =>
}),
),
async (c) => {
- const method = await Installation.method()
- if (method === "unknown") {
- return c.json({ success: false, error: "Unknown installation method" }, 400)
- }
- const target = c.req.valid("json").target || (await Installation.latest(method))
- const result = await Installation.upgrade(method, target)
- .then(() => ({ success: true as const, version: target }))
- .catch((e) => ({ success: false as const, error: e instanceof Error ? e.message : String(e) }))
- if (result.success) {
- GlobalBus.emit("event", {
- directory: "global",
- payload: {
- type: Installation.Event.Updated.type,
- properties: { version: target },
- },
- })
- return c.json(result)
+ const result = await AppRuntime.runPromise(
+ Installation.Service.use((svc) =>
+ Effect.gen(function* () {
+ const method = yield* svc.method()
+ if (method === "unknown") {
+ return { success: false as const, status: 400 as const, error: "Unknown installation method" }
+ }
+
+ const target = c.req.valid("json").target || (yield* svc.latest(method))
+ const result = yield* Effect.catch(
+ svc.upgrade(method, target).pipe(Effect.as({ success: true as const, version: target })),
+ (err) =>
+ Effect.succeed({
+ success: false as const,
+ status: 500 as const,
+ error: err instanceof Error ? err.message : String(err),
+ }),
+ )
+ if (!result.success) return result
+ return { ...result, status: 200 as const }
+ }),
+ ),
+ )
+ if (!result.success) {
+ return c.json({ success: false, error: result.error }, result.status)
}
- return c.json(result, 500)
+ const target = result.version
+ GlobalBus.emit("event", {
+ directory: "global",
+ payload: {
+ type: Installation.Event.Updated.type,
+ properties: { version: target },
+ },
+ })
+ return c.json({ success: true, version: target })
},
),
)