From 69b4a2604f5d3b00387d079aebea470a3a2fb39c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Thu, 9 Apr 2026 14:13:55 -0400 Subject: [PATCH] sync --- packages/opencode/src/agent/agent.ts | 12 ++++----- packages/opencode/src/cli/cmd/run.ts | 2 +- packages/opencode/src/cli/cmd/tui/worker.ts | 2 +- packages/opencode/src/plugin/index.ts | 2 +- .../opencode/src/server/instance/index.ts | 2 +- packages/opencode/src/server/server.ts | 26 ++++++++++++------- packages/opencode/src/server/ui/index.ts | 2 +- .../test/server/project-init-git.test.ts | 4 +-- .../test/server/session-actions.test.ts | 4 +-- .../test/server/session-messages.test.ts | 8 +++--- .../test/server/session-select.test.ts | 6 ++--- 11 files changed, 37 insertions(+), 33 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 2a8bed0927..6d8cc1d823 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -398,13 +398,11 @@ export namespace Agent { }), ) - export const defaultLayer = Layer.suspend(() => - layer.pipe( - Layer.provide(Provider.defaultLayer), - Layer.provide(Auth.defaultLayer), - Layer.provide(Config.defaultLayer), - Layer.provide(Skill.defaultLayer), - ), + export const defaultLayer = layer.pipe( + Layer.provide(Provider.defaultLayer), + Layer.provide(Auth.defaultLayer), + Layer.provide(Config.defaultLayer), + Layer.provide(Skill.defaultLayer), ) const { runPromise } = makeRuntime(Service, defaultLayer) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 04130aa951..3e234d87ec 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -680,7 +680,7 @@ export const RunCommand = cmd({ await bootstrap(process.cwd(), async () => { const fetchFn = (async (input: RequestInfo | URL, init?: RequestInit) => { const request = new Request(input, init) - return Server.Default().app.fetch(request) + return (await Server.Default()).app.fetch(request) }) as typeof globalThis.fetch const sdk = createOpencodeClient({ baseUrl: "http://opencode.internal", fetch: fetchFn }) await execute(sdk) diff --git a/packages/opencode/src/cli/cmd/tui/worker.ts b/packages/opencode/src/cli/cmd/tui/worker.ts index 15e02b8634..49bd19dd1b 100644 --- a/packages/opencode/src/cli/cmd/tui/worker.ts +++ b/packages/opencode/src/cli/cmd/tui/worker.ts @@ -138,7 +138,7 @@ export const rpc = { headers, body: input.body, }) - const response = await Server.Default().app.fetch(request) + const response = await (await Server.Default()).app.fetch(request) const body = await response.text() return { status: response.status, diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index 814e7870a4..9615b573ab 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -119,7 +119,7 @@ export namespace Plugin { Authorization: `Basic ${Buffer.from(`${Flag.OPENCODE_SERVER_USERNAME ?? "opencode"}:${Flag.OPENCODE_SERVER_PASSWORD}`).toString("base64")}`, } : undefined, - fetch: async (...args) => Server.Default().app.fetch(...args), + fetch: async (...args) => (await Server.Default()).app.fetch(...args), }) const cfg = yield* config.get() const input: PluginInput = { diff --git a/packages/opencode/src/server/instance/index.ts b/packages/opencode/src/server/instance/index.ts index fb13d9b24a..b3cbe94ea9 100644 --- a/packages/opencode/src/server/instance/index.ts +++ b/packages/opencode/src/server/instance/index.ts @@ -24,7 +24,7 @@ import { ProviderRoutes } from "./provider" import { EventRoutes } from "./event" import { WorkspaceRouterMiddleware } from "./middleware" -export const InstanceRoutes = (upgrade: UpgradeWebSocket) => +export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => new Hono() .use(WorkspaceRouterMiddleware(upgrade)) .route("/project", ProjectRoutes()) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 903882d3cc..79f46eb3b4 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -3,19 +3,12 @@ import { Hono } from "hono" import { createNodeWebSocket } from "@hono/node-ws" import { MDNS } from "./mdns" import { lazy } from "@/util/lazy" -import { AuthMiddleware, CompressionMiddleware, CorsMiddleware, ErrorMiddleware, LoggerMiddleware } from "./middleware" -import { InstanceRoutes } from "./instance" -import { initProjectors } from "./projectors" import { createAdaptorServer, type ServerType } from "@hono/node-server" -import { ControlPlaneRoutes } from "./control" import { Log } from "@/util/log" -import { UIRoutes } from "./ui" // @ts-ignore This global is needed to prevent ai-sdk from logging warnings to stdout https://github.com/vercel/ai/blob/2dc67e0ef538307f21368db32d5a12345d98831b/packages/ai/src/logger/log-warnings.ts#L85 globalThis.AI_SDK_LOG_WARNINGS = false -initProjectors() - export namespace Server { const log = Log.create({ service: "server" }) @@ -28,7 +21,20 @@ export namespace Server { export const Default = lazy(() => create({})) - function create(opts: { cors?: string[] }) { + async function create(opts: { cors?: string[] }) { + const [ + { AuthMiddleware, CompressionMiddleware, CorsMiddleware, ErrorMiddleware, LoggerMiddleware }, + , + { ControlPlaneRoutes }, + { InstanceRoutes }, + { UIRoutes }, + ] = await Promise.all([ + import("./middleware"), + import("./projectors"), + import("./control"), + import("./instance"), + import("./ui"), + ]) const app = new Hono() const ws = createNodeWebSocket({ app }) return { @@ -50,7 +56,7 @@ export namespace Server { // hono-openapi can see describeRoute metadata (`.route()` wraps // handlers when the sub-app has a custom errorHandler, which // strips the metadata symbol). - const { app } = create({}) + const { app } = await create({}) const result = await generateSpecs(app, { documentation: { info: { @@ -73,7 +79,7 @@ export namespace Server { mdnsDomain?: string cors?: string[] }): Promise { - const built = create(opts) + const built = await create(opts) const start = (port: number) => new Promise((resolve, reject) => { const server = createAdaptorServer({ fetch: built.app.fetch }) diff --git a/packages/opencode/src/server/ui/index.ts b/packages/opencode/src/server/ui/index.ts index 7043473bfe..afe6e510f1 100644 --- a/packages/opencode/src/server/ui/index.ts +++ b/packages/opencode/src/server/ui/index.ts @@ -16,7 +16,7 @@ const DEFAULT_CSP = const csp = (hash = "") => `default-src 'self'; script-src 'self' 'wasm-unsafe-eval'${hash ? ` 'sha256-${hash}'` : ""}; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src 'self' data:` -export const UIRoutes = () => +export const UIRoutes = (): Hono => new Hono().all("/*", async (c) => { const embeddedWebUI = await embeddedUIPromise const path = c.req.path diff --git a/packages/opencode/test/server/project-init-git.test.ts b/packages/opencode/test/server/project-init-git.test.ts index eca562a0f5..012035abf0 100644 --- a/packages/opencode/test/server/project-init-git.test.ts +++ b/packages/opencode/test/server/project-init-git.test.ts @@ -19,7 +19,7 @@ afterEach(async () => { describe("project.initGit endpoint", () => { test("initializes git and reloads immediately", async () => { await using tmp = await tmpdir() - const app = Server.Default().app + const app = (await Server.Default()).app const seen: { directory?: string; payload: { type: string } }[] = [] const fn = (evt: { directory?: string; payload: { type: string } }) => { seen.push(evt) @@ -76,7 +76,7 @@ describe("project.initGit endpoint", () => { test("does not reload when the project is already git", async () => { await using tmp = await tmpdir({ git: true }) - const app = Server.Default().app + const app = (await Server.Default()).app const seen: { directory?: string; payload: { type: string } }[] = [] const fn = (evt: { directory?: string; payload: { type: string } }) => { seen.push(evt) diff --git a/packages/opencode/test/server/session-actions.test.ts b/packages/opencode/test/server/session-actions.test.ts index 4ab485965e..fb3a17bc17 100644 --- a/packages/opencode/test/server/session-actions.test.ts +++ b/packages/opencode/test/server/session-actions.test.ts @@ -43,7 +43,7 @@ describe("session action routes", () => { fn: async () => { const session = await Session.create({}) const cancel = spyOn(SessionPrompt, "cancel").mockResolvedValue() - const app = Server.Default().app + const app = (await Server.Default()).app const res = await app.request(`/session/${session.id}/abort`, { method: "POST", @@ -67,7 +67,7 @@ describe("session action routes", () => { const msg = await user(session.id, "hello") const busy = spyOn(SessionRunState, "assertNotBusy").mockRejectedValue(new Session.BusyError(session.id)) const remove = spyOn(Session, "removeMessage").mockResolvedValue(msg.id) - const app = Server.Default().app + const app = (await Server.Default()).app const res = await app.request(`/session/${session.id}/message/${msg.id}`, { method: "DELETE", diff --git a/packages/opencode/test/server/session-messages.test.ts b/packages/opencode/test/server/session-messages.test.ts index 7ba95f3b1e..145668adc1 100644 --- a/packages/opencode/test/server/session-messages.test.ts +++ b/packages/opencode/test/server/session-messages.test.ts @@ -60,7 +60,7 @@ describe("session messages endpoint", () => { fn: async () => { const session = await Session.create({}) const ids = await fill(session.id, 5) - const app = Server.Default().app + const app = (await Server.Default()).app const a = await app.request(`/session/${session.id}/message?limit=2`) expect(a.status).toBe(200) @@ -89,7 +89,7 @@ describe("session messages endpoint", () => { fn: async () => { const session = await Session.create({}) const ids = await fill(session.id, 3) - const app = Server.Default().app + const app = (await Server.Default()).app const res = await app.request(`/session/${session.id}/message`) expect(res.status).toBe(200) @@ -109,7 +109,7 @@ describe("session messages endpoint", () => { directory: tmp.path, fn: async () => { const session = await Session.create({}) - const app = Server.Default().app + const app = (await Server.Default()).app const bad = await app.request(`/session/${session.id}/message?limit=2&before=bad`) expect(bad.status).toBe(400) @@ -131,7 +131,7 @@ describe("session messages endpoint", () => { fn: async () => { const session = await Session.create({}) await fill(session.id, 520) - const app = Server.Default().app + const app = (await Server.Default()).app const res = await app.request(`/session/${session.id}/message?limit=510`) expect(res.status).toBe(200) diff --git a/packages/opencode/test/server/session-select.test.ts b/packages/opencode/test/server/session-select.test.ts index 7558b4a6b6..009b212818 100644 --- a/packages/opencode/test/server/session-select.test.ts +++ b/packages/opencode/test/server/session-select.test.ts @@ -21,7 +21,7 @@ describe("tui.selectSession endpoint", () => { const session = await Session.create({}) // #when - const app = Server.Default().app + const app = (await Server.Default()).app const response = await app.request("/tui/select-session", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -47,7 +47,7 @@ describe("tui.selectSession endpoint", () => { const nonExistentSessionID = "ses_nonexistent123" // #when - const app = Server.Default().app + const app = (await Server.Default()).app const response = await app.request("/tui/select-session", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -69,7 +69,7 @@ describe("tui.selectSession endpoint", () => { const invalidSessionID = "invalid_session_id" // #when - const app = Server.Default().app + const app = (await Server.Default()).app const response = await app.request("/tui/select-session", { method: "POST", headers: { "Content-Type": "application/json" },