Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
import http from 'node:http'
import type { AddressInfo } from 'node:net'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { WebSocket } from 'ws'
import type { Frame, LocalClientSink } from './backendSocket.js'
import { attachLocalWsServer, type LocalWsBackend, type LocalWsServer, type LocalWsServerOptions } from './localWsServer.js'
import { encodeTerminalLocal, TerminalBinaryKind, type TerminalBinaryClear } from './lib/terminalBinary.js'
import { listenLocalSocket } from './lib/localSocket.js'
import { mkdtempSync, rmSync } from 'node:fs'
import { join } from 'node:path'
import { WindowForm } from './cable/windowForm.js'
const machineId = 'machine-123'
const streamId = '00112233-4455-6677-8899-aabbccddeeff'
class FakeBackend implements LocalWsBackend {
sink: LocalClientSink | null = null
connId: string | null = null
frames: Frame[] = []
binaries: TerminalBinaryClear[] = []
unregisters: string[] = []
focuses: Array<[string, string | null]> = []
tools: string[] = []
registerLocalClient(connId: string, sink: LocalClientSink, opts: { tool?: boolean } = {}): boolean {
this.connId = connId
this.sink = sink
if (opts.tool) this.tools.push(connId)
return true
}
async unregisterLocalClient(connId: string): Promise<void> {
this.unregisters.push(connId)
}
handleLocalFrame(_connId: string, frame: Frame): void {
this.frames.push(frame)
}
async handleLocalBinary(_connId: string, frame: TerminalBinaryClear): Promise<void> {
this.binaries.push(frame)
}
setLocalTerminalFocus(connId: string, agentId: string | null): void {
this.focuses.push([connId, agentId])
}
}
function onceOpen(ws: WebSocket): Promise<void> {
return new Promise((resolve, reject) => {
ws.once('open', () => resolve())
ws.once('error', reject)
})
}
function onceMessage(ws: WebSocket): Promise<Frame> {
return new Promise((resolve, reject) => {
ws.once('message', (raw) => {
try { resolve(JSON.parse(raw.toString()) as Frame) } catch (error) { reject(error) }
})
ws.once('error', reject)
})
}
describe('local CLI WebSocket', () => {
let server: http.Server | null = null
let local: LocalWsServer | null = null
afterEach(async () => {
await local?.close()
await new Promise<void>((resolve) => server?.close(() => resolve()) ?? resolve())
local = null
server = null
})
async function start(backend: FakeBackend, extra: Partial<LocalWsServerOptions> = {}): Promise<string> {
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, { machineId, backend, ...extra })
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const port = (server.address() as AddressInfo).port
return `ws://127.0.0.1:${port}/api/local-ws`
}
it('serves the same endpoint over the daemon socket, with no Host to name and no Origin allowed', async () => {
const dir = mkdtempSync('/tmp/hsock-')
const socketPath = join(dir, 'daemon.sock')
const backend = new FakeBackend()
const unix = await listenLocalSocket((_req, res) => { res.statusCode = 404; res.end() }, socketPath)
await start(backend, { localSocketServer: unix.server })
const url = `ws+unix://${socketPath}:/api/local-ws`
try {
// No port, no loopback Host — refused on TCP, served here.
const ws = new WebSocket(url, { headers: { host: 'rebind.evil.example' } })
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
expect(await connected).toMatchObject({ type: 'connected', payload: { machineId, transport: 'local' } })
expect(backend.connId).toMatch(/^local:/)
ws.close()
// A browser still has no business here, whichever way it arrived.
const browser = new WebSocket(url, { headers: { origin: 'http://localhost' } })
const status = await new Promise<number>((resolve) => browser.once('unexpected-response', (_req, res) => resolve(res.statusCode ?? 0)))
expect(status).toBe(403)
} finally {
await local?.close()
local = null
await unix.close()
rmSync(dir, { recursive: true, force: true })
}
})
it('refuses an upgrade whose Host is not a loopback name for this port', async () => {
const url = await start(new FakeBackend())
const ws = new WebSocket(url, { headers: { host: 'rebind.evil.example:' + new URL(url).port } })
const status = await new Promise<number>((resolve) => ws.once('unexpected-response', (_req, res) => resolve(res.statusCode ?? 0)))
expect(status).toBe(403)
})
it('hands a window that connects late the questions still open', async () => {
const asked = { type: 'commander_question', agentId: 'a1', dbSessionId: 's1', payload: { requestId: 'q_1', questions: [] } }
const ws = new WebSocket(await start(new FakeBackend(), { openQuestions: () => [asked] }))
await onceOpen(ws)
const frames: Frame[] = []
const got = new Promise<void>((resolve) => ws.on('message', (raw) => {
frames.push(JSON.parse(raw.toString()) as Frame)
if (frames.length === 3) resolve()
}))
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await got
expect(frames.map((f) => f.type)).toEqual(['connected', 'commander_question', 'commander_questions_open'])
expect(frames[1]).toEqual(asked)
expect(frames[2]).toEqual({ type: 'commander_questions_open', payload: { requestIds: ['q_1'] } })
ws.close()
})
it('consumes validated preparation UI acknowledgements locally', async () => {
const backend = new FakeBackend(), opened = vi.fn()
const ws = new WebSocket(await start(backend, { onDevicePrepareOpened: opened }))
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'device_prepare_opened', payload: { operationId: 'invalid', agentId: 'a' } }))
ws.send(JSON.stringify({ type: 'device_prepare_opened', payload: { operationId: 'a'.repeat(64), agentId: 'agent1' } }))
await vi.waitFor(() => expect(opened).toHaveBeenCalledExactlyOnceWith('a'.repeat(64), 'agent1'))
expect(backend.frames).toEqual([])
ws.close()
})
it.each(['selection', 'visit', 'form'])('addresses one window for %s and consumes its result locally', async kind => {
const backend = new FakeBackend(), reply = vi.fn()
const ws = new WebSocket(await start(backend, { [kind === 'form' ? 'onFormReply' : kind === 'visit' ? 'onVisitReply' : 'onSelectionReply']: reply }))
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
expect(local!.sendToWindow('unknown', { type: `dial_${kind}`, payload: {} })).toBe(false)
const request = onceMessage(ws)
expect(local!.sendToWindow(backend.connId!, { type: `dial_${kind}`, payload: { requestId: 'selection' } })).toBe(true)
expect(await request).toEqual({ type: `dial_${kind}`, payload: { requestId: 'selection' } })
ws.send(JSON.stringify({ type: `app_${kind}_result`, payload: { text: 'private selected text' } }))
await vi.waitFor(() => expect(reply).toHaveBeenCalledWith(backend.connId, machineId, { text: 'private selected text' }))
expect(backend.frames).toEqual([])
const id = backend.connId!
ws.close()
await vi.waitFor(() => expect(local!.sendToWindow(id, { type: `dial_${kind}`, payload: {} })).toBe(false))
})
it.each(['selection', 'visit', 'form'])('keeps %s on this desk and ignores upstream gestures', async kind => {
const backend = new FakeBackend(), reply = vi.fn(), focus = vi.fn()
const relayed: Frame[] = [], received: Frame[] = []
let upstream: LocalClientSink | undefined
const relayPool = {
acquire: async (_id: string, _env: string, _select: Frame, sink: LocalClientSink) => {
upstream = sink
sink.sendFrame({ type: 'connected', payload: { machineId: 'remote', e2ee: false } })
return { send: async (frame: Frame) => { relayed.push(frame) }, sendBinary: async () => {}, detach: () => {} }
},
acquireIsolated: async () => { throw new Error('unused') }, invalidate: () => {},
}
const ws = new WebSocket(await start(backend, {
autonomousEnv: 'test', [kind === 'form' ? 'onFormReply' : kind === 'visit' ? 'onVisitReply' : 'onSelectionReply']: reply, onAppFocusState: focus,
relayPool: relayPool as unknown as NonNullable<LocalWsServerOptions['relayPool']>,
}))
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId: 'remote', localProtocolVersion: 1 } }))
await connected
ws.on('message', raw => received.push(JSON.parse(raw.toString())))
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'remote-agent' } }))
await vi.waitFor(() => expect(focus).toHaveBeenCalled())
const connId = focus.mock.calls[0][2] as string
upstream!.sendFrame({ type: `dial_${kind}`, payload: { requestId: 'upstream' } })
const selection = onceMessage(ws)
expect(local!.sendToWindow(connId, { type: `dial_${kind}`, payload: { requestId: 'from-device' } })).toBe(true)
expect((await selection).payload).toEqual({ requestId: 'from-device' })
ws.send(JSON.stringify({ type: `app_${kind}_result`, payload: { text: 'quoted remote output' } }))
await vi.waitFor(() => expect(reply).toHaveBeenCalledWith(connId, 'remote', { text: 'quoted remote output' }))
expect(relayed.some(frame => frame.type === `app_${kind}_result`)).toBe(false)
expect(received.filter(frame => frame.type === `dial_${kind}`)).toHaveLength(1)
expect(backend.frames).toEqual([])
ws.close()
})
it('accepts loopback, selects the exact machine, and routes JSON plus HTRL binary', async () => {
const backend = new FakeBackend()
const url = await start(backend)
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({
type: 'machine_select',
payload: { machineId, localProtocolVersion: 1 },
}))
await expect(connected).resolves.toMatchObject({
type: 'connected',
payload: { machineId, transport: 'local', e2ee: false },
})
ws.send(JSON.stringify({ type: 'agents_list', payload: { requestId: 'r1' } }))
const binary = encodeTerminalLocal({
kind: TerminalBinaryKind.input,
streamId,
seq: 1,
bytes: new TextEncoder().encode('hello'),
compressed: false,
})!
ws.send(binary)
await new Promise((resolve) => setTimeout(resolve, 20))
expect(backend.frames).toEqual([{ type: 'agents_list', payload: { requestId: 'r1' } }])
expect(backend.binaries[0]).toMatchObject({
kind: TerminalBinaryKind.input,
streamId,
seq: 1,
})
const reply = onceMessage(ws)
expect(backend.sink?.sendFrame({ type: 'agents_list_result', payload: { requestId: 'r1', agents: [] } })).toBe(true)
await expect(reply).resolves.toMatchObject({ type: 'agents_list_result' })
ws.close()
})
// A window from before it introduced itself on `terminal_open` still gets named on the far
// machine's "took control" banner: this daemon knows the window is its own desktop.
it('introduces a silent window on a relayed terminal_open, and believes one that speaks', async () => {
const backend = new FakeBackend()
const relayed: Frame[] = []
const relayPool = {
acquire: async (_machineId: string, _env: string, _select: Frame, sink: LocalClientSink) => {
sink.sendFrame({ type: 'connected', payload: { machineId: 'other-machine', e2ee: false } })
return { send: async (frame: Frame) => { relayed.push(frame) }, sendBinary: async () => {}, detach: () => {} }
},
acquireIsolated: async () => { throw new Error('unused') },
invalidate: () => {},
}
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId, backend, autonomousEnv: 'test',
relayPool: relayPool as unknown as NonNullable<Parameters<typeof attachLocalWsServer>[1]['relayPool']>,
localClient: () => ({ kind: 'desktop', name: 'This Mac', machineId }),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const ws = new WebSocket(`ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId: 'other-machine', localProtocolVersion: 1 } }))
await expect(connected).resolves.toMatchObject({ type: 'connected' })
ws.send(JSON.stringify({ type: 'terminal_open', payload: { requestId: 'o1', agentId: 'a', cols: 80, rows: 24, protocolVersion: 3 } }))
ws.send(JSON.stringify({ type: 'terminal_open', payload: { requestId: 'o2', agentId: 'a', cols: 80, rows: 24, protocolVersion: 3, client: { kind: 'desktop', name: 'Named by the window' } } }))
ws.send(JSON.stringify({ type: 'agents_list', payload: { requestId: 'r1' } }))
await new Promise((resolve) => setTimeout(resolve, 30))
expect(relayed).toEqual([
{ type: 'terminal_open', payload: { requestId: 'o1', agentId: 'a', cols: 80, rows: 24, protocolVersion: 3, client: { kind: 'desktop', name: 'This Mac', machineId } } },
{ type: 'terminal_open', payload: { requestId: 'o2', agentId: 'a', cols: 80, rows: 24, protocolVersion: 3, client: { kind: 'desktop', name: 'Named by the window' } } },
{ type: 'agents_list', payload: { requestId: 'r1' } },
])
ws.close()
})
it('takes the window\'s tile roster, keeps it off the wire, and forgets it on close', async () => {
const backend = new FakeBackend()
const rosters: string[][] = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onAppPanes: (ids) => rosters.push(ids),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_panes', payload: { agentIds: ['a1', 'a2', '', 7, null] } }))
await new Promise((resolve) => setTimeout(resolve, 20))
// Anything that is not a usable id is dropped rather than trusted.
expect(rosters).toEqual([['a1', 'a2']])
// Like app_focus: it describes a screen at this desk, so the machine never sees it.
expect(backend.frames.map((frame) => frame.type)).toEqual([])
ws.close()
// A window that went away has no tiles open. Left standing, the roster would go on silencing the
// dial for agents nobody can see any more — backwards, and permanently.
await vi.waitFor(() => expect(rosters).toEqual([['a1', 'a2'], []]))
})
it('says whether the window those tiles belong to is actually in front', async () => {
// The roster alone cannot answer it: every pane keeps its place on the tab
// while the window sits behind a browser. Without this the dial stayed quiet
// about work nobody could see, which is the one case it exists for.
const backend = new FakeBackend()
const seen: Array<{ ids: string[]; foreground: boolean }> = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onAppPanes: (ids, foreground) => seen.push({ ids, foreground }),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_panes', payload: { agentIds: ['a1'], foreground: true } }))
ws.send(JSON.stringify({ type: 'app_panes', payload: { agentIds: ['a1'], foreground: false } }))
// A window that predates the field only ever sent this list while it was up,
// so absence reads as in front — the behaviour it has today.
ws.send(JSON.stringify({ type: 'app_panes', payload: { agentIds: ['a1'] } }))
await vi.waitFor(() => expect(seen).toHaveLength(3))
expect(seen.map((row) => row.foreground)).toEqual([true, false, true])
ws.close()
// No window at all is not a window in front.
await vi.waitFor(() => expect(seen[3]).toEqual({ ids: [], foreground: false }))
})
it('takes the window\'s swarms, drops what is not a swarm, and forgets them on close', async () => {
const backend = new FakeBackend()
const seen: unknown[] = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onAppSwarms: (swarms) => seen.push(swarms),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_swarms', payload: {
active: 's2',
swarms: [
{ id: 's1', name: 'Workshop', agentIds: ['a1', '', 7, 'a2'], panes: 3 },
{ id: '', name: 'no id' },
'junk',
{ id: 's2', name: 'Launch' },
],
} }))
await new Promise((resolve) => setTimeout(resolve, 20))
expect(seen).toEqual([{ active: 's2', swarms: [
// Three tiles, two of them agents: the third is a shell or a viewer, and saying so is the
// point — see the terminal-only tab below.
{ id: 's1', name: 'Workshop', agentIds: ['a1', 'a2'], panes: 3 },
// No count at all, from a window too old to send one: as many tiles as agents, which is what
// this row meant before the field existed.
{ id: 's2', name: 'Launch', agentIds: [], panes: 0 },
// This window sent no `tiles`, which is how every window behaved until it had a device with a
// face big enough to draw one. Empty is the honest reading, and the device falls back to
// deriving the shape from the count exactly as it does today.
], tiles: [] }])
// Like app_panes: a fact about this desk, so the machine never sees it.
expect(backend.frames.map((frame) => frame.type)).toEqual([])
ws.close()
// The window is gone, and so are its tabs.
await vi.waitFor(() => expect(seen).toHaveLength(2))
expect(seen[1]).toBeNull()
})
it('follows an explicit app_focus, and keeps it off the wire', async () => {
const backend = new FakeBackend()
const moves: Array<{ machineId: string; agentId: string }> = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onAppFocus: (m, a) => moves.push({ machineId: m, agentId: a }),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
// Opening a terminal still counts: that is all an older app build sends.
ws.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'agent-opened' } }))
// And a window that MOVED without opening anything now says so — which is every click on a pane
// that already holds a live session, the case the dial used to miss entirely.
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'agent-focused' } }))
ws.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'background-restored' } }))
await new Promise((resolve) => setTimeout(resolve, 20))
expect(moves).toEqual([
{ machineId, agentId: 'agent-opened' },
{ machineId, agentId: 'agent-focused' },
])
// Consumed locally: it describes a hand at this desk, and the machine has no use for an unknown
// frame type arriving on every pane click.
expect(backend.frames.map((frame) => frame.type)).toEqual(['terminal_open', 'terminal_open'])
ws.close()
})
it('reports only explicit voice focus and clears by originating connection', async () => {
const backend = new FakeBackend()
const states: Array<{ machine: string; agent: string | null; conn: string }> = []
const disconnected = vi.fn()
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId, backend,
onAppFocusState: (machine, agent, conn) => states.push({ machine, agent, conn }),
onAppDisconnect: disconnected,
})
await new Promise<void>(resolve => server!.listen(0, '127.0.0.1', resolve))
const ws = new WebSocket(`ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'background' } }))
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'focused' } }))
ws.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'another-background' } }))
await vi.waitFor(() => expect(states).toHaveLength(1))
expect(states[0]).toMatchObject({ machine: machineId, agent: 'focused' })
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: null } }))
await vi.waitFor(() => expect(states).toHaveLength(2))
expect(states[1]).toEqual({ ...states[0], agent: null })
expect(backend.frames.map(frame => frame.type)).toEqual(['terminal_open', 'terminal_open'])
ws.close()
await vi.waitFor(() => expect(disconnected).toHaveBeenCalledExactlyOnceWith(machineId, states[0].conn))
expect(states).toHaveLength(2)
})
it('keeps Find on the live desktop when a background or replaced socket closes', async () => {
const backend = new FakeBackend(), disconnected = vi.fn()
let focused: { machineId: string; connId: string } | undefined
const form = new WindowForm({ focus: () => focused,
send: (conn, payload) => local!.sendToWindow(conn, { type: 'dial_form', payload }) })
const url = await start(backend, {
onAppFocusState: (machineId, _agent, connId) => { focused = { machineId, connId } },
onAppDisconnect: (machine, conn) => {
disconnected(machine, conn)
if (focused?.connId === conn) focused = undefined
form.disconnected(conn)
},
onFormReply: (conn, machine, payload) => form.reply(conn, machine, payload),
})
const connect = async () => {
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
return { ws, connId: backend.connId! }
}
const select = async (client: Awaited<ReturnType<typeof connect>>, agentId: string | null) => {
client.ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId } }))
await vi.waitFor(() => expect(focused?.connId).toBe(client.connId))
}
const close = async (client: Awaited<ReturnType<typeof connect>>) => {
client.ws.close()
await vi.waitFor(() => expect(backend.unregisters).toContain(client.connId))
}
const ready = async (client: Awaited<ReturnType<typeof connect>>, id: string) => {
const received = onceMessage(client.ws)
const result = form.command({ op: 'open', surface: 'find', formId: id })
const frame = await received
expect(frame.type).toBe('dial_form')
client.ws.send(JSON.stringify({ type: 'app_form_result', payload: {
...(frame.payload as Record<string, unknown>), ok: true, active: true, revision: 1, position: 0, total: 0,
busy: false, enabled: false, canQuery: true, title: 'Find Harness', label: 'Say a name',
} }))
expect(await result).toMatchObject({ ok: true, active: true, canQuery: true })
}
const desktop = await connect()
await select(desktop, null) // An empty workspace can still open Find.
const background = await connect()
await close(background)
expect(focused?.connId).toBe(desktop.connId)
await ready(desktop, 'find-after-background-close')
const replacement = await connect()
await select(replacement, 'selected-pane')
await close(desktop) // The old connection closes after the new one reports focus.
expect(focused?.connId).toBe(replacement.connId)
await ready(replacement, 'find-after-reconnect')
await close(replacement)
expect(focused).toBeUndefined()
expect(disconnected).toHaveBeenCalledTimes(3)
expect(await form.command({ op: 'open', surface: 'find', formId: 'find-offline' }))
.toMatchObject({ ok: false, active: false })
expect(backend.frames).toEqual([])
expect(backend.binaries).toEqual([])
})
it('keeps background connections from stealing selection and releases compatibility mode on disconnect', async () => {
const backend = new FakeBackend(), dial = vi.fn()
const url = await start(backend, { onAppFocus: dial })
const select = async () => {
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
return ws
}
const selected = await select()
selected.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'hn' } }))
await vi.waitFor(() => expect(dial).toHaveBeenCalledExactlyOnceWith(machineId, 'hn'))
const background = await select()
background.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'firmware' } }))
await vi.waitFor(() => expect(backend.frames).toHaveLength(1))
expect(dial).toHaveBeenCalledTimes(1)
selected.send(JSON.stringify({ type: 'app_focus', payload: { agentId: null } }))
selected.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'another-background' } }))
await vi.waitFor(() => expect(backend.frames).toHaveLength(2))
expect(dial).toHaveBeenCalledTimes(1) // a cleared selection must also stay clear
selected.close()
await vi.waitFor(() => expect(backend.unregisters).toHaveLength(1))
background.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'legacy-window' } }))
await vi.waitFor(() => expect(dial).toHaveBeenLastCalledWith(machineId, 'legacy-window'))
background.close()
})
it('keeps stale automatic focus off the dial and forwards its revision for validation', async () => {
const backend = new FakeBackend()
const focus = vi.fn(() => false), dial = vi.fn()
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, { machineId, backend, onAppFocusState: focus, onAppFocus: dial })
await new Promise<void>(resolve => server!.listen(0, '127.0.0.1', resolve))
const ws = new WebSocket(`ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'first', focusRevision: 'old:0' } }))
ws.send(JSON.stringify({ type: 'terminal_open', payload: { agentId: 'background' } }))
await vi.waitFor(() => expect(focus).toHaveBeenCalledTimes(1))
await vi.waitFor(() => expect(backend.frames).toHaveLength(1))
expect(focus).toHaveBeenCalledWith(machineId, 'first', expect.any(String), 'old:0')
expect(dial).not.toHaveBeenCalled()
expect(backend.frames.map((frame) => frame.type)).toEqual(['terminal_open'])
ws.close()
})
it('tells this daemon\'s terminals which one is focused, even when the dial refuses the move', async () => {
const backend = new FakeBackend()
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
// A stale revision keeps the dial where it is; it says nothing about the terminal in front of the person.
local = attachLocalWsServer(server, { machineId, backend, onAppFocusState: () => false })
await new Promise<void>(resolve => server!.listen(0, '127.0.0.1', resolve))
const ws = new WebSocket(`ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'focused', focusRevision: 'old:0' } }))
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: '' } })) // malformed: ignored
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: null } }))
await vi.waitFor(() => expect(backend.focuses).toHaveLength(2))
expect(backend.focuses).toEqual([[backend.connId, 'focused'], [backend.connId, null]])
ws.close()
})
it('never hands a relayed machine\'s focus to this daemon\'s terminals', async () => {
const backend = new FakeBackend()
const relayPool = {
acquire: async (_machineId: string, _env: string, _select: Frame, sink: LocalClientSink) => {
sink.sendFrame({ type: 'connected', payload: { machineId: 'other-machine', e2ee: false } })
return { send: async () => {}, sendBinary: async () => {}, detach: () => {} }
},
acquireIsolated: async () => { throw new Error('unused') },
invalidate: () => {},
}
const states: Array<string | null> = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId, backend, autonomousEnv: 'test',
relayPool: relayPool as unknown as NonNullable<Parameters<typeof attachLocalWsServer>[1]['relayPool']>,
onAppFocusState: (_machine, agent) => { states.push(agent) },
})
await new Promise<void>(resolve => server!.listen(0, '127.0.0.1', resolve))
const ws = new WebSocket(`ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId: 'other-machine', localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'app_focus', payload: { agentId: 'remote-agent' } }))
await vi.waitFor(() => expect(states).toEqual(['remote-agent']))
expect(backend.focuses).toEqual([])
ws.close()
})
/** The daemon's Unix socket beside the TCP port: the pair brain's frames are taken only over the socket. */
async function unixWorld(backend: FakeBackend, extra: Partial<LocalWsServerOptions> = {}) {
const dir = mkdtempSync('/tmp/hsock-')
const socketPath = join(dir, 'daemon.sock')
const unix = await listenLocalSocket((_req, res) => { res.statusCode = 404; res.end() }, socketPath)
const tcp = await start(backend, { localSocketServer: unix.server, ...extra })
const open = async (url: string, select: Record<string, unknown>): Promise<WebSocket> => {
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { localProtocolVersion: 1, ...select } }))
await connected
return ws
}
const cleanup = async (): Promise<void> => {
await local?.close()
local = null
await unix.close()
rmSync(dir, { recursive: true, force: true })
}
return { unix: `ws+unix://${socketPath}:/api/local-ws`, tcp, open, cleanup }
}
it('takes the pair brain\'s frames only over its own socket, and keys, talk and confirmations only from a window', async () => {
const backend = new FakeBackend()
const relayed: Frame[] = []
const relayPool = {
acquire: async (_machineId: string, _env: string, _select: Frame, sink: LocalClientSink) => {
sink.sendFrame({ type: 'connected', payload: { machineId: 'other-machine', e2ee: false } })
return { send: async (frame: Frame) => { relayed.push(frame) }, sendBinary: async () => {}, detach: () => {} }
},
acquireIsolated: async () => { throw new Error('unused') },
invalidate: () => {},
}
const got: Array<[string, Record<string, unknown>]> = []
const presence: Array<{ payload: Record<string, unknown>; ui: boolean }> = []
const w = await unixWorld(backend, {
autonomousEnv: 'test',
relayPool: relayPool as unknown as NonNullable<Parameters<typeof attachLocalWsServer>[1]['relayPool']>,
onDaemonAct: (_connId, payload, reply) => { got.push(['act', payload]); reply({ type: 'daemon_act_result', payload: { requestId: payload.requestId, ok: true } }) },
onDaemonTalk: (_connId, payload, reply) => { got.push(['talk', payload]); reply({ type: 'daemon_talk_result', payload: { requestId: payload.requestId, ok: true } }) },
onDaemonConfirm: (_connId, payload, reply) => { got.push(['confirm', payload]); reply({ type: 'daemon_confirm_result', payload: { requestId: payload.requestId, ok: true } }) },
onDaemonShown: (_connId, payload) => { got.push(['shown', payload]) },
onDaemonPresence: (_connId, payload, meta) => { presence.push({ payload, ui: meta.ui }) },
})
try {
// A window on this machine, over the socket: every one of them reaches the brain.
const ws = await w.open(w.unix, { machineId })
ws.send(JSON.stringify({ type: 'daemon_presence', payload: { active: true, awayMs: 0 } }))
ws.send(JSON.stringify({ type: 'daemon_shown', payload: { id: 'need:x' } }))
let result = onceMessage(ws)
ws.send(JSON.stringify({ type: 'daemon_act', payload: { requestId: 'r1', id: 'need:x', choice: 'n' } }))
expect(await result).toEqual({ type: 'daemon_act_result', payload: { requestId: 'r1', ok: true } })
result = onceMessage(ws)
ws.send(JSON.stringify({ type: 'daemon_talk', payload: { requestId: 't1', text: 'what needs me?' } }))
expect(await result).toEqual({ type: 'daemon_talk_result', payload: { requestId: 't1', ok: true } })
result = onceMessage(ws)
ws.send(JSON.stringify({ type: 'daemon_confirm', payload: { requestId: 'c1', kind: 'autonomy', nonce: 'n1', accept: true } }))
expect(await result).toEqual({ type: 'daemon_confirm_result', payload: { requestId: 'c1', ok: true } })
expect(got.map(([kind]) => kind)).toEqual(['shown', 'act', 'talk', 'confirm'])
expect(presence).toEqual([{ payload: { active: true, awayMs: 0 }, ui: true }])
ws.close()
// Over TCP — any user's process can reach it — none of them, and nothing is passed on.
const tcp = await w.open(w.tcp, { machineId })
tcp.send(JSON.stringify({ type: 'daemon_presence', payload: { active: false } }))
tcp.send(JSON.stringify({ type: 'daemon_shown', payload: { id: 'need:x' } }))
result = onceMessage(tcp)
tcp.send(JSON.stringify({ type: 'daemon_act', payload: { requestId: 'r2', id: 'need:x', choice: 'y' } }))
expect(await result).toMatchObject({ type: 'daemon_act_result', payload: { requestId: 'r2', id: 'need:x', ok: false, error: 'LOCAL_SOCKET_REQUIRED' } })
result = onceMessage(tcp)
tcp.send(JSON.stringify({ type: 'daemon_confirm', payload: { requestId: 'c2', kind: 'rules', nonce: 'n2' } }))
expect(await result).toMatchObject({ type: 'daemon_confirm_result', payload: { requestId: 'c2', kind: 'rules', nonce: 'n2', ok: false, error: 'LOCAL_SOCKET_REQUIRED' } })
tcp.close()
// A tool (`harness pair`, the MCP server) is not a window, even over the socket.
const tool = await w.open(w.unix, { machineId, tool: true })
result = onceMessage(tool)
tool.send(JSON.stringify({ type: 'daemon_talk', payload: { requestId: 't3', text: 'hi' } }))
expect(await result).toMatchObject({ type: 'daemon_talk_result', payload: { requestId: 't3', ok: false, error: 'UI_ONLY' } })
tool.close()
// A relayed machine's socket: its presence is a fact about this desk; a key on it is not a window's.
const relay = await w.open(w.unix, { machineId: 'other-machine' })
relay.send(JSON.stringify({ type: 'daemon_presence', payload: { active: true } }))
result = onceMessage(relay)
relay.send(JSON.stringify({ type: 'daemon_act', payload: { requestId: 'r4', id: 'need:x', choice: 'y' } }))
expect(await result).toMatchObject({ type: 'daemon_act_result', payload: { requestId: 'r4', ok: false, error: 'UI_ONLY' } })
relay.close()
expect(got.map(([kind]) => kind)).toEqual(['shown', 'act', 'talk', 'confirm'])
expect(presence.map((p) => p.ui)).toEqual([true, false])
// Neither this daemon's dispatcher (whose send() uploads) nor the relayed machine ever saw one.
expect(backend.frames).toEqual([])
expect(relayed).toEqual([])
} finally {
await w.cleanup()
}
})
it('serves individual art on the private socket and refuses it on TCP', async () => {
const backend = new FakeBackend()
const called = vi.fn((_connId, payload, reply) => reply({ type: 'daemon_plate', payload: { requestId: payload.requestId, frames: [{ rows: 'o', mats: '.' }] } }))
const w = await unixWorld(backend, { onDaemonPlate: called })
try {
const socket = await w.open(w.unix, { machineId })
let result = onceMessage(socket)
socket.send(JSON.stringify({ type: 'daemon_plate_get', payload: { requestId: 'art' } }))
expect(await result).toMatchObject({ type: 'daemon_plate', payload: { requestId: 'art', frames: [{ rows: 'o', mats: '.' }] } })
const tcp = await w.open(w.tcp, { machineId })
result = onceMessage(tcp)
tcp.send(JSON.stringify({ type: 'daemon_plate_get', payload: { requestId: 'tcp' } }))
expect(await result).toMatchObject({ type: 'daemon_plate', payload: { requestId: 'tcp', error: 'LOCAL_SOCKET_REQUIRED' } })
expect(called).toHaveBeenCalledOnce()
expect(backend.frames).toEqual([])
socket.close()
tcp.close()
} finally { await w.cleanup() }
})
it('answers daemon_act UNSUPPORTED when there is no pair brain, rather than passing it on', async () => {
const backend = new FakeBackend()
const w = await unixWorld(backend)
try {
const ws = await w.open(w.unix, { machineId })
const result = onceMessage(ws)
ws.send(JSON.stringify({ type: 'daemon_act', payload: { requestId: 'r1', id: 'need:x', choice: 'y' } }))
expect(await result).toEqual({ type: 'daemon_act_result', payload: { requestId: 'r1', id: 'need:x', ok: false, error: 'UNSUPPORTED' } })
expect(backend.frames).toEqual([])
ws.close()
} finally {
await w.cleanup()
}
})
it('carries the window\'s answer about a spoken task, and keeps it off the wire', async () => {
const backend = new FakeBackend()
const replies: Array<{ voiceId: string; reply: unknown }> = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onVoiceRouteReply: (voiceId, reply) => replies.push({ voiceId, reply }),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
ws.send(JSON.stringify({ type: 'voice_route_reply', payload: { voiceId: 'v1', state: 'taken' } }))
ws.send(JSON.stringify({ type: 'voice_route_reply', payload: { voiceId: 'v1', state: 'sent', agentId: 'a7' } }))
ws.send(JSON.stringify({ type: 'voice_route_reply', payload: { voiceId: 'v2', state: 'cancelled' } }))
// Neither of these is an answer: one names no request, the other a state this side cannot read.
// Guessing at either would settle a spoken turn on something nobody said.
ws.send(JSON.stringify({ type: 'voice_route_reply', payload: { state: 'sent', agentId: 'a9' } }))
ws.send(JSON.stringify({ type: 'voice_route_reply', payload: { voiceId: 'v3', state: 'maybe' } }))
await new Promise((resolve) => setTimeout(resolve, 20))
expect(replies).toEqual([
{ voiceId: 'v1', reply: { t: 'taken' } },
{ voiceId: 'v1', reply: { t: 'sent', agentId: 'a7' } },
{ voiceId: 'v2', reply: { t: 'cancelled' } },
])
// It describes a hand at this desk. The machine has no use for it.
expect(backend.frames).toEqual([])
ws.close()
})
it('answers a routed task on the id it was asked with, and sends nothing', async () => {
const backend = new FakeBackend()
const asked: string[] = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onRouteTask: async (text) => {
asked.push(text)
return {
agentId: 'a1', machineId: 'm-local', name: 'auth-api', confidence: 0.86, reason: 'name matches',
weighed: 4, machines: 2, via: 'model',
candidates: [{ agentId: 'a1', machineId: 'm-local', name: 'auth-api', machine: 'this computer', engine: 'claude', recent: 'token rotation', confidence: 0.86 }],
}
},
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
const answered = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_task', payload: { requestId: 'q-7', text: ' fix the retry ' } }))
const reply = await answered // onceMessage already parses
// The requestId comes back UNTOUCHED — it is the window's own rpc id, and the only thing tying this
// answer to the spinner it is holding open.
expect(reply.type).toBe('route_result')
expect(reply.payload).toMatchObject({ requestId: 'q-7', agentId: 'a1', machineId: 'm-local', name: 'auth-api', confidence: 0.86 })
expect(asked).toEqual(['fix the retry'])
// Asking is not sending. Nothing reached the machine.
expect(backend.frames.map((frame) => frame.type)).toEqual([])
ws.close()
})
it('still answers when there is nothing to answer with', async () => {
// The window holds a spinner on the id it asked with, so silence is the one reply it cannot recover
// from — an empty task and a router that throws must both come back as frames.
const backend = new FakeBackend()
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onRouteTask: async () => { throw new Error('router unavailable') },
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
const blank = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_task', payload: { requestId: 'q-empty', text: ' ' } }))
expect((await blank).payload).toMatchObject({ requestId: 'q-empty', agentId: '', reason: 'empty task' })
const failed = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_task', payload: { requestId: 'q-throw', text: 'anything' } }))
expect((await failed).payload).toMatchObject({ requestId: 'q-throw', agentId: '', reason: 'router unavailable' })
ws.close()
})
it('delivers a committed route, and keeps the frame off the wire', async () => {
const backend = new FakeBackend()
const sent: Array<{ agentId: string; text: string }> = []
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onRouteSend: (agentId, text) => {
sent.push({ agentId, text })
return { ok: true as const }
},
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
const delivered = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_send', payload: { requestId: 's-1', agentId: 'a2', text: 'do the thing' } }))
expect((await delivered).payload).toMatchObject({ requestId: 's-1', ok: true })
// The half-formed one is dropped rather than delivered to whoever sorts first — and it is REFUSED
// out loud, because the window is waiting on this id either way.
const refused = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_send', payload: { requestId: 's-2', agentId: '', text: 'nobody' } }))
expect((await refused).payload).toMatchObject({ requestId: 's-2', ok: false })
expect(sent).toEqual([{ agentId: 'a2', text: 'do the thing' }])
expect(backend.frames.map((frame) => frame.type)).toEqual([])
ws.close()
})
it('says so when the agent could not be delivered to', async () => {
// The remote leg carries no ack of its own: a machine that has gone deaf takes the turn and nothing
// comes back. With the palette closing silently on a confident route, that is a task that vanishes
// without a mark anywhere — so the refusal has to travel.
const backend = new FakeBackend()
server = http.createServer((_req, res) => { res.statusCode = 404; res.end() })
local = attachLocalWsServer(server, {
machineId,
backend,
onRouteSend: () => ({ ok: false as const, machine: 'mac-mini', reason: 'the last request to it did not come back' }),
})
await new Promise<void>((resolve) => server!.listen(0, '127.0.0.1', resolve))
const url = `ws://127.0.0.1:${(server.address() as AddressInfo).port}/api/local-ws`
const ws = new WebSocket(url)
await onceOpen(ws)
const connected = onceMessage(ws)
ws.send(JSON.stringify({ type: 'machine_select', payload: { machineId, localProtocolVersion: 1 } }))
await connected
const answered = onceMessage(ws)
ws.send(JSON.stringify({ type: 'route_send', payload: { requestId: 's-3', agentId: 'a9', text: 'work' } }))
expect((await answered).payload).toMatchObject({
requestId: 's-3', ok: false, machine: 'mac-mini', reason: 'the last request to it did not come back',
})
ws.close()
})
it('does not require a credential on the loopback transport', async () => {
const url = await start(new FakeBackend())
const ws = new WebSocket(url, ['legacy-client-label'])
await onceOpen(ws)
ws.close()
})
it('rejects browser origins and machine-id mismatches', async () => {
const url = await start(new FakeBackend())
const browser = new WebSocket(url, { origin: 'https://example.com' })
const error = await new Promise<Error>((resolve) => browser.once('error', resolve))
expect(error.message).toContain('403')
const ws = new WebSocket(url)
await onceOpen(ws)
const closed = new Promise<number>((resolve) => ws.once('close', resolve))
ws.send(JSON.stringify({
type: 'machine_select',
payload: { machineId: 'other-machine', localProtocolVersion: 1 },
}))
await expect(closed).resolves.toBe(4403)
})
})
56ae2e47fThis file is pinned to the selected release. Download the original to open it in your design tool.