diff --git a/packages/opencode/src/pty/index.ts b/packages/opencode/src/pty/index.ts index fdb46c817..33083485b 100644 --- a/packages/opencode/src/pty/index.ts +++ b/packages/opencode/src/pty/index.ts @@ -39,9 +39,8 @@ export namespace Pty { return next } - const token = (ws: unknown) => { - if (!ws || typeof ws !== "object") return ws - const data = (ws as { data?: unknown }).data + const token = (ws: Socket) => { + const data = ws.data if (data === undefined) return if (data === null) return if (typeof data !== "object") return data @@ -318,7 +317,7 @@ export namespace Pty { } } - export function connect(id: string, ws: Socket, cursor?: number, identity?: unknown) { + export function connect(id: string, ws: Socket, cursor?: number) { const session = state().get(id) if (!session) { ws.close() @@ -338,7 +337,7 @@ export namespace Pty { } owners.set(ws, id) - session.subscribers.set(ws, { id: socketId, token: token(identity ?? ws) }) + session.subscribers.set(ws, { id: socketId, token: token(ws) }) const cleanup = () => { session.subscribers.delete(ws) diff --git a/packages/opencode/src/server/routes/pty.ts b/packages/opencode/src/server/routes/pty.ts index 640cfa333..368c9612b 100644 --- a/packages/opencode/src/server/routes/pty.ts +++ b/packages/opencode/src/server/routes/pty.ts @@ -182,7 +182,7 @@ export const PtyRoutes = lazy(() => ws.close() return } - handler = Pty.connect(id, socket, cursor, ws) + handler = Pty.connect(id, socket, cursor) }, onMessage(event) { if (typeof event.data !== "string") return diff --git a/packages/opencode/test/pty/pty-output-isolation.test.ts b/packages/opencode/test/pty/pty-output-isolation.test.ts index 2c9cc5d92..07e86ea97 100644 --- a/packages/opencode/test/pty/pty-output-isolation.test.ts +++ b/packages/opencode/test/pty/pty-output-isolation.test.ts @@ -98,54 +98,6 @@ describe("pty", () => { }) }) - test("does not leak when identity token is only on websocket wrapper", async () => { - await using dir = await tmpdir({ git: true }) - - await Instance.provide({ - directory: dir.path, - fn: async () => { - const a = await Pty.create({ command: "cat", title: "a" }) - try { - const outA: string[] = [] - const outB: string[] = [] - const text = (data: string | Uint8Array | ArrayBuffer) => { - if (typeof data === "string") return data - if (data instanceof ArrayBuffer) return Buffer.from(new Uint8Array(data)).toString("utf8") - return Buffer.from(data).toString("utf8") - } - - const raw: Parameters[1] = { - readyState: 1, - send: (data) => { - outA.push(text(data)) - }, - close: () => { - // no-op - }, - } - - const wrap = { data: { events: { connection: "a" } } } - - Pty.connect(a.id, raw, undefined, wrap) - outA.length = 0 - - // Simulate Bun reusing the raw socket object before the next onOpen, - // while the connection token only exists on the wrapper socket. - raw.send = (data) => { - outB.push(text(data)) - } - - Pty.write(a.id, "AAA\n") - await Bun.sleep(100) - - expect(outB.join("")).not.toContain("AAA") - } finally { - await Pty.remove(a.id) - } - }, - }) - }) - test("does not leak output when socket data mutates in-place", async () => { await using dir = await tmpdir({ git: true })