Skip to content

Commit 8f93890

Browse files
0xdsqrColin4k1024
authored andcommitted
fix(app): derive terminal WebSocket URL from browser origin instead o… (anomalyco#12178)
1 parent 9b8aa7d commit 8f93890

3 files changed

Lines changed: 48 additions & 2 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { describe, expect, test } from "bun:test"
2+
import { ptySocketUrl } from "./terminal-url"
3+
4+
describe("ptySocketUrl", () => {
5+
test("uses browser host instead of sdk host", () => {
6+
const url = ptySocketUrl("http://localhost:4096", "pty_1", "/repo", {
7+
host: "192.168.1.50:4096",
8+
protocol: "http:",
9+
})
10+
expect(url.toString()).toBe("ws://192.168.1.50:4096/pty/pty_1/connect?directory=%2Frepo")
11+
})
12+
13+
test("uses secure websocket on https", () => {
14+
const url = ptySocketUrl("http://localhost:4096", "pty_1", "/repo", {
15+
host: "opencode.local",
16+
protocol: "https:",
17+
})
18+
expect(url.toString()).toBe("wss://opencode.local/pty/pty_1/connect?directory=%2Frepo")
19+
})
20+
21+
test("preserves browser port", () => {
22+
const url = ptySocketUrl("http://localhost:4096", "pty_1", "/repo", {
23+
host: "opencode.local:8443",
24+
protocol: "https:",
25+
})
26+
expect(url.toString()).toBe("wss://opencode.local:8443/pty/pty_1/connect?directory=%2Frepo")
27+
})
28+
29+
test("handles slash base url", () => {
30+
const url = ptySocketUrl("/", "pty_1", "/repo", {
31+
host: "192.168.1.50:4096",
32+
protocol: "http:",
33+
})
34+
expect(url.toString()).toBe("ws://192.168.1.50:4096/pty/pty_1/connect?directory=%2Frepo")
35+
})
36+
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function ptySocketUrl(base: string, id: string, directory: string, origin: { host: string; protocol: string }) {
2+
const root = `${origin.protocol}//${origin.host}`
3+
const current = new URL(root)
4+
const prefix = /^https?:\/\//.test(base) ? base : new URL(base || "/", root).toString()
5+
const url = new URL(prefix.replace(/\/+$/, "") + `/pty/${id}/connect?directory=${encodeURIComponent(directory)}`)
6+
url.hostname = current.hostname
7+
url.port = current.port
8+
url.protocol = origin.protocol === "https:" ? "wss:" : "ws:"
9+
return url
10+
}

packages/app/src/components/terminal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { LocalPTY } from "@/context/terminal"
88
import { resolveThemeVariant, useTheme, withAlpha, type HexColor } from "@opencode-ai/ui/theme"
99
import { useLanguage } from "@/context/language"
1010
import { showToast } from "@opencode-ai/ui/toast"
11+
import { ptySocketUrl } from "./terminal-url"
1112

1213
export interface TerminalProps extends ComponentProps<"div"> {
1314
pty: LocalPTY
@@ -163,8 +164,7 @@ export const Terminal = (props: TerminalProps) => {
163164

164165
const once = { value: false }
165166

166-
const url = new URL(sdk.url + `/pty/${local.pty.id}/connect?directory=${encodeURIComponent(sdk.directory)}`)
167-
url.protocol = url.protocol === "https:" ? "wss:" : "ws:"
167+
const url = ptySocketUrl(sdk.url, local.pty.id, sdk.directory, window.location)
168168
if (window.__OPENCODE__?.serverPassword) {
169169
url.username = "opencode"
170170
url.password = window.__OPENCODE__?.serverPassword

0 commit comments

Comments
 (0)