From a05915ddc8f34d592c05ac6a4f4e8d932a9a0964 Mon Sep 17 00:00:00 2001 From: Ashutosh Kumar Date: Mon, 22 Dec 2025 17:26:23 +0530 Subject: [PATCH] server: ensure frontend has correct port for PTY websocket connections (#5898) --- packages/desktop/src/app.tsx | 2 +- packages/opencode/src/server/server.ts | 34 +++++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/desktop/src/app.tsx b/packages/desktop/src/app.tsx index 2ed529bbc..e5607fd33 100644 --- a/packages/desktop/src/app.tsx +++ b/packages/desktop/src/app.tsx @@ -35,7 +35,7 @@ const url = new URLSearchParams(document.location.search).get("url") || (location.hostname.includes("opencode.ai") || location.hostname.includes("localhost") ? `http://${host}:${port}` - : "/") + : window.location.origin) export function App() { return ( diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index e92c46225..69bd5e3be 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -6,7 +6,6 @@ import { describeRoute, generateSpecs, validator, resolver, openAPIRouteHandler import { Hono } from "hono" import { cors } from "hono/cors" import { stream, streamSSE } from "hono/streaming" -import { proxy } from "hono/proxy" import { Session } from "../session" import z from "zod" import { Provider } from "../provider/provider" @@ -54,6 +53,9 @@ globalThis.AI_SDK_LOG_WARNINGS = false export namespace Server { const log = Log.create({ service: "server" }) + // Port that the server is running on, used to inject into frontend HTML + let serverPort: number = 4096 + export const Event = { Connected: BusEvent.define("server.connected", z.object({})), Disposed: BusEvent.define("global.disposed", z.object({})), @@ -2578,12 +2580,25 @@ export namespace Server { }, ) .all("/*", async (c) => { - return proxy(`https://desktop.opencode.ai${c.req.path}`, { - ...c.req, + const response = await fetch(`https://desktop.opencode.ai${c.req.path}`, { + method: c.req.method, headers: { host: "desktop.opencode.ai", }, }) + + const contentType = response.headers.get("content-type") || "" + + // If this is an HTML response, inject the server port + if (contentType.includes("text/html")) { + const html = await response.text() + const portScript = `` + // Inject the script right after the opening tag + const modifiedHtml = html.replace("", `${portScript}`) + return c.html(modifiedHtml) + } + + return response }), ) @@ -2607,14 +2622,9 @@ export namespace Server { idleTimeout: 0, fetch: App().fetch, websocket: websocket, - } as const - if (opts.port === 0) { - try { - return Bun.serve({ ...args, port: 4096 }) - } catch { - // port 4096 not available, fall through to use port 0 - } - } - return Bun.serve({ ...args, port: opts.port }) + }) + // Store the actual port for injection into frontend HTML + serverPort = server.port ?? opts.port + return server } }