From 387220f368ca3a31d94b4be3937d9d825ebd888c Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sun, 3 May 2026 14:23:29 -0400 Subject: fix(server): support desktop PTY websockets with HttpApi (#25598) --- .../app/src/utils/terminal-websocket-url.test.ts | 36 ++++++++++++++++++++++ packages/app/src/utils/terminal-websocket-url.ts | 16 ++++++++++ 2 files changed, 52 insertions(+) create mode 100644 packages/app/src/utils/terminal-websocket-url.test.ts create mode 100644 packages/app/src/utils/terminal-websocket-url.ts (limited to 'packages/app/src/utils') diff --git a/packages/app/src/utils/terminal-websocket-url.test.ts b/packages/app/src/utils/terminal-websocket-url.test.ts new file mode 100644 index 000000000..c85863abd --- /dev/null +++ b/packages/app/src/utils/terminal-websocket-url.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, test } from "bun:test" +import { terminalWebSocketURL } from "./terminal-websocket-url" + +describe("terminalWebSocketURL", () => { + test("uses query auth without embedding credentials in websocket URL", () => { + const url = terminalWebSocketURL({ + url: "http://127.0.0.1:49365", + id: "pty_test", + directory: "/tmp/project", + cursor: 0, + sameOrigin: false, + username: "opencode", + password: "secret", + }) + + expect(url.protocol).toBe("ws:") + expect(url.username).toBe("") + expect(url.password).toBe("") + expect(url.searchParams.get("auth_token")).toBe(btoa("opencode:secret")) + }) + + test("omits query auth for same-origin websocket URL", () => { + const url = terminalWebSocketURL({ + url: "https://app.example.test", + id: "pty_test", + directory: "/tmp/project", + cursor: 10, + sameOrigin: true, + username: "opencode", + password: "secret", + }) + + expect(url.protocol).toBe("wss:") + expect(url.searchParams.has("auth_token")).toBe(false) + }) +}) diff --git a/packages/app/src/utils/terminal-websocket-url.ts b/packages/app/src/utils/terminal-websocket-url.ts new file mode 100644 index 000000000..146df16b7 --- /dev/null +++ b/packages/app/src/utils/terminal-websocket-url.ts @@ -0,0 +1,16 @@ +export function terminalWebSocketURL(input: { + url: string + id: string + directory: string + cursor: number + sameOrigin: boolean + username: string + password?: string +}) { + const next = new URL(`${input.url}/pty/${input.id}/connect`) + next.searchParams.set("directory", input.directory) + next.searchParams.set("cursor", String(input.cursor)) + next.protocol = next.protocol === "https:" ? "wss:" : "ws:" + if (!input.sameOrigin && input.password) next.searchParams.set("auth_token", btoa(`${input.username}:${input.password}`)) + return next +} -- cgit v1.2.3