@braedonsaunders/appkit-desk 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/protocol.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The framed JSON protocol spoken between the host and the in-guest agent\n * over vsock. Everything here is pure encode/decode/validate — no sockets, no\n * processes — so the security-critical parsing is unit-testable on any\n * platform, and both the host backend and the guest agent share one message\n * vocabulary.\n *\n * Wire format: a 4-byte big-endian length prefix followed by that many bytes\n * of UTF-8 JSON. Frame sizes are bounded; a peer declaring an oversized frame\n * is a protocol violation and the connection must be dropped, not resynced.\n */\nimport { Buffer } from 'node:buffer'\nimport type {\n A11yNode,\n DeskFrameFormat,\n DeskHandoverScope,\n DeskPoint,\n DeskPointerButton,\n DeskVideoChunkKind,\n WindowInfo,\n} from './events'\n\nexport const FRAME_HEADER_BYTES = 4\nexport const DEFAULT_MAX_FRAME_BYTES = 8 * 1024 * 1024\n/** The vsock port the in-guest agent listens on. */\nexport const GUEST_AGENT_VSOCK_PORT = 5252\n\nconst REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/\nconst MAX_STRING_LENGTH = 65_536\nconst MAX_ARGUMENTS = 256\nconst MAX_ENVIRONMENT_ENTRIES = 128\nconst MAX_WINDOWS = 256\nconst MAX_A11Y_NODES = 10_000\nconst MAX_A11Y_DEPTH = 32\n\nexport class DeskProtocolError extends Error {\n override readonly name = 'DeskProtocolError'\n}\n\nexport type GuestInput =\n | { type: 'move'; x: number; y: number }\n | { type: 'click'; x: number; y: number; button: DeskPointerButton }\n | { type: 'type'; text: string }\n | { type: 'key'; combo: string }\n | { type: 'scroll'; x: number; y: number; dx: number; dy: number }\n | { type: 'drag'; from: DeskPoint; to: DeskPoint }\n\n/** A request body, before the transport assigns its correlation id. */\nexport type GuestCommand =\n | { op: 'ping' }\n | { op: 'capabilities' }\n | {\n op: 'exec'\n command: string\n args?: readonly string[]\n cwd?: string\n env?: Readonly<Record<string, string>>\n timeoutMs?: number\n }\n | {\n op: 'job-start'\n command: string\n args?: readonly string[]\n cwd?: string\n env?: Readonly<Record<string, string>>\n }\n | { op: 'job-signal'; jobId: string; signal: 'SIGTERM' | 'SIGKILL' }\n | { op: 'screen-start'; width: number; height: number }\n | { op: 'screen-stop' }\n | { op: 'observe' }\n | { op: 'input'; input: GuestInput }\n | { op: 'a11y-invoke'; nodeId: string; action: string }\n | { op: 'launch'; appId: string; args?: readonly string[] }\n | { op: 'clipboard-read' }\n | { op: 'clipboard-write'; text: string }\n | {\n op: 'frames-start'\n fps: number\n width: number\n height: number\n /** Omitted lets the guest choose; a guest that predates this ignores it. */\n format?: DeskFrameFormat\n }\n | { op: 'frames-stop' }\n | { op: 'video-start'; fps: number; width: number; height: number }\n | { op: 'video-stop' }\n | { op: 'handover-begin'; ttlMs: number; scope: DeskHandoverScope }\n | { op: 'handover-end' }\n\nexport type GuestOp = GuestCommand['op']\n\nexport type GuestRequest = GuestCommand & { id: string }\n\nexport type GuestResponse =\n | { id: string; ok: true; result: unknown }\n | { id: string; ok: false; error: string }\n\n/** Unsolicited guest-to-host messages: job exits, frames, focus changes. */\nexport type GuestEventMessage =\n | { event: 'job-exit'; jobId: string; exitCode: number | null; signal: string | null }\n | {\n event: 'frame'\n seq: number\n width: number\n height: number\n data: string\n /**\n * How `data` is encoded. Absent on the wire means `png`: frames were\n * PNG-only before this field existed, so an older guest paired with a\n * newer host keeps working rather than having its every frame rejected.\n */\n format: DeskFrameFormat\n }\n | {\n event: 'video-chunk'\n seq: number\n kind: DeskVideoChunkKind\n /** RFC 6381, e.g. `avc1.42C020`, read out of the bytes by the guest. */\n codec: string\n width: number\n height: number\n /**\n * Whether a `media` chunk begins at a sync sample. Only a chunk that does\n * can start or resume a decoder; `init` chunks report false because the\n * question does not apply to them.\n */\n keyframe: boolean\n data: string\n }\n | { event: 'window-focus'; window: WindowInfo }\n\nexport type HostBoundMessage = GuestResponse | GuestEventMessage\n\n/** The wire shape of an exec result, before the host turns it into a snapshot. */\nexport interface GuestExecResult {\n exitCode: number | null\n signal: string | null\n stdout: string\n stderr: string\n truncated: boolean\n}\n\n/** The wire shape of an observation; `png` is base64. */\nexport interface GuestObservation {\n png: string\n width: number\n height: number\n a11y: A11yNode | null\n windows: WindowInfo[]\n focused: WindowInfo | null\n}\n\n/** Encode one message as a length-prefixed JSON frame. */\nexport function encodeFrame(message: unknown, maxFrameBytes = DEFAULT_MAX_FRAME_BYTES): Buffer {\n const body = Buffer.from(JSON.stringify(message), 'utf8')\n if (body.byteLength > maxFrameBytes) {\n throw new DeskProtocolError(\n `Refusing to encode a ${body.byteLength}-byte frame; the limit is ${maxFrameBytes}.`,\n )\n }\n const frame = Buffer.allocUnsafe(FRAME_HEADER_BYTES + body.byteLength)\n frame.writeUInt32BE(body.byteLength, 0)\n body.copy(frame, FRAME_HEADER_BYTES)\n return frame\n}\n\n/**\n * Incremental frame decoder. Feed it arbitrary chunk boundaries; it returns\n * every complete parsed JSON value. A declared frame length beyond the bound\n * or a body that is not valid JSON throws — framing violations are fatal to\n * the connection because there is no way to resynchronize a byte stream whose\n * lengths cannot be trusted.\n */\nexport class FrameDecoder {\n readonly #maxFrameBytes: number\n #buffered: Buffer = Buffer.alloc(0)\n\n constructor(options: { maxFrameBytes?: number } = {}) {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES\n if (!Number.isInteger(maxFrameBytes) || maxFrameBytes < 1) {\n throw new DeskProtocolError('maxFrameBytes must be a positive integer.')\n }\n this.#maxFrameBytes = maxFrameBytes\n }\n\n push(chunk: Buffer): unknown[] {\n this.#buffered = this.#buffered.byteLength === 0\n ? chunk\n : Buffer.concat([this.#buffered, chunk])\n const messages: unknown[] = []\n while (this.#buffered.byteLength >= FRAME_HEADER_BYTES) {\n const declared = this.#buffered.readUInt32BE(0)\n if (declared > this.#maxFrameBytes) {\n throw new DeskProtocolError(\n `Peer declared a ${declared}-byte frame; the limit is ${this.#maxFrameBytes}.`,\n )\n }\n if (this.#buffered.byteLength < FRAME_HEADER_BYTES + declared) break\n const body = this.#buffered.subarray(FRAME_HEADER_BYTES, FRAME_HEADER_BYTES + declared)\n this.#buffered = this.#buffered.subarray(FRAME_HEADER_BYTES + declared)\n try {\n messages.push(JSON.parse(body.toString('utf8')))\n } catch (error) {\n throw new DeskProtocolError(\n `Frame body is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n return messages\n }\n}\n\n/** Validate a host-to-guest request. Unknown ops and malformed fields throw. */\nexport function parseGuestRequest(value: unknown): GuestRequest {\n const record = asRecord(value, 'request')\n const id = requireString(record, 'id')\n if (!REQUEST_ID_PATTERN.test(id)) {\n throw new DeskProtocolError('Request id must be 1–128 URL-safe characters.')\n }\n const op = requireString(record, 'op')\n switch (op) {\n case 'ping':\n case 'capabilities':\n case 'screen-stop':\n case 'observe':\n case 'clipboard-read':\n case 'frames-stop':\n case 'video-stop':\n case 'handover-end':\n return { id, op }\n case 'exec':\n return {\n id,\n op,\n command: requireString(record, 'command'),\n args: optionalStringArray(record, 'args'),\n cwd: optionalString(record, 'cwd'),\n env: optionalEnvironment(record),\n timeoutMs: optionalPositiveInteger(record, 'timeoutMs'),\n }\n case 'job-start':\n return {\n id,\n op,\n command: requireString(record, 'command'),\n args: optionalStringArray(record, 'args'),\n cwd: optionalString(record, 'cwd'),\n env: optionalEnvironment(record),\n }\n case 'job-signal': {\n const signal = requireString(record, 'signal')\n if (signal !== 'SIGTERM' && signal !== 'SIGKILL') {\n throw new DeskProtocolError('job-signal signal must be SIGTERM or SIGKILL.')\n }\n return { id, op, jobId: requireString(record, 'jobId'), signal }\n }\n case 'screen-start':\n return {\n id,\n op,\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n }\n case 'input':\n return { id, op, input: parseGuestInput(record.input) }\n case 'a11y-invoke':\n return {\n id,\n op,\n nodeId: requireString(record, 'nodeId'),\n action: requireString(record, 'action'),\n }\n case 'launch':\n return {\n id,\n op,\n appId: requireString(record, 'appId'),\n args: optionalStringArray(record, 'args'),\n }\n case 'clipboard-write':\n return { id, op, text: requireString(record, 'text') }\n case 'frames-start':\n return {\n id,\n op,\n fps: requirePositiveInteger(record, 'fps'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n format: optionalFrameFormat(record),\n }\n case 'video-start':\n return {\n id,\n op,\n fps: requirePositiveInteger(record, 'fps'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n }\n case 'handover-begin':\n return {\n id,\n op,\n ttlMs: requirePositiveInteger(record, 'ttlMs'),\n scope: parseHandoverScope(record.scope),\n }\n default:\n throw new DeskProtocolError(`Unknown request op: ${op}`)\n }\n}\n\nexport function parseGuestInput(value: unknown): GuestInput {\n const record = asRecord(value, 'input')\n const type = requireString(record, 'type')\n switch (type) {\n case 'move':\n return { type, x: requireCoordinate(record, 'x'), y: requireCoordinate(record, 'y') }\n case 'click':\n return {\n type,\n x: requireCoordinate(record, 'x'),\n y: requireCoordinate(record, 'y'),\n button: parsePointerButton(record.button),\n }\n case 'type':\n return { type, text: requireString(record, 'text') }\n case 'key':\n return { type, combo: requireString(record, 'combo') }\n case 'scroll':\n return {\n type,\n x: requireCoordinate(record, 'x'),\n y: requireCoordinate(record, 'y'),\n dx: requireDelta(record, 'dx'),\n dy: requireDelta(record, 'dy'),\n }\n case 'drag':\n return { type, from: parsePoint(record.from), to: parsePoint(record.to) }\n default:\n throw new DeskProtocolError(`Unknown input type: ${type}`)\n }\n}\n\n/** Validate a guest-to-host message: a correlated response or an event. */\nexport function parseHostBoundMessage(value: unknown): HostBoundMessage {\n const record = asRecord(value, 'message')\n if ('id' in record) {\n const id = requireString(record, 'id')\n if (record.ok === true) return { id, ok: true, result: record.result ?? {} }\n if (record.ok === false) return { id, ok: false, error: requireString(record, 'error') }\n throw new DeskProtocolError('Response ok must be a boolean.')\n }\n const event = requireString(record, 'event')\n switch (event) {\n case 'job-exit':\n return {\n event,\n jobId: requireString(record, 'jobId'),\n exitCode: nullableInteger(record, 'exitCode'),\n signal: nullableString(record, 'signal'),\n }\n case 'frame':\n return {\n event,\n seq: requireNonNegativeInteger(record, 'seq'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n data: requireUnboundedString(record, 'data'),\n // Absent means png — see the field's contract on GuestEventMessage.\n format: optionalFrameFormat(record) ?? 'png',\n }\n case 'video-chunk':\n return {\n event,\n seq: requireNonNegativeInteger(record, 'seq'),\n kind: parseVideoChunkKind(record.kind),\n codec: requireString(record, 'codec'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n keyframe: record.keyframe === true,\n data: requireUnboundedString(record, 'data'),\n }\n case 'window-focus':\n return { event, window: parseWindowInfo(record.window) }\n default:\n throw new DeskProtocolError(`Unknown event: ${event}`)\n }\n}\n\n/** Validate the result payload of an `exec` response. */\nexport function parseExecResult(value: unknown): GuestExecResult {\n const record = asRecord(value, 'exec result')\n return {\n exitCode: nullableInteger(record, 'exitCode'),\n signal: nullableString(record, 'signal'),\n stdout: requireUnboundedString(record, 'stdout'),\n stderr: requireUnboundedString(record, 'stderr'),\n truncated: record.truncated === true,\n }\n}\n\n/** Validate the result payload of a `job-start` response. */\nexport function parseJobStarted(value: unknown): { jobId: string } {\n const record = asRecord(value, 'job-start result')\n return { jobId: requireString(record, 'jobId') }\n}\n\n/** Validate the result payload of an `observe` response. */\nexport function parseObservation(value: unknown): GuestObservation {\n const record = asRecord(value, 'observation')\n const windows = parseWindows(record.windows)\n return {\n png: requireUnboundedString(record, 'png'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n a11y: record.a11y === null || record.a11y === undefined\n ? null\n : parseA11yTree(record.a11y),\n windows,\n focused: record.focused === null || record.focused === undefined\n ? null\n : parseWindowInfo(record.focused),\n }\n}\n\n/** Validate the result payload of a `handover-begin` response. */\nexport function parseHandoverBegun(value: unknown): { url: string } {\n const record = asRecord(value, 'handover-begin result')\n return { url: requireString(record, 'url') }\n}\n\n/** Validate the result payload of a `clipboard-read` response. */\nexport function parseClipboardText(value: unknown): string {\n const record = asRecord(value, 'clipboard-read result')\n return requireUnboundedString(record, 'text')\n}\n\n/** Validate the result payload of a `capabilities` response. */\nexport function parseCapabilities(value: unknown): { virtioGpu: boolean } {\n const record = asRecord(value, 'capabilities result')\n return { virtioGpu: record.virtioGpu === true }\n}\n\nexport function parseWindowInfo(value: unknown): WindowInfo {\n const record = asRecord(value, 'window')\n return {\n id: requireString(record, 'id'),\n title: requireString(record, 'title'),\n appId: nullableString(record, 'appId'),\n }\n}\n\nfunction parseWindows(value: unknown): WindowInfo[] {\n if (value === undefined || value === null) return []\n if (!Array.isArray(value) || value.length > MAX_WINDOWS) {\n throw new DeskProtocolError(`windows must be an array of at most ${MAX_WINDOWS} entries.`)\n }\n return value.map(parseWindowInfo)\n}\n\nfunction parseA11yTree(value: unknown): A11yNode {\n const budget = { remaining: MAX_A11Y_NODES }\n return parseA11yNode(value, budget, 0)\n}\n\nfunction parseA11yNode(value: unknown, budget: { remaining: number }, depth: number): A11yNode {\n if (depth > MAX_A11Y_DEPTH) {\n throw new DeskProtocolError(`Accessibility tree exceeds depth ${MAX_A11Y_DEPTH}.`)\n }\n if (budget.remaining <= 0) {\n throw new DeskProtocolError(`Accessibility tree exceeds ${MAX_A11Y_NODES} nodes.`)\n }\n budget.remaining -= 1\n const record = asRecord(value, 'a11y node')\n const rawChildren = record.children ?? []\n if (!Array.isArray(rawChildren)) {\n throw new DeskProtocolError('a11y node children must be an array.')\n }\n return {\n id: requireString(record, 'id'),\n role: requireString(record, 'role'),\n name: nullableString(record, 'name'),\n actions: optionalStringArray(record, 'actions') ?? [],\n bounds: record.bounds === null || record.bounds === undefined\n ? null\n : parseBounds(record.bounds),\n children: rawChildren.map((child) => parseA11yNode(child, budget, depth + 1)),\n }\n}\n\nfunction parseBounds(value: unknown): { x: number; y: number; width: number; height: number } {\n const record = asRecord(value, 'bounds')\n return {\n x: requireDelta(record, 'x'),\n y: requireDelta(record, 'y'),\n width: requireNonNegativeInteger(record, 'width'),\n height: requireNonNegativeInteger(record, 'height'),\n }\n}\n\nfunction parsePoint(value: unknown): DeskPoint {\n const record = asRecord(value, 'point')\n return { x: requireCoordinate(record, 'x'), y: requireCoordinate(record, 'y') }\n}\n\nfunction parsePointerButton(value: unknown): DeskPointerButton {\n if (value === undefined) return 'left'\n if (value === 'left' || value === 'middle' || value === 'right') return value\n throw new DeskProtocolError('button must be left, middle, or right.')\n}\n\n/**\n * A frame format, when the field is present. Absent is `undefined` here and\n * every caller decides what that means; on a frame event it means `png`,\n * because that is what the field's absence used to imply.\n */\nfunction optionalFrameFormat(record: Record<string, unknown>): DeskFrameFormat | undefined {\n const value = record.format\n if (value === undefined) return undefined\n if (value === 'png' || value === 'jpeg') return value\n throw new DeskProtocolError('format must be png or jpeg.')\n}\n\nfunction parseVideoChunkKind(value: unknown): DeskVideoChunkKind {\n if (value === 'init' || value === 'media') return value\n throw new DeskProtocolError('video chunk kind must be init or media.')\n}\n\nfunction parseHandoverScope(value: unknown): DeskHandoverScope {\n if (value === 'view' || value === 'control') return value\n throw new DeskProtocolError('scope must be view or control.')\n}\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new DeskProtocolError(`Expected ${label} to be an object.`)\n }\n return value as Record<string, unknown>\n}\n\nfunction requireString(record: Record<string, unknown>, field: string): string {\n const value = record[field]\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(\n `${field} must be a string of 1–${MAX_STRING_LENGTH} characters.`,\n )\n }\n return value\n}\n\nfunction requireUnboundedString(record: Record<string, unknown>, field: string): string {\n // Bounded by the frame limit rather than the field limit; used for payloads\n // such as command output, screenshots, and clipboard text.\n const value = record[field]\n if (typeof value !== 'string') {\n throw new DeskProtocolError(`${field} must be a string.`)\n }\n return value\n}\n\nfunction optionalString(record: Record<string, unknown>, field: string): string | undefined {\n return record[field] === undefined ? undefined : requireString(record, field)\n}\n\nfunction nullableString(record: Record<string, unknown>, field: string): string | null {\n const value = record[field]\n if (value === null || value === undefined) return null\n return requireString(record, field)\n}\n\nfunction optionalStringArray(\n record: Record<string, unknown>,\n field: string,\n): string[] | undefined {\n const value = record[field]\n if (value === undefined) return undefined\n if (!Array.isArray(value) || value.length > MAX_ARGUMENTS) {\n throw new DeskProtocolError(`${field} must be an array of at most ${MAX_ARGUMENTS} strings.`)\n }\n return value.map((entry, index) => {\n if (typeof entry !== 'string' || entry.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(`${field}[${index}] must be a string of at most ${MAX_STRING_LENGTH} characters.`)\n }\n return entry\n })\n}\n\nfunction optionalEnvironment(\n record: Record<string, unknown>,\n): Record<string, string> | undefined {\n const value = record.env\n if (value === undefined) return undefined\n const env = asRecord(value, 'env')\n const entries = Object.entries(env)\n if (entries.length > MAX_ENVIRONMENT_ENTRIES) {\n throw new DeskProtocolError(`env must have at most ${MAX_ENVIRONMENT_ENTRIES} entries.`)\n }\n const clean: Record<string, string> = {}\n for (const [key, entry] of entries) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n throw new DeskProtocolError(`Invalid environment variable name: ${key}`)\n }\n if (typeof entry !== 'string' || entry.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(`env.${key} must be a string of at most ${MAX_STRING_LENGTH} characters.`)\n }\n clean[key] = entry\n }\n return clean\n}\n\nfunction requirePositiveInteger(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 1) {\n throw new DeskProtocolError(`${field} must be a positive integer.`)\n }\n return value\n}\n\nfunction optionalPositiveInteger(\n record: Record<string, unknown>,\n field: string,\n): number | undefined {\n return record[field] === undefined ? undefined : requirePositiveInteger(record, field)\n}\n\nfunction requireNonNegativeInteger(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new DeskProtocolError(`${field} must be a non-negative integer.`)\n }\n return value\n}\n\nfunction requireDimension(record: Record<string, unknown>, field: string): number {\n const value = requirePositiveInteger(record, field)\n if (value > 16_384) {\n throw new DeskProtocolError(`${field} must be at most 16384 pixels.`)\n }\n return value\n}\n\nfunction requireCoordinate(record: Record<string, unknown>, field: string): number {\n return requireNonNegativeInteger(record, field)\n}\n\nfunction requireDelta(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value)) {\n throw new DeskProtocolError(`${field} must be an integer.`)\n }\n return value\n}\n\nfunction nullableInteger(record: Record<string, unknown>, field: string): number | null {\n const value = record[field]\n if (value === null || value === undefined) return null\n if (typeof value !== 'number' || !Number.isInteger(value)) {\n throw new DeskProtocolError(`${field} must be an integer or null.`)\n }\n return value\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The framed JSON protocol spoken between the host and the in-guest agent\n * over vsock. Everything here is pure encode/decode/validate — no sockets, no\n * processes — so the security-critical parsing is unit-testable on any\n * platform, and both the host backend and the guest agent share one message\n * vocabulary.\n *\n * Wire format: a 4-byte big-endian length prefix followed by that many bytes\n * of UTF-8 JSON. Frame sizes are bounded; a peer declaring an oversized frame\n * is a protocol violation and the connection must be dropped, not resynced.\n */\nimport { Buffer } from 'node:buffer'\nimport type {\n A11yNode,\n DeskFrameFormat,\n DeskHandoverScope,\n DeskPoint,\n DeskPointerButton,\n DeskVideoChunkKind,\n WindowInfo,\n} from './events'\n\nexport const FRAME_HEADER_BYTES = 4\nexport const DEFAULT_MAX_FRAME_BYTES = 8 * 1024 * 1024\n/** The vsock port the in-guest agent listens on. */\nexport const GUEST_AGENT_VSOCK_PORT = 5252\n\nconst REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/\nconst MAX_STRING_LENGTH = 65_536\nconst MAX_ARGUMENTS = 256\nconst MAX_ENVIRONMENT_ENTRIES = 128\nconst MAX_WINDOWS = 256\nconst MAX_A11Y_NODES = 10_000\nconst MAX_A11Y_DEPTH = 32\n\nexport class DeskProtocolError extends Error {\n override readonly name = 'DeskProtocolError'\n}\n\nexport type GuestInput =\n | { type: 'move'; x: number; y: number }\n | { type: 'click'; x: number; y: number; button: DeskPointerButton; clicks: 1 | 2 }\n | { type: 'type'; text: string }\n | { type: 'key'; combo: string }\n | { type: 'scroll'; x: number; y: number; dx: number; dy: number }\n | { type: 'drag'; from: DeskPoint; to: DeskPoint }\n\n/** A request body, before the transport assigns its correlation id. */\nexport type GuestCommand =\n | { op: 'ping' }\n | { op: 'capabilities' }\n | {\n op: 'exec'\n command: string\n args?: readonly string[]\n cwd?: string\n env?: Readonly<Record<string, string>>\n timeoutMs?: number\n }\n | {\n op: 'job-start'\n command: string\n args?: readonly string[]\n cwd?: string\n env?: Readonly<Record<string, string>>\n }\n | { op: 'job-signal'; jobId: string; signal: 'SIGTERM' | 'SIGKILL' }\n | { op: 'screen-start'; width: number; height: number }\n | { op: 'screen-stop' }\n | { op: 'observe' }\n | { op: 'input'; input: GuestInput }\n | { op: 'a11y-invoke'; nodeId: string; action: string }\n | { op: 'launch'; appId: string; args?: readonly string[] }\n | { op: 'clipboard-read' }\n | { op: 'clipboard-write'; text: string }\n | {\n op: 'frames-start'\n fps: number\n width: number\n height: number\n /** Omitted lets the guest choose; a guest that predates this ignores it. */\n format?: DeskFrameFormat\n }\n | { op: 'frames-stop' }\n | { op: 'video-start'; fps: number; width: number; height: number }\n | { op: 'video-stop' }\n | { op: 'handover-begin'; ttlMs: number; scope: DeskHandoverScope }\n | { op: 'handover-end' }\n\nexport type GuestOp = GuestCommand['op']\n\nexport type GuestRequest = GuestCommand & { id: string }\n\nexport type GuestResponse =\n | { id: string; ok: true; result: unknown }\n | { id: string; ok: false; error: string }\n\n/** Unsolicited guest-to-host messages: job exits, frames, focus changes. */\nexport type GuestEventMessage =\n | { event: 'job-exit'; jobId: string; exitCode: number | null; signal: string | null }\n | {\n event: 'frame'\n seq: number\n width: number\n height: number\n data: string\n /**\n * How `data` is encoded. Absent on the wire means `png`: frames were\n * PNG-only before this field existed, so an older guest paired with a\n * newer host keeps working rather than having its every frame rejected.\n */\n format: DeskFrameFormat\n }\n | {\n event: 'video-chunk'\n seq: number\n kind: DeskVideoChunkKind\n /** RFC 6381, e.g. `avc1.42C020`, read out of the bytes by the guest. */\n codec: string\n width: number\n height: number\n /**\n * Whether a `media` chunk begins at a sync sample. Only a chunk that does\n * can start or resume a decoder; `init` chunks report false because the\n * question does not apply to them.\n */\n keyframe: boolean\n data: string\n }\n | { event: 'window-focus'; window: WindowInfo }\n\nexport type HostBoundMessage = GuestResponse | GuestEventMessage\n\n/** The wire shape of an exec result, before the host turns it into a snapshot. */\nexport interface GuestExecResult {\n exitCode: number | null\n signal: string | null\n stdout: string\n stderr: string\n truncated: boolean\n}\n\n/** The wire shape of an observation; `png` is base64. */\nexport interface GuestObservation {\n png: string\n width: number\n height: number\n a11y: A11yNode | null\n windows: WindowInfo[]\n focused: WindowInfo | null\n}\n\n/** Encode one message as a length-prefixed JSON frame. */\nexport function encodeFrame(message: unknown, maxFrameBytes = DEFAULT_MAX_FRAME_BYTES): Buffer {\n const body = Buffer.from(JSON.stringify(message), 'utf8')\n if (body.byteLength > maxFrameBytes) {\n throw new DeskProtocolError(\n `Refusing to encode a ${body.byteLength}-byte frame; the limit is ${maxFrameBytes}.`,\n )\n }\n const frame = Buffer.allocUnsafe(FRAME_HEADER_BYTES + body.byteLength)\n frame.writeUInt32BE(body.byteLength, 0)\n body.copy(frame, FRAME_HEADER_BYTES)\n return frame\n}\n\n/**\n * Incremental frame decoder. Feed it arbitrary chunk boundaries; it returns\n * every complete parsed JSON value. A declared frame length beyond the bound\n * or a body that is not valid JSON throws — framing violations are fatal to\n * the connection because there is no way to resynchronize a byte stream whose\n * lengths cannot be trusted.\n */\nexport class FrameDecoder {\n readonly #maxFrameBytes: number\n #buffered: Buffer = Buffer.alloc(0)\n\n constructor(options: { maxFrameBytes?: number } = {}) {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES\n if (!Number.isInteger(maxFrameBytes) || maxFrameBytes < 1) {\n throw new DeskProtocolError('maxFrameBytes must be a positive integer.')\n }\n this.#maxFrameBytes = maxFrameBytes\n }\n\n push(chunk: Buffer): unknown[] {\n this.#buffered = this.#buffered.byteLength === 0\n ? chunk\n : Buffer.concat([this.#buffered, chunk])\n const messages: unknown[] = []\n while (this.#buffered.byteLength >= FRAME_HEADER_BYTES) {\n const declared = this.#buffered.readUInt32BE(0)\n if (declared > this.#maxFrameBytes) {\n throw new DeskProtocolError(\n `Peer declared a ${declared}-byte frame; the limit is ${this.#maxFrameBytes}.`,\n )\n }\n if (this.#buffered.byteLength < FRAME_HEADER_BYTES + declared) break\n const body = this.#buffered.subarray(FRAME_HEADER_BYTES, FRAME_HEADER_BYTES + declared)\n this.#buffered = this.#buffered.subarray(FRAME_HEADER_BYTES + declared)\n try {\n messages.push(JSON.parse(body.toString('utf8')))\n } catch (error) {\n throw new DeskProtocolError(\n `Frame body is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n return messages\n }\n}\n\n/** Validate a host-to-guest request. Unknown ops and malformed fields throw. */\nexport function parseGuestRequest(value: unknown): GuestRequest {\n const record = asRecord(value, 'request')\n const id = requireString(record, 'id')\n if (!REQUEST_ID_PATTERN.test(id)) {\n throw new DeskProtocolError('Request id must be 1–128 URL-safe characters.')\n }\n const op = requireString(record, 'op')\n switch (op) {\n case 'ping':\n case 'capabilities':\n case 'screen-stop':\n case 'observe':\n case 'clipboard-read':\n case 'frames-stop':\n case 'video-stop':\n case 'handover-end':\n return { id, op }\n case 'exec':\n return {\n id,\n op,\n command: requireString(record, 'command'),\n args: optionalStringArray(record, 'args'),\n cwd: optionalString(record, 'cwd'),\n env: optionalEnvironment(record),\n timeoutMs: optionalPositiveInteger(record, 'timeoutMs'),\n }\n case 'job-start':\n return {\n id,\n op,\n command: requireString(record, 'command'),\n args: optionalStringArray(record, 'args'),\n cwd: optionalString(record, 'cwd'),\n env: optionalEnvironment(record),\n }\n case 'job-signal': {\n const signal = requireString(record, 'signal')\n if (signal !== 'SIGTERM' && signal !== 'SIGKILL') {\n throw new DeskProtocolError('job-signal signal must be SIGTERM or SIGKILL.')\n }\n return { id, op, jobId: requireString(record, 'jobId'), signal }\n }\n case 'screen-start':\n return {\n id,\n op,\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n }\n case 'input':\n return { id, op, input: parseGuestInput(record.input) }\n case 'a11y-invoke':\n return {\n id,\n op,\n nodeId: requireString(record, 'nodeId'),\n action: requireString(record, 'action'),\n }\n case 'launch':\n return {\n id,\n op,\n appId: requireString(record, 'appId'),\n args: optionalStringArray(record, 'args'),\n }\n case 'clipboard-write':\n return { id, op, text: requireString(record, 'text') }\n case 'frames-start':\n return {\n id,\n op,\n fps: requirePositiveInteger(record, 'fps'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n format: optionalFrameFormat(record),\n }\n case 'video-start':\n return {\n id,\n op,\n fps: requirePositiveInteger(record, 'fps'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n }\n case 'handover-begin':\n return {\n id,\n op,\n ttlMs: requirePositiveInteger(record, 'ttlMs'),\n scope: parseHandoverScope(record.scope),\n }\n default:\n throw new DeskProtocolError(`Unknown request op: ${op}`)\n }\n}\n\nexport function parseGuestInput(value: unknown): GuestInput {\n const record = asRecord(value, 'input')\n const type = requireString(record, 'type')\n switch (type) {\n case 'move':\n return { type, x: requireCoordinate(record, 'x'), y: requireCoordinate(record, 'y') }\n case 'click':\n return {\n type,\n x: requireCoordinate(record, 'x'),\n y: requireCoordinate(record, 'y'),\n button: parsePointerButton(record.button),\n clicks: parseClickCount(record.clicks),\n }\n case 'type':\n return { type, text: requireString(record, 'text') }\n case 'key':\n return { type, combo: requireString(record, 'combo') }\n case 'scroll':\n return {\n type,\n x: requireCoordinate(record, 'x'),\n y: requireCoordinate(record, 'y'),\n dx: requireDelta(record, 'dx'),\n dy: requireDelta(record, 'dy'),\n }\n case 'drag':\n return { type, from: parsePoint(record.from), to: parsePoint(record.to) }\n default:\n throw new DeskProtocolError(`Unknown input type: ${type}`)\n }\n}\n\nfunction parseClickCount(value: unknown): 1 | 2 {\n if (value === undefined || value === 1) return 1\n if (value === 2) return 2\n throw new DeskProtocolError('clicks must be 1 or 2.')\n}\n\n/** Validate a guest-to-host message: a correlated response or an event. */\nexport function parseHostBoundMessage(value: unknown): HostBoundMessage {\n const record = asRecord(value, 'message')\n if ('id' in record) {\n const id = requireString(record, 'id')\n if (record.ok === true) return { id, ok: true, result: record.result ?? {} }\n if (record.ok === false) return { id, ok: false, error: requireString(record, 'error') }\n throw new DeskProtocolError('Response ok must be a boolean.')\n }\n const event = requireString(record, 'event')\n switch (event) {\n case 'job-exit':\n return {\n event,\n jobId: requireString(record, 'jobId'),\n exitCode: nullableInteger(record, 'exitCode'),\n signal: nullableString(record, 'signal'),\n }\n case 'frame':\n return {\n event,\n seq: requireNonNegativeInteger(record, 'seq'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n data: requireUnboundedString(record, 'data'),\n // Absent means png — see the field's contract on GuestEventMessage.\n format: optionalFrameFormat(record) ?? 'png',\n }\n case 'video-chunk':\n return {\n event,\n seq: requireNonNegativeInteger(record, 'seq'),\n kind: parseVideoChunkKind(record.kind),\n codec: requireString(record, 'codec'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n keyframe: record.keyframe === true,\n data: requireUnboundedString(record, 'data'),\n }\n case 'window-focus':\n return { event, window: parseWindowInfo(record.window) }\n default:\n throw new DeskProtocolError(`Unknown event: ${event}`)\n }\n}\n\n/** Validate the result payload of an `exec` response. */\nexport function parseExecResult(value: unknown): GuestExecResult {\n const record = asRecord(value, 'exec result')\n return {\n exitCode: nullableInteger(record, 'exitCode'),\n signal: nullableString(record, 'signal'),\n stdout: requireUnboundedString(record, 'stdout'),\n stderr: requireUnboundedString(record, 'stderr'),\n truncated: record.truncated === true,\n }\n}\n\n/** Validate the result payload of a `job-start` response. */\nexport function parseJobStarted(value: unknown): { jobId: string } {\n const record = asRecord(value, 'job-start result')\n return { jobId: requireString(record, 'jobId') }\n}\n\n/** Validate the result payload of an `observe` response. */\nexport function parseObservation(value: unknown): GuestObservation {\n const record = asRecord(value, 'observation')\n const windows = parseWindows(record.windows)\n return {\n png: requireUnboundedString(record, 'png'),\n width: requireDimension(record, 'width'),\n height: requireDimension(record, 'height'),\n a11y: record.a11y === null || record.a11y === undefined\n ? null\n : parseA11yTree(record.a11y),\n windows,\n focused: record.focused === null || record.focused === undefined\n ? null\n : parseWindowInfo(record.focused),\n }\n}\n\n/** Validate the result payload of a `handover-begin` response. */\nexport function parseHandoverBegun(value: unknown): { url: string } {\n const record = asRecord(value, 'handover-begin result')\n return { url: requireString(record, 'url') }\n}\n\n/** Validate the result payload of a `clipboard-read` response. */\nexport function parseClipboardText(value: unknown): string {\n const record = asRecord(value, 'clipboard-read result')\n return requireUnboundedString(record, 'text')\n}\n\n/** Validate the result payload of a `capabilities` response. */\nexport function parseCapabilities(value: unknown): { virtioGpu: boolean } {\n const record = asRecord(value, 'capabilities result')\n return { virtioGpu: record.virtioGpu === true }\n}\n\nexport function parseWindowInfo(value: unknown): WindowInfo {\n const record = asRecord(value, 'window')\n return {\n id: requireString(record, 'id'),\n title: requireString(record, 'title'),\n appId: nullableString(record, 'appId'),\n }\n}\n\nfunction parseWindows(value: unknown): WindowInfo[] {\n if (value === undefined || value === null) return []\n if (!Array.isArray(value) || value.length > MAX_WINDOWS) {\n throw new DeskProtocolError(`windows must be an array of at most ${MAX_WINDOWS} entries.`)\n }\n return value.map(parseWindowInfo)\n}\n\nfunction parseA11yTree(value: unknown): A11yNode {\n const budget = { remaining: MAX_A11Y_NODES }\n return parseA11yNode(value, budget, 0)\n}\n\nfunction parseA11yNode(value: unknown, budget: { remaining: number }, depth: number): A11yNode {\n if (depth > MAX_A11Y_DEPTH) {\n throw new DeskProtocolError(`Accessibility tree exceeds depth ${MAX_A11Y_DEPTH}.`)\n }\n if (budget.remaining <= 0) {\n throw new DeskProtocolError(`Accessibility tree exceeds ${MAX_A11Y_NODES} nodes.`)\n }\n budget.remaining -= 1\n const record = asRecord(value, 'a11y node')\n const rawChildren = record.children ?? []\n if (!Array.isArray(rawChildren)) {\n throw new DeskProtocolError('a11y node children must be an array.')\n }\n return {\n id: requireString(record, 'id'),\n role: requireString(record, 'role'),\n name: nullableString(record, 'name'),\n actions: optionalStringArray(record, 'actions') ?? [],\n bounds: record.bounds === null || record.bounds === undefined\n ? null\n : parseBounds(record.bounds),\n children: rawChildren.map((child) => parseA11yNode(child, budget, depth + 1)),\n }\n}\n\nfunction parseBounds(value: unknown): { x: number; y: number; width: number; height: number } {\n const record = asRecord(value, 'bounds')\n return {\n x: requireDelta(record, 'x'),\n y: requireDelta(record, 'y'),\n width: requireNonNegativeInteger(record, 'width'),\n height: requireNonNegativeInteger(record, 'height'),\n }\n}\n\nfunction parsePoint(value: unknown): DeskPoint {\n const record = asRecord(value, 'point')\n return { x: requireCoordinate(record, 'x'), y: requireCoordinate(record, 'y') }\n}\n\nfunction parsePointerButton(value: unknown): DeskPointerButton {\n if (value === undefined) return 'left'\n if (value === 'left' || value === 'middle' || value === 'right') return value\n throw new DeskProtocolError('button must be left, middle, or right.')\n}\n\n/**\n * A frame format, when the field is present. Absent is `undefined` here and\n * every caller decides what that means; on a frame event it means `png`,\n * because that is what the field's absence used to imply.\n */\nfunction optionalFrameFormat(record: Record<string, unknown>): DeskFrameFormat | undefined {\n const value = record.format\n if (value === undefined) return undefined\n if (value === 'png' || value === 'jpeg') return value\n throw new DeskProtocolError('format must be png or jpeg.')\n}\n\nfunction parseVideoChunkKind(value: unknown): DeskVideoChunkKind {\n if (value === 'init' || value === 'media') return value\n throw new DeskProtocolError('video chunk kind must be init or media.')\n}\n\nfunction parseHandoverScope(value: unknown): DeskHandoverScope {\n if (value === 'view' || value === 'control') return value\n throw new DeskProtocolError('scope must be view or control.')\n}\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new DeskProtocolError(`Expected ${label} to be an object.`)\n }\n return value as Record<string, unknown>\n}\n\nfunction requireString(record: Record<string, unknown>, field: string): string {\n const value = record[field]\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(\n `${field} must be a string of 1–${MAX_STRING_LENGTH} characters.`,\n )\n }\n return value\n}\n\nfunction requireUnboundedString(record: Record<string, unknown>, field: string): string {\n // Bounded by the frame limit rather than the field limit; used for payloads\n // such as command output, screenshots, and clipboard text.\n const value = record[field]\n if (typeof value !== 'string') {\n throw new DeskProtocolError(`${field} must be a string.`)\n }\n return value\n}\n\nfunction optionalString(record: Record<string, unknown>, field: string): string | undefined {\n return record[field] === undefined ? undefined : requireString(record, field)\n}\n\nfunction nullableString(record: Record<string, unknown>, field: string): string | null {\n const value = record[field]\n if (value === null || value === undefined) return null\n return requireString(record, field)\n}\n\nfunction optionalStringArray(\n record: Record<string, unknown>,\n field: string,\n): string[] | undefined {\n const value = record[field]\n if (value === undefined) return undefined\n if (!Array.isArray(value) || value.length > MAX_ARGUMENTS) {\n throw new DeskProtocolError(`${field} must be an array of at most ${MAX_ARGUMENTS} strings.`)\n }\n return value.map((entry, index) => {\n if (typeof entry !== 'string' || entry.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(`${field}[${index}] must be a string of at most ${MAX_STRING_LENGTH} characters.`)\n }\n return entry\n })\n}\n\nfunction optionalEnvironment(\n record: Record<string, unknown>,\n): Record<string, string> | undefined {\n const value = record.env\n if (value === undefined) return undefined\n const env = asRecord(value, 'env')\n const entries = Object.entries(env)\n if (entries.length > MAX_ENVIRONMENT_ENTRIES) {\n throw new DeskProtocolError(`env must have at most ${MAX_ENVIRONMENT_ENTRIES} entries.`)\n }\n const clean: Record<string, string> = {}\n for (const [key, entry] of entries) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n throw new DeskProtocolError(`Invalid environment variable name: ${key}`)\n }\n if (typeof entry !== 'string' || entry.length > MAX_STRING_LENGTH) {\n throw new DeskProtocolError(`env.${key} must be a string of at most ${MAX_STRING_LENGTH} characters.`)\n }\n clean[key] = entry\n }\n return clean\n}\n\nfunction requirePositiveInteger(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 1) {\n throw new DeskProtocolError(`${field} must be a positive integer.`)\n }\n return value\n}\n\nfunction optionalPositiveInteger(\n record: Record<string, unknown>,\n field: string,\n): number | undefined {\n return record[field] === undefined ? undefined : requirePositiveInteger(record, field)\n}\n\nfunction requireNonNegativeInteger(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new DeskProtocolError(`${field} must be a non-negative integer.`)\n }\n return value\n}\n\nfunction requireDimension(record: Record<string, unknown>, field: string): number {\n const value = requirePositiveInteger(record, field)\n if (value > 16_384) {\n throw new DeskProtocolError(`${field} must be at most 16384 pixels.`)\n }\n return value\n}\n\nfunction requireCoordinate(record: Record<string, unknown>, field: string): number {\n return requireNonNegativeInteger(record, field)\n}\n\nfunction requireDelta(record: Record<string, unknown>, field: string): number {\n const value = record[field]\n if (typeof value !== 'number' || !Number.isInteger(value)) {\n throw new DeskProtocolError(`${field} must be an integer.`)\n }\n return value\n}\n\nfunction nullableInteger(record: Record<string, unknown>, field: string): number | null {\n const value = record[field]\n if (value === null || value === undefined) return null\n if (typeof value !== 'number' || !Number.isInteger(value)) {\n throw new DeskProtocolError(`${field} must be an integer or null.`)\n }\n return value\n}\n"]}