@agimon-ai/po-core 0.0.0-alpha.63 → 0.0.0-alpha.65

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.
@@ -641,7 +641,8 @@ async function serveHeadlessServer(options) {
641
641
  return;
642
642
  }
643
643
  if (url.pathname === "/api/compositions" && request.method === "GET") {
644
- json(response, 200, await options.compositions?.() ?? { workspaces: [] });
644
+ const nativeClient = url.searchParams.get("client") === "native";
645
+ json(response, 200, await options.compositions?.({ nativeClient }) ?? { workspaces: [] });
645
646
  return;
646
647
  }
647
648
  if ((url.pathname.startsWith("/api/web-plugins/") || url.pathname === "/bundle-manifest.json" || url.pathname.startsWith("/bundle-assets/")) && options.requestAsset) {
@@ -1 +1 @@
1
- {"version":3,"file":"headlessServer.cjs","names":["PO_API_CALLER_HEADERS","createHash","timingSafeEqual","os","path","fs","Readable","pipeline","WebSocketServer","harnessErrorMessage","createHeadlessProtocol","createSessionMcpRoutes","createSessionMcpActivityStore","createSessionMcpConversationStore","createSessionMcpRegistrationStore","createServer","isPoSessionSetupError","isPublicSessionMcpRoute","isSessionMcpHostRoute","normalizeSessionGroups","createContextApi","readContextDetail","PO_API_CALLER_LOCALITY_HEADER","PO_API_CALLER_STEP_UP_HEADER","contentClass","BACKGROUND_CONTEXT","SESSION_FILES_API","writeSessionAttachment","parsePoSocketPath","webSocketLink"],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import { createHash, timingSafeEqual } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { type Duplex, Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nimport { webSocketLink, type Context, type Link, type WebSocketLike } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { WebSocket } from 'ws';\nimport { WebSocketServer } from 'ws';\n\nimport { API_BASE_PATH as CONTEXT_API_BASE_PATH } from '../constants/contextApi';\nimport { SESSION_FILES_API } from '../constants/sessionFiles';\nimport {\n PO_API_CALLER_HEADERS,\n PO_API_CALLER_LOCALITY_HEADER,\n PO_API_CALLER_STEP_UP_HEADER,\n parsePoSocketPath,\n type PoApiHandler,\n type PoApiMount,\n type PoApiPublicRoutes,\n type PoApiSocket,\n} from '../exports/packageApi';\nimport type { TranscriptPage, TranscriptPageRequest } from '../exports/sessionProtocol';\nimport { isPoSessionSetupError } from '../schemas/headless';\nimport type { PoHubSessionReservations } from '../schemas/hubChannel';\nimport { normalizeSessionGroups } from '../schemas/sessionProtocol';\nimport { readContextDetail } from '../services/contextDetailStore';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport { observe, type ServerTelemetry } from '../services/serverTelemetry';\nimport { writeSessionAttachment } from '../services/sessionAttachments';\nimport { createSessionMcpActivityStore } from '../services/sessionMcpActivity';\nimport { createSessionMcpConversationStore } from '../services/sessionMcpConversations';\nimport { createSessionMcpRegistrationStore } from '../services/sessionMcpRegistrationStore';\nimport type { RemovedSession, SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspace, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\nimport { contentClass } from './packageApiServer';\nimport { createSessionMcpRoutes, isPublicSessionMcpRoute, isSessionMcpHostRoute } from './sessionMcpRoutes';\n\n/**\n * The canonical public shape of a package API request, as dispatch reads it.\n *\n * Groups: workspace id, session id, plugin base path, and the remainder handed\n * to the package. `settings` is the host's own API and sits beside `plugins`\n * rather than under it.\n *\n * Exported so the browser's URL construction can be pinned against it. The two\n * are written independently, in halves of this package that may not import each\n * other, and a disagreement between them is not a 404 from the route: the\n * service worker answers an unrecognised path out of the signed bundle cache,\n * so the symptom appears nowhere near the cause.\n */\nexport const PO_PACKAGE_API_PATH_PATTERN =\n /^\\/api(?:\\/workspaces\\/([^/]+)(?:\\/sessions\\/([^/]+))?)?\\/(?:plugins\\/([^/]+)|settings)(?:\\/(.*))?$/u;\n\nconst HEALTH_ROLE = 'hub';\nconst PROTOCOL_VERSION = 1;\nconst MAX_BODY_BYTES = 8 * 1024 * 1024;\n/** Body and WebSocket frame cap for package public routes. */\nconst PUBLIC_MAX_BYTES = 1024 * 1024;\nconst PUBLIC_PLUGIN_PATH = /^\\/api\\/plugins\\/([^/]+)(\\/.*)?$/u;\nconst LOOPBACK_HOST = /^(?:127\\.0\\.0\\.1|localhost|\\[::1\\])(?::\\d+)?$/iu;\nconst LOOPBACK_PEERS = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);\nconst EXTENSION_ORIGIN_PREFIX = 'chrome-extension://';\n/**\n * Headers that mark a forwarded request. The remote runtime's forward always attaches the host token\n * and sealed requests carry caller stamps, so a public route answers any of these with 404.\n */\nconst FORWARDED_MARKERS = [\n 'x-po-token',\n ...PO_API_CALLER_HEADERS,\n 'forwarded',\n 'x-forwarded-for',\n 'x-forwarded-host',\n 'cf-connecting-ip',\n 'cf-ray',\n];\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\nconst WORKSPACE_INSTRUCTIONS_MAX_LENGTH = 100_000;\nconst WORKSPACE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9 ._-]*$/u;\n/** Restart closes the session host, which aborts a running turn, so it waits for idle. */\nexport const RESTART_WHILE_RUNNING_ERROR =\n 'The session is running a turn. Stop it or wait for it to finish before reloading extensions.';\n\nexport interface HeadlessServerOptions {\n headlessHub: HeadlessHub;\n port: number;\n host?: string;\n /** Requests other than health require this bearer token when set. */\n token?: string;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n compositions?: () => unknown;\n requestAsset?: (request: Request) => Promise<Response | undefined>;\n /** Independently authenticated by the destination federation boundary. */\n requestNetwork?: (request: Request) => Promise<Response | undefined>;\n acceptNetworkRelay?: (socket: PoApiSocket, url: URL) => Promise<void>;\n sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<string>;\n /** Sessions removed from a workspace's History that can still be restored, newest first. */\n removedSessions?: (workspaceId: string) => Promise<RemovedSession[]>;\n /** Returns a removed session to History; false once it is being deleted or is already gone. */\n restoreRemovedSession?: (workspaceId: string, sessionId: string) => Promise<boolean>;\n /**\n * Sets (a provider id) or clears (`null`) the sandbox provider of a workspace and re-registers it. The\n * change applies to new sessions only; sessions already running on the host are left alone.\n * Answers `{ error }` when the host refuses, for example for a provider id it does not know.\n */\n setWorkspaceSandbox?: (\n workspaceId: string,\n sandbox: string | null,\n ) => Promise<{ workspace: HeadlessWorkspace } | { error: string }>;\n declaredWorkspaces?: (path: string) => Promise<{\n root: string;\n declarations: { name: string; instructions?: string; workspaceId?: string }[];\n }>;\n setWorkspaceInstructions?: (\n workspaceId: string,\n instructions: string,\n ) => Promise<{ workspace: HeadlessWorkspace } | { error: string }>;\n readDormantTranscript?: (\n record: OpenSessionRecord,\n request: TranscriptPageRequest,\n context: Context,\n ) => Promise<TranscriptPage>;\n restartSession?: (session: HeadlessHubSession) => Promise<void>;\n resumeSession?: (session: HeadlessHubSession, targetSessionId: string) => Promise<string>;\n /** Recorded sessions this server has not reopened, surfaced so a client can ask for one. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n removeDormantSession?: (record: OpenSessionRecord) => void | Promise<void>;\n /** Explicit Remove only, after live work stops. The host cleans output and removes the open-session record. */\n removeSessionFiles?: (sessionId: string) => Promise<void>;\n /** Stores new groups on a dormant session's record; a revived session adopts them. */\n setDormantGroups?: (record: OpenSessionRecord, groups: readonly string[]) => void | Promise<void>;\n reviveSession?: (record: OpenSessionRecord) => Promise<void>;\n /** Trusted HTTPS origin advertised for public session MCP and OAuth endpoints. */\n sessionMcpPublicOrigin?: () => string | undefined;\n /** Durable state directory for verified Session MCP clients. */\n sessionMcpStateDir?: string;\n /** Monotonic exposure revision, including disable/re-enable cycles. */\n sessionMcpPublicOriginRevision?: () => number;\n isSessionPersisted?: (sessionId: string, cwd: string) => boolean;\n /**\n * False serves no public route: neither a global API's declared public paths nor the public session MCP\n * endpoints, so every request but health needs the token. A contained server passes false. Default true.\n */\n publicRoutes?: boolean;\n /** Largest protocol WebSocket message accepted, in bytes. Defaults to the ws library's limit. */\n webSocketMaxPayload?: number;\n}\n\nexport interface HeadlessServer {\n readonly url: string;\n readonly sessionReservations: PoHubSessionReservations;\n /** Hands an in-process link (a relayed device) to the protocol as if it had upgraded at `pathname`. */\n acceptProtocol(pathname: string, link: Link, headers: IncomingHttpHeaders): boolean;\n close(): Promise<void>;\n}\n\ntype Client = { socket: WebSocket };\n\nfunction sessionView(session: HeadlessHubSession): Record<string, unknown> {\n return {\n id: session.id,\n workspaceId: session.workspaceId,\n webComposition: session.webComposition,\n nativeComposition: session.nativeComposition,\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n ...(session.backgroundWorkActive === undefined ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { ...session.git } }),\n ...(session.profile === undefined ? {} : { profile: { ...session.profile } }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): Record<string, unknown> {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'detached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\nfunction json(response: ServerResponse, status: number, value: unknown): void {\n const body = JSON.stringify(value);\n response.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'content-length': Buffer.byteLength(body),\n });\n response.end(body);\n}\n\nconst tokenDigest = (value: string): Buffer => createHash('sha256').update(value).digest();\n\n/** Compares fixed-length digests, so neither the length nor the content of the token leaks through timing. */\nfunction tokenMatches(candidate: string | null | undefined, token: string): boolean {\n return typeof candidate === 'string' && timingSafeEqual(tokenDigest(candidate), tokenDigest(token));\n}\n\nfunction authorized(request: IncomingMessage, token: string | undefined): boolean {\n if (token === undefined) return true;\n const authorization = request.headers.authorization;\n if (authorization?.startsWith('Bearer ') && tokenMatches(authorization.slice('Bearer '.length), token)) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && tokenMatches(header, token)) return true;\n try {\n return tokenMatches(new URL(request.url ?? '/', 'http://po.local').searchParams.get('token'), token);\n } catch {\n return false;\n }\n}\n\n/** Why a public route refuses a request before authentication: 404 when forwarded, 403 when not local. */\nfunction publicRefusal(request: IncomingMessage): 403 | 404 | undefined {\n if (FORWARDED_MARKERS.some((name) => request.headers[name] !== undefined)) return 404;\n const origin = request.headers.origin;\n if (\n !LOOPBACK_HOST.test(request.headers.host ?? '') ||\n !LOOPBACK_PEERS.has(request.socket.remoteAddress ?? '') ||\n (origin !== undefined && !origin.startsWith(EXTENSION_ORIGIN_PREFIX))\n )\n return 403;\n return undefined;\n}\n\n/** Headers a public route sees: never Host, and never the host token or caller stamps. */\nfunction publicHeaders(request: IncomingMessage, token: string | undefined): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value === undefined || name === 'host') continue;\n const joined = Array.isArray(value) ? value.join(', ') : value;\n if (\n name === 'authorization' &&\n token !== undefined &&\n joined.startsWith('Bearer ') &&\n tokenMatches(joined.slice('Bearer '.length), token)\n )\n continue;\n headers.set(name, joined);\n }\n return headers;\n}\n\n/** Adapts an accepted `ws` socket. Its default binary type delivers every frame as one Buffer. */\nfunction apiSocket(client: WebSocket): PoApiSocket {\n return {\n get isOpen() {\n return client.readyState === client.OPEN;\n },\n send: (data) => client.send(data),\n close: (code, reason) => client.close(code, reason),\n onMessage: (listener) => {\n client.on('message', (data, isBinary) => {\n const bytes = data as Buffer;\n listener(isBinary ? bytes : bytes.toString('utf8'));\n });\n },\n onClose: (listener) => {\n client.on('close', (code, reason) => listener(code, reason.toString('utf8')));\n },\n };\n}\n\nfunction requestPath(request: IncomingMessage): URL {\n return new URL(request.url ?? '/', 'http://po.local');\n}\n\nfunction parseTranscriptRequest(url: URL): TranscriptPageRequest {\n const request: TranscriptPageRequest = {};\n const cursor = url.searchParams.get('cursor');\n const direction = url.searchParams.get('direction');\n const limit = url.searchParams.get('limit');\n if (cursor !== null) request.cursor = cursor;\n if (direction !== null) {\n if (direction !== 'older' && direction !== 'newer') throw new Error('Invalid transcript direction');\n request.direction = direction;\n }\n if (limit !== null) {\n if (!/^\\d+$/u.test(limit)) throw new Error('Invalid transcript page limit');\n const parsed = Number(limit);\n if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 100) throw new Error('Invalid transcript page limit');\n request.limit = parsed;\n }\n const entry = url.searchParams.get('entry');\n if (entry !== null) request.entryId = entry;\n return request;\n}\n\n/** Expands a leading `~` the way a shell would, so typed paths match what the user sees in a terminal. */\nfunction expandHome(value: string): string {\n if (value === HOME_PREFIX) return os.homedir();\n return value.startsWith(`${HOME_PREFIX}${path.sep}`) ? path.join(os.homedir(), value.slice(2)) : value;\n}\n\n/**\n * Validates an add-workspace request. A name alone asks for a new default folder,\n * so it must be safe to use as one folder name.\n */\nfunction parseWorkspaceAdmission(body: unknown): HeadlessWorkspaceAdmission | { error: string } {\n if (typeof body !== 'object' || body === null) return { error: 'A workspace root or name is required.' };\n const record = body as Record<string, unknown>;\n if (record.root !== undefined && typeof record.root !== 'string')\n return { error: 'The workspace root must be text.' };\n if (record.name !== undefined && typeof record.name !== 'string')\n return { error: 'The workspace name must be text.' };\n if (record.declaration !== undefined && typeof record.declaration !== 'string')\n return { error: 'The workspace declaration must be text.' };\n if (\n record.instructions !== undefined &&\n (typeof record.instructions !== 'string' || record.instructions.length > WORKSPACE_INSTRUCTIONS_MAX_LENGTH)\n )\n return {\n error: `Workspace instructions must be text up to ${String(WORKSPACE_INSTRUCTIONS_MAX_LENGTH)} characters.`,\n };\n const declaration = typeof record.declaration === 'string' ? record.declaration.trim() : undefined;\n const root =\n typeof record.root === 'string' && record.root.trim() !== '' ? expandHome(record.root.trim()) : undefined;\n const name = typeof record.name === 'string' && record.name.trim() !== '' ? record.name.trim() : undefined;\n if (root === undefined && name === undefined) return { error: 'A workspace root or name is required.' };\n if (root !== undefined && !path.isAbsolute(root))\n return { error: `Use a full folder path, such as ~/${root}, or pick a suggestion.` };\n if (\n [name, declaration].some(\n (value) =>\n value !== undefined &&\n (value.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(value) || value.includes('..')),\n )\n )\n return {\n error: `Workspace names use letters, numbers, spaces, dots, dashes, or underscores (up to ${String(WORKSPACE_NAME_MAX_LENGTH)} characters).`,\n };\n return {\n ...(root === undefined ? {} : { root }),\n ...(name === undefined ? {} : { name }),\n ...(declaration === undefined ? {} : { declaration }),\n ...(typeof record.instructions === 'string' ? { instructions: record.instructions } : {}),\n };\n}\n\nasync function directorySuggestions(query: string, sessions: readonly HeadlessHubSession[]): Promise<string[]> {\n const typed = expandHome(query.trim());\n if (typed === '') return [];\n const matches = (value: string): boolean => value.toLowerCase().includes(typed.toLowerCase());\n const known = [...new Set([process.cwd(), ...sessions.map((session) => session.cwd)])].filter(matches);\n const candidates = path.isAbsolute(typed)\n ? [typed]\n : typed.includes(path.sep)\n ? [path.resolve(process.cwd(), typed)]\n : [path.join(path.dirname(process.cwd()), typed), path.join(process.cwd(), typed)];\n const completed: string[] = [];\n for (const candidate of candidates) {\n const drilling = typed.endsWith(path.sep);\n const parent = drilling ? candidate : path.dirname(candidate);\n const partial = drilling ? '' : path.basename(candidate).toLowerCase();\n try {\n const entries = await fs.readdir(parent, { withFileTypes: true });\n completed.push(\n ...entries\n .filter((entry) => entry.isDirectory() && entry.name.toLowerCase().includes(partial))\n .map((entry) => path.join(parent, entry.name)),\n );\n } catch {\n // A missing or unreadable parent simply has no completions.\n }\n }\n return [...new Set([...known, ...completed.sort((left, right) => left.localeCompare(right))])].slice(\n 0,\n DIRECTORY_SUGGESTION_LIMIT,\n );\n}\n\n/**\n * Lists the visible child directories of one folder for the workspace folder browser.\n * Resolves undefined for a relative, missing, or unreadable path.\n */\nasync function directoryChildren(\n requested: string | null,\n): Promise<{ path: string; parent?: string; directories: string[] } | undefined> {\n const directory = requested === null || requested.trim() === '' ? os.homedir() : expandHome(requested.trim());\n if (!path.isAbsolute(directory)) return undefined;\n const resolved = path.resolve(directory);\n let entries: Dirent[];\n try {\n entries = await fs.readdir(resolved, { withFileTypes: true });\n } catch {\n return undefined;\n }\n const directories = entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))\n .map((entry) => path.join(resolved, entry.name))\n .sort((left, right) => left.localeCompare(right))\n .slice(0, DIRECTORY_CHILDREN_LIMIT);\n const parent = path.dirname(resolved);\n return { path: resolved, ...(parent === resolved ? {} : { parent }), directories };\n}\n\nconst PO_FOLDER_SCAN_DEPTH = 3;\nconst PO_FOLDER_SCAN_VISIT_LIMIT = 2000;\nconst PO_FOLDER_LIMIT = 20;\nconst PO_FOLDER_SKIP = new Set(['node_modules', 'Library']);\n\n/**\n * Folders under home that already hold a `.po` folder, for first-run onboarding.\n * Home itself is skipped: its `.po` is Po's own home, not a workspace.\n */\nasync function poFolders(): Promise<string[]> {\n // ponytail: a bounded breadth-first walk (depth, visits, results); a deeper or\n // indexed search can replace it if people keep projects further down.\n const found: string[] = [];\n let level = [os.homedir()];\n let visited = 0;\n for (let depth = 1; depth <= PO_FOLDER_SCAN_DEPTH && level.length > 0; depth++) {\n const next: string[] = [];\n for (const parent of level) {\n if (visited++ >= PO_FOLDER_SCAN_VISIT_LIMIT || found.length >= PO_FOLDER_LIMIT) return found;\n let entries: Dirent[];\n try {\n entries = await fs.readdir(parent, { withFileTypes: true });\n } catch {\n continue; // An unreadable folder simply has nothing to offer.\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || PO_FOLDER_SKIP.has(entry.name)) continue;\n const child = path.join(parent, entry.name);\n if (\n await fs.access(path.join(child, '.po')).then(\n () => true,\n () => false,\n )\n )\n found.push(child);\n else next.push(child);\n }\n }\n level = next;\n }\n return found.slice(0, PO_FOLDER_LIMIT);\n}\n\nclass RequestBodyTooLargeError extends Error {\n constructor() {\n super('Request body is too large.');\n }\n}\n\nasync function readBody(request: IncomingMessage, limit = MAX_BODY_BYTES): Promise<Uint8Array> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.byteLength;\n if (size > limit) throw new RequestBodyTooLargeError();\n chunks.push(buffer);\n }\n return Buffer.concat(chunks);\n}\n\nfunction parseJson(body: Uint8Array): unknown {\n if (body.byteLength === 0) return {};\n return JSON.parse(Buffer.from(body).toString('utf8')) as unknown;\n}\n\nfunction webRequest(request: IncomingMessage, url: URL, signal?: AbortSignal): Request {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n return new Request(url, {\n method: request.method,\n headers,\n signal,\n ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : {\n body: Readable.toWeb(request) as never,\n duplex: 'half' as const,\n }),\n });\n}\n\nasync function writeResponse(\n response: ServerResponse,\n result: Response,\n onChunk?: (bytes: number) => void,\n): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n const body = Readable.fromWeb(result.body as import('node:stream/web').ReadableStream);\n if (onChunk === undefined) {\n await pipeline(body, response);\n return;\n }\n await pipeline(\n body,\n async function* (chunks: AsyncIterable<Uint8Array>) {\n for await (const chunk of chunks) {\n onChunk(chunk.byteLength);\n yield chunk;\n }\n },\n response,\n );\n}\n\n/**\n * Client-neutral HTTP and WebSocket boundary for the process-local headless hub.\n * It deliberately delegates every session operation to HeadlessHub, so transport\n * clients cannot create a second session backend or bypass its lifecycle.\n */\nexport async function serveHeadlessServer(options: HeadlessServerOptions): Promise<HeadlessServer> {\n const clients = new Set<Client>();\n const desktopAuthorized = (request: IncomingMessage): boolean => {\n const proof = request.headers['x-po-desktop'];\n return (\n typeof proof === 'string' &&\n options.headlessHub.computerUse?.authorize?.(new Headers({ 'x-po-desktop': proof })) === true\n );\n };\n const computerUseAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (desktopAuthorized(request)) return true;\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeSession?.(sessionId, headers) === true;\n };\n const activationAuthorized = (request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeActivation?.(headers) === true;\n };\n const pendingAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizePending?.(sessionId, headers) === true;\n };\n const recordingAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeRecording?.(sessionId, headers) === true;\n };\n let closed = false;\n const webSockets = new WebSocketServer({\n noServer: true,\n ...(options.webSocketMaxPayload === undefined ? {} : { maxPayload: options.webSocketMaxPayload }),\n });\n const publicRoutes = options.publicRoutes !== false;\n const publicSockets = new WebSocketServer({ noServer: true, maxPayload: PUBLIC_MAX_BYTES });\n type PublicRoute = { path: string; routes: PoApiPublicRoutes; handler: PoApiHandler };\n /** A declared public route of a global API; every other plugin path keeps the host token. */\n const publicRouteFor = (url: URL): PublicRoute | undefined => {\n if (!publicRoutes) return undefined;\n const match = PUBLIC_PLUGIN_PATH.exec(url.pathname);\n if (match === null) return undefined;\n let basePath: string;\n try {\n basePath = decodeURIComponent(match[1]);\n } catch {\n return undefined;\n }\n const api = options.headlessHub.publicApi(basePath);\n const routePath = match[2] ?? '/';\n const declared = api?.routes.paths.some(\n (prefix) => routePath === prefix || routePath.startsWith(prefix.endsWith('/') ? prefix : `${prefix}/`),\n );\n return api === undefined || declared !== true ? undefined : { path: routePath, ...api };\n };\n /** The request a public route sees, without the host's own `token` query parameter. */\n const publicRequest = (request: IncomingMessage, url: URL, route: PublicRoute, body?: Uint8Array): Request => {\n const target = new URL(`http://po.local${route.path}${url.search}`);\n target.searchParams.delete('token');\n return new Request(target, {\n method: request.method,\n headers: publicHeaders(request, options.token),\n ...(body === undefined ? {} : { body: Buffer.from(body) }),\n });\n };\n const servePublicRoute = async (\n request: IncomingMessage,\n response: ServerResponse,\n url: URL,\n route: PublicRoute,\n ): Promise<void> => {\n const refusal = publicRefusal(request);\n if (refusal !== undefined) {\n json(response, refusal, { error: refusal === 404 ? 'Not found.' : 'Forbidden.' });\n return;\n }\n let body: Uint8Array | undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await readBody(request, PUBLIC_MAX_BYTES);\n } catch (error) {\n if (!(error instanceof RequestBodyTooLargeError)) throw error;\n json(response, 413, { error: error.message });\n return;\n }\n }\n const forwarded = publicRequest(request, url, route, body);\n if (!(await route.routes.authenticate(forwarded.clone()))) {\n json(response, 401, { error: 'Unauthorized.' });\n return;\n }\n await writeResponse(response, await route.handler.fetch(forwarded));\n };\n const upgradePublicRoute = async (\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n route: PublicRoute,\n ): Promise<void> => {\n const refuse = (status: string): void => {\n socket.write(`HTTP/1.1 ${status}\\r\\n\\r\\n`);\n socket.destroy();\n };\n const refusal = publicRefusal(request);\n const upgrade = route.handler.upgrade?.bind(route.handler);\n if (refusal === 404 || upgrade === undefined) return refuse('404 Not Found');\n if (refusal === 403) return refuse('403 Forbidden');\n const forwarded = publicRequest(request, requestPath(request), route);\n if (!(await route.routes.authenticate(forwarded.clone()))) return refuse('401 Unauthorized');\n if (closed || socket.destroyed) {\n socket.destroy();\n return;\n }\n publicSockets.handleUpgrade(request, socket, head, (client) => {\n const entry: Client = { socket: client };\n clients.add(entry);\n client.on('close', () => clients.delete(entry));\n // An oversized frame lands here; ws then closes the socket with 1009.\n client.on('error', (error) => options.onNotice?.(`Public socket failed: ${error.message}`));\n try {\n upgrade(forwarded, apiSocket(client));\n } catch (error) {\n options.onNotice?.(`Public socket handler failed: ${harnessErrorMessage(error)}`);\n client.close(1011);\n }\n });\n };\n /**\n * A recorded session is dormant exactly while the hub has no session for its\n * id, so reviving one needs no bookkeeping beyond the hub itself.\n */\n const dormant = (): readonly OpenSessionRecord[] =>\n (options.dormantSessions?.() ?? []).filter((record) => options.headlessHub.session(record.sessionId) === undefined);\n const protocol = createHeadlessProtocol({\n hub: options.headlessHub,\n telemetry: options.telemetry,\n onNotice: options.onNotice,\n dormantSessions: dormant,\n });\n const sessionMcpStateDir =\n options.sessionMcpStateDir ?? (await fs.mkdtemp(path.join(os.tmpdir(), 'po-session-mcp-')));\n const sessionMcp = createSessionMcpRoutes({\n headlessHub: options.headlessHub,\n publicOrigin: options.sessionMcpPublicOrigin ?? (() => undefined),\n publicOriginRevision: options.sessionMcpPublicOriginRevision,\n onNotice: options.onNotice,\n isSessionPersisted: options.isSessionPersisted,\n activityStore: await createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: await createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: await createSessionMcpRegistrationStore({\n stateDir: sessionMcpStateDir,\n onNotice: options.onNotice,\n }),\n });\n /** Sessions being restarted, keyed by id, settled once the reopen succeeds or fails. */\n const restarting = new Map<string, Promise<void>>();\n /**\n * Stores already-normalized groups where a session keeps them: the journal of a live\n * session, which announces the change itself, or the record of a dormant one.\n */\n const writeGroups = async (sessionId: string, groups: string[]): Promise<boolean> => {\n const runtime = options.headlessHub.runtime(sessionId);\n if (runtime !== undefined) {\n await runtime.setGroups(groups);\n return true;\n }\n const record = dormant().find((candidate) => candidate.sessionId === sessionId);\n if (record === undefined || options.setDormantGroups === undefined) return false;\n await options.setDormantGroups(record, groups);\n options.headlessHub.notifyDormantChanged(sessionId);\n return true;\n };\n const server = createServer((request, response) => {\n void handleRequest(request, response).catch((error: unknown) => {\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\n if (response.headersSent) {\n response.destroy();\n return;\n }\n // A setup problem the user must fix carries its own instructions; anything else stays generic.\n if (isPoSessionSetupError(error)) json(response, 422, { error: error.message });\n else json(response, 500, { error: 'Internal server error.' });\n });\n });\n\n async function handleRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const url = requestPath(request);\n if (url.pathname === '/api/health' && request.method === 'GET') {\n json(response, 200, {\n ok: true,\n role: HEALTH_ROLE,\n protocol: PROTOCOL_VERSION,\n sessions: options.headlessHub.snapshot().length,\n });\n return;\n }\n if (\n (url.pathname.startsWith('/api/network/') || /^\\/api\\/networks\\/[^/]+\\/network\\//.test(url.pathname)) &&\n options.requestNetwork\n ) {\n const result = await options.requestNetwork(webRequest(request, url));\n if (result) {\n await writeResponse(response, result);\n return;\n }\n }\n const publicRoute = publicRouteFor(url);\n if (publicRoute !== undefined) {\n await servePublicRoute(request, response, url, publicRoute);\n return;\n }\n const scopedSession = /^\\/api\\/workspaces\\/[^/]+\\/sessions\\/([^/]+)(?:\\/|$)/u.exec(url.pathname)?.[1];\n if (\n scopedSession &&\n options.headlessHub.computerUse?.ownsSession?.(decodeURIComponent(scopedSession)) &&\n !computerUseAuthorized(decodeURIComponent(scopedSession), request) &&\n !(\n request.method === 'GET' &&\n url.pathname.endsWith('/plugins/computer-use/artifact') &&\n recordingAuthorized(decodeURIComponent(scopedSession), request)\n ) &&\n !(\n request.method === 'POST' &&\n url.pathname.endsWith('/plugins/computer-use/activate') &&\n activationAuthorized(request)\n ) &&\n !(\n url.pathname.endsWith('/plugins/computer-use/activate') &&\n ((request.method === 'GET' &&\n (pendingAuthorized(decodeURIComponent(scopedSession), request) ||\n recordingAuthorized(decodeURIComponent(scopedSession), request))) ||\n (request.method === 'DELETE' && pendingAuthorized(decodeURIComponent(scopedSession), request)))\n )\n ) {\n json(response, 404, { error: 'This session belongs to its Desktop instance.' });\n return;\n }\n if (publicRoutes && isPublicSessionMcpRoute(request.method ?? 'GET', url.pathname)) {\n const sessionMcpAbort = new AbortController();\n const abortSessionMcp = (): void => {\n if (!response.writableEnded) sessionMcpAbort.abort();\n };\n response.once('close', abortSessionMcp);\n const publicSessionMcp = await sessionMcp.handlePublic(webRequest(request, url, sessionMcpAbort.signal));\n if (publicSessionMcp !== undefined) {\n try {\n await writeResponse(response, publicSessionMcp);\n } finally {\n response.off('close', abortSessionMcp);\n }\n return;\n }\n response.off('close', abortSessionMcp);\n }\n // The optional identity package authenticates its own routes, not with the host attach token.\n const identity =\n publicRoutes && url.pathname.startsWith('/api/auth/') ? options.headlessHub.publicApi('auth') : undefined;\n if (identity) {\n await writeResponse(response, await identity.handler.fetch(webRequest(request, url)));\n return;\n }\n if (!authorized(request, options.token)) {\n json(response, 401, { error: 'Unauthorized.' });\n return;\n }\n // A restart closes the session before reopening it under the same id. Any session-scoped\n // request that lands in that gap, such as a plugin's poll, waits for the reopened session.\n const reopening = scopedSession === undefined ? undefined : restarting.get(decodeURIComponent(scopedSession));\n if (reopening !== undefined && options.headlessHub.session(decodeURIComponent(scopedSession!)) === undefined)\n await reopening;\n if (isSessionMcpHostRoute(url.pathname)) {\n const hostSessionMcp = await sessionMcp.handleHost(webRequest(request, url));\n if (hostSessionMcp !== undefined) {\n await writeResponse(response, hostSessionMcp);\n return;\n }\n }\n if (url.pathname === '/api/remote' || url.pathname.startsWith('/api/remote/')) {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value !== undefined && name !== 'authorization' && name !== 'x-po-token')\n headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n const result = await options.headlessHub.requestApi(\n { scope: 'global' },\n 'remote',\n new Request(`http://po.local${url.pathname.slice('/api/remote'.length)}${url.search}`, {\n method: request.method,\n headers,\n ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n await writeResponse(response, result);\n return;\n }\n if (url.pathname === '/api/telemetry/browser' && request.method === 'POST') {\n const body = JSON.parse(new TextDecoder().decode(await readBody(request))) as { v?: unknown; events?: unknown };\n if (body.v !== 1 || !Array.isArray(body.events) || body.events.length > 10) {\n json(response, 400, { error: 'Invalid browser telemetry batch.' });\n return;\n }\n for (const event of body.events) {\n if (\n !event ||\n typeof event !== 'object' ||\n typeof event.name !== 'string' ||\n !/^web\\.browser\\.[a-z_]{1,40}$/u.test(event.name)\n )\n continue;\n if (!options.telemetry) continue;\n const attributes: Record<string, unknown> = {\n ...(typeof event.duration_ms === 'number' && Number.isFinite(event.duration_ms) && event.duration_ms >= 0\n ? { duration_ms: event.duration_ms }\n : {}),\n ...(typeof event.count === 'number' && Number.isFinite(event.count) && event.count >= 0\n ? { count: event.count }\n : {}),\n };\n // UI trace rollups carry a few named scalars; the telemetry sanitizer still filters every key.\n if (event.attributes && typeof event.attributes === 'object' && !Array.isArray(event.attributes))\n for (const [key, value] of Object.entries(event.attributes as Record<string, unknown>).slice(0, 12))\n if (\n /^[a-z_]{1,32}$/u.test(key) &&\n ((typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'string' && value.length <= 256))\n )\n attributes[key] = value;\n observe(\n event.level === 'warn'\n ? options.telemetry.recordWarning(event.name, undefined, attributes)\n : options.telemetry.recordEvent(event.name, attributes),\n );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n json(response, 200, (await options.compositions?.()) ?? { workspaces: [] });\n return;\n }\n if (\n (url.pathname.startsWith('/api/web-plugins/') ||\n url.pathname === '/bundle-manifest.json' ||\n url.pathname.startsWith('/bundle-assets/')) &&\n options.requestAsset\n ) {\n const result = await options.requestAsset(new Request(url, { method: request.method }));\n if (result) {\n await writeResponse(response, result);\n return;\n }\n }\n if (url.pathname === '/api/directories/workspaces' && request.method === 'GET' && options.declaredWorkspaces) {\n const requestedPath = url.searchParams.get('path');\n if (!requestedPath?.trim()) {\n json(response, 400, { error: 'A folder path is required.' });\n return;\n }\n try {\n json(response, 200, await options.declaredWorkspaces(expandHome(requestedPath.trim())));\n } catch (error) {\n json(response, 422, { error: harnessErrorMessage(error) });\n }\n return;\n }\n if (url.pathname === '/api/directories/children' && request.method === 'GET') {\n const listing = await directoryChildren(url.searchParams.get('path'));\n if (listing === undefined) json(response, 404, { error: 'That folder cannot be read.' });\n else json(response, 200, listing);\n return;\n }\n if (url.pathname === '/api/directories/po' && request.method === 'GET') {\n json(response, 200, { directories: await poFolders() });\n return;\n }\n if (url.pathname === '/api/directories' && request.method === 'GET') {\n json(response, 200, {\n directories: await directorySuggestions(url.searchParams.get('q') ?? '', options.headlessHub.snapshot()),\n });\n return;\n }\n // Verified browser bundles can remain active across a server upgrade. Keep\n // their former create route working while they refresh to workspace routes.\n if (url.pathname === '/api/sessions' && request.method === 'POST') {\n const body = parseJson(await readBody(request));\n if (\n !body ||\n typeof body !== 'object' ||\n !('cwd' in body) ||\n typeof body.cwd !== 'string' ||\n !body.cwd.trim() ||\n ('name' in body && typeof body.name !== 'string')\n ) {\n json(response, 400, { error: 'A session needs a working directory and an optional name.' });\n return;\n }\n const created = await options.headlessHub.sessionService.create({\n cwd: body.cwd,\n name: 'name' in body ? String(body.name) : path.basename(body.cwd),\n });\n json(response, 201, { sessionId: created.sessionId });\n return;\n }\n const workspaceSessions = /^\\/api\\/workspaces\\/([^/]+)\\/sessions$/u.exec(url.pathname);\n if (workspaceSessions) {\n const workspaceId = decodeURIComponent(workspaceSessions[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (request.method === 'GET') {\n json(response, 200, {\n sessions: [\n ...options.headlessHub\n .snapshot()\n .filter(\n (session) =>\n session.workspaceId === workspaceId &&\n (!options.headlessHub.computerUse?.ownsSession?.(session.id) ||\n computerUseAuthorized(session.id, request)),\n )\n .map(sessionView),\n ...dormant()\n .filter(\n (record) =>\n record.workspaceId === workspaceId &&\n (!options.headlessHub.computerUse?.ownsSession?.(record.sessionId) ||\n computerUseAuthorized(record.sessionId, request)),\n )\n .map((record) =>\n dormantView(record, options.headlessHub.sessionPendingApprovalCount?.(record.sessionId)),\n ),\n ],\n });\n return;\n }\n if (request.method === 'POST') {\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n const body = parseJson(await readBody(request));\n if (!body || typeof body !== 'object' || ('name' in body && typeof body.name !== 'string')) {\n json(response, 400, { error: 'A session accepts an optional name.' });\n return;\n }\n const created = await options.headlessHub.sessionService.create({\n workspaceId,\n cwd: workspace.root,\n name: 'name' in body ? String(body.name) : path.basename(workspace.root),\n });\n json(response, 201, { sessionId: created.sessionId });\n return;\n }\n }\n // Renames a group (PATCH { name }) or removes it (DELETE) on every session this caller can see.\n const groupMatch = /^\\/api\\/session-groups\\/([^/]+)$/u.exec(url.pathname);\n if (groupMatch && (request.method === 'PATCH' || request.method === 'DELETE')) {\n const from = decodeURIComponent(groupMatch[1]);\n let to: string[] = [];\n if (request.method === 'PATCH') {\n const body = parseJson(await readBody(request));\n const name = body && typeof body === 'object' && 'name' in body ? body.name : undefined;\n if (typeof name !== 'string' || name.trim() === '') {\n json(response, 400, { error: 'A group needs a new name.' });\n return;\n }\n to = [name];\n }\n const members = [\n ...options.headlessHub.snapshot().map((session) => ({ id: session.id, groups: session.groups ?? [] })),\n ...dormant().map((record) => ({ id: record.sessionId, groups: record.groups ?? [] })),\n ].filter(\n (member) =>\n member.groups.includes(from) &&\n (!options.headlessHub.computerUse?.ownsSession?.(member.id) || computerUseAuthorized(member.id, request)),\n );\n // Every session's new list is validated before any is written, so a bad name changes nothing.\n let updates: { id: string; groups: string[] }[];\n try {\n updates = members.map((member) => ({\n id: member.id,\n groups: normalizeSessionGroups(member.groups.flatMap((group) => (group === from ? to : [group]))),\n }));\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n for (const update of updates) await writeGroups(update.id, update.groups);\n json(response, 200, { sessions: updates.length });\n return;\n }\n if (url.pathname === '/api/workspaces') {\n if (request.method === 'GET') {\n json(response, 200, { workspaces: options.headlessHub.workspaces() });\n return;\n }\n if (request.method === 'POST') {\n const admission = parseWorkspaceAdmission(parseJson(await readBody(request)));\n if ('error' in admission) {\n json(response, 400, admission);\n return;\n }\n let workspace: Awaited<ReturnType<HeadlessHub['admitWorkspace']>>;\n try {\n workspace = await options.headlessHub.admitWorkspace(admission);\n } catch (error) {\n json(response, 422, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n json(response, 201, { workspace });\n return;\n }\n }\n const workspaceHistoryMatch = /^\\/api\\/workspaces\\/([^/]+)\\/history$/u.exec(url.pathname);\n if (workspaceHistoryMatch && request.method === 'GET' && options.workspaceHistory) {\n const workspaceId = decodeURIComponent(workspaceHistoryMatch[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n json(response, 200, { sessions: await options.workspaceHistory(workspaceId) });\n return;\n }\n const workspaceResumeMatch = /^\\/api\\/workspaces\\/([^/]+)\\/resume$/u.exec(url.pathname);\n if (workspaceResumeMatch && request.method === 'POST' && options.resumeWorkspaceSession) {\n const workspaceId = decodeURIComponent(workspaceResumeMatch[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n const body = parseJson(await readBody(request));\n const targetSessionId =\n body && typeof body === 'object' && 'targetSessionId' in body ? body.targetSessionId : undefined;\n if (typeof targetSessionId !== 'string' || !/^[A-Za-z0-9_-]+$/u.test(targetSessionId)) {\n json(response, 400, { error: 'Invalid target session id.' });\n return;\n }\n json(response, 200, { sessionId: await options.resumeWorkspaceSession(workspaceId, targetSessionId) });\n return;\n }\n const workspaceRemovedMatch = /^\\/api\\/workspaces\\/([^/]+)\\/removed$/u.exec(url.pathname);\n if (workspaceRemovedMatch && request.method === 'GET' && options.removedSessions) {\n const workspaceId = decodeURIComponent(workspaceRemovedMatch[1]);\n if (!options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n json(response, 200, { sessions: await options.removedSessions(workspaceId) });\n return;\n }\n const workspaceRestoreMatch = /^\\/api\\/workspaces\\/([^/]+)\\/removed\\/([^/]+)\\/restore$/u.exec(url.pathname);\n if (workspaceRestoreMatch && request.method === 'POST' && options.restoreRemovedSession) {\n const workspaceId = decodeURIComponent(workspaceRestoreMatch[1]);\n const sessionId = decodeURIComponent(workspaceRestoreMatch[2]);\n if (!options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (!/^[A-Za-z0-9_-]+$/u.test(sessionId)) {\n json(response, 400, { error: 'Invalid session id.' });\n return;\n }\n if (!(await options.restoreRemovedSession(workspaceId, sessionId))) {\n json(response, 409, { error: 'This session is being deleted or is already gone.' });\n return;\n }\n json(response, 200, { ok: true });\n return;\n }\n const workspaceMatch = /^\\/api\\/workspaces\\/([^/]+)$/u.exec(url.pathname);\n if (workspaceMatch && request.method === 'GET') {\n const workspace = options.headlessHub\n .workspaces()\n .find((entry) => entry.id === decodeURIComponent(workspaceMatch[1]));\n json(response, workspace ? 200 : 404, workspace ? { workspace } : { error: 'Workspace not found.' });\n return;\n }\n if (workspaceMatch && request.method === 'PATCH') {\n const id = decodeURIComponent(workspaceMatch[1]);\n const body = parseJson(await readBody(request));\n if (\n !body ||\n typeof body !== 'object' ||\n Array.isArray(body) ||\n Object.keys(body).length !== 1 ||\n (!('sandbox' in body) && !('instructions' in body))\n ) {\n json(response, 400, { error: 'Provide exactly one of sandbox or instructions.' });\n return;\n }\n const instructions = 'instructions' in body ? body.instructions : undefined;\n const sandbox = 'sandbox' in body ? body.sandbox : undefined;\n if ('instructions' in body) {\n if (typeof instructions !== 'string' || instructions.length > WORKSPACE_INSTRUCTIONS_MAX_LENGTH) {\n json(response, 400, {\n error: `Workspace instructions must be text up to ${String(WORKSPACE_INSTRUCTIONS_MAX_LENGTH)} characters.`,\n });\n return;\n }\n } else if (sandbox !== null && (typeof sandbox !== 'string' || sandbox.trim() === '')) {\n json(response, 400, { error: 'The sandbox must be a provider id, or null to run locally.' });\n return;\n }\n if (!options.headlessHub.workspaces().some((workspace) => workspace.id === id)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (typeof instructions === 'string' ? !options.setWorkspaceInstructions : !options.setWorkspaceSandbox) {\n json(response, 404, { error: 'Workspace settings are unavailable.' });\n return;\n }\n const result =\n typeof instructions === 'string'\n ? await options.setWorkspaceInstructions!(id, instructions)\n : await options.setWorkspaceSandbox!(id, sandbox as string | null);\n json(response, 'error' in result ? 409 : 200, result);\n return;\n }\n if (workspaceMatch && request.method === 'DELETE') {\n const id = decodeURIComponent(workspaceMatch[1]);\n if (!options.headlessHub.workspaces().some((workspace) => workspace.id === id)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (\n options.headlessHub.snapshot().some((session) => session.workspaceId === id) ||\n dormant().some((session) => session.workspaceId === id)\n ) {\n json(response, 409, { error: 'Workspace still has sessions.' });\n return;\n }\n await options.headlessHub.removeWorkspace(id);\n json(response, 200, { ok: true });\n return;\n }\n const pluginMatch = PO_PACKAGE_API_PATH_PATTERN.exec(url.pathname);\n if (pluginMatch !== null && request.method !== 'CONNECT') {\n const workspaceId = pluginMatch[1] === undefined ? undefined : decodeURIComponent(pluginMatch[1]);\n const sessionId = pluginMatch[2] === undefined ? undefined : decodeURIComponent(pluginMatch[2]);\n if (workspaceId !== undefined && !options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (sessionId !== undefined && options.headlessHub.session(sessionId)?.workspaceId !== workspaceId) {\n // A stopped session still shows the composition it last published, so its context detail\n // is served from the file it wrote. Nothing else answers until it is woken.\n const stopped = dormant().some(\n (record) => record.sessionId === sessionId && record.workspaceId === workspaceId,\n );\n if (stopped && pluginMatch[3] === CONTEXT_API_BASE_PATH && request.method === 'GET') {\n const detail = await createContextApi({ sessionId, environment: process.env }).fetch(\n new Request(`http://po.local/${pluginMatch[4] ?? ''}${url.search}`),\n );\n const body = (await detail.json()) as { error?: string };\n // The detail file is only kept while the session runs, so a stopped session usually has none.\n if (readContextDetail(sessionId, process.env) === undefined)\n json(response, 404, { error: 'This session is stopped. Wake it to read this item.' });\n else json(response, detail.status, body);\n return;\n }\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n const mount: PoApiMount =\n sessionId !== undefined\n ? { scope: 'session', sessionId }\n : workspaceId !== undefined\n ? { scope: 'workspace', workspaceId }\n : { scope: 'global' };\n const basePath = pluginMatch[3] === undefined ? 'settings' : decodeURIComponent(pluginMatch[3]);\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(basePath)) {\n json(response, 400, { error: 'Invalid package API base path.' });\n return;\n }\n if (pluginMatch[3] === 'settings' || (sessionId !== undefined && basePath === 'settings')) {\n json(response, 404, { error: 'Not found.' });\n return;\n }\n const headers = new Headers();\n // Only the authenticated loopback proxy knows the server token and may\n // forward caller stamps. Browser-supplied stamps remain untrusted.\n const trustedCaller = options.token !== undefined && authorized(request, options.token);\n for (const [name, value] of Object.entries(request.headers)) {\n if (\n value !== undefined &&\n !['host', 'authorization', 'x-po-token'].includes(name) &&\n (trustedCaller || !PO_API_CALLER_HEADERS.includes(name as (typeof PO_API_CALLER_HEADERS)[number]))\n )\n headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n if (!trustedCaller) {\n headers.set(PO_API_CALLER_LOCALITY_HEADER, 'local');\n headers.set(PO_API_CALLER_STEP_UP_HEADER, 'not-required');\n }\n const abort = new AbortController();\n const disconnected = (): void => {\n if (!response.writableEnded) abort.abort();\n };\n response.once('close', disconnected);\n try {\n const started = performance.now();\n const attributes = {\n scope: mount.scope,\n 'plugin.name': basePath,\n 'http.operation': request.method,\n ...(mount.scope === 'workspace' ? { 'workspace.id': mount.workspaceId } : {}),\n ...(mount.scope === 'session' ? { 'session.id': mount.sessionId } : {}),\n };\n let requestBytes = 0;\n const dispatch = async () => {\n const body =\n request.method === 'GET' || request.method === 'HEAD' ? undefined : Buffer.from(await readBody(request));\n requestBytes = body?.byteLength ?? 0;\n return options.headlessHub.requestApi(\n mount,\n basePath,\n new Request(`http://po.local/${pluginMatch[4] ?? ''}${url.search}`, {\n method: request.method,\n headers,\n signal: abort.signal,\n ...(body === undefined ? {} : { body }),\n }),\n );\n };\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n const durationMs = performance.now() - started;\n let responseBytes = 0;\n try {\n await writeResponse(response, result, (bytes) => {\n responseBytes += bytes;\n });\n } finally {\n // Recorded after the body is written, so its size explains heap growth from large replies.\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs,\n request_bytes: requestBytes,\n response_bytes: responseBytes,\n response_kind: contentClass(result.headers.get('content-type')),\n flush_ms: performance.now() - started - durationMs,\n }),\n options.onNotice,\n );\n }\n } finally {\n response.off('close', disconnected);\n }\n return;\n }\n const sessionMatch = /^\\/api\\/workspaces\\/([^/]+)\\/sessions\\/([^/]+)(?:\\/(.*))?$/u.exec(url.pathname);\n if (sessionMatch === null) {\n json(response, 404, { error: 'Not found.' });\n return;\n }\n const sessionId = decodeURIComponent(sessionMatch[2]);\n const workspaceId = decodeURIComponent(sessionMatch[1]);\n const session = options.headlessHub.session(sessionId);\n const suffix = sessionMatch[3] === undefined ? '' : `/${sessionMatch[3]}`;\n if (suffix === '/transcript' && request.method === 'GET' && options.readDormantTranscript) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (record === undefined) {\n json(response, 404, { error: 'Dormant session not found.' });\n return;\n }\n let transcriptRequest: TranscriptPageRequest;\n try {\n transcriptRequest = parseTranscriptRequest(url);\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : 'Invalid transcript request.' });\n return;\n }\n try {\n const page = await options.readDormantTranscript(record, transcriptRequest, BACKGROUND_CONTEXT);\n json(response, 200, page);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const status = message === 'STALE_TRANSCRIPT_CURSOR' ? 409 : 422;\n json(response, status, {\n error: status === 409 ? 'STALE_TRANSCRIPT_CURSOR' : 'Saved transcript is unavailable.',\n });\n }\n return;\n }\n // Groups are set on live and dormant sessions alike: a dormant one keeps them on its record.\n if (suffix === '/groups' && request.method === 'PUT') {\n const known =\n session?.workspaceId === workspaceId ||\n dormant().some((candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId);\n if (!known) {\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n const body = parseJson(await readBody(request));\n let groups: string[];\n try {\n groups = normalizeSessionGroups(body && typeof body === 'object' && 'groups' in body ? body.groups : undefined);\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n if (!(await writeGroups(sessionId, groups))) {\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n json(response, 200, { groups });\n return;\n }\n // Revive is the one session route that answers before a runtime exists: it\n // is what creates one.\n if (sessionMatch[3] === 'revive' && request.method === 'POST' && options.reviveSession) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (record === undefined) {\n json(response, 404, { error: 'Dormant session not found.' });\n return;\n }\n await options.reviveSession(record);\n json(response, 200, { ok: true });\n return;\n }\n if (session === undefined || session.workspaceId !== workspaceId) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (\n suffix === '' &&\n request.method === 'DELETE' &&\n record !== undefined &&\n options.removeDormantSession !== undefined\n ) {\n await sessionMcp.closeSessionBinding(record.sessionId);\n // A previous live Remove may have failed while stopping. Do not clean its files until that stop is known safe.\n await options.headlessHub.closeSession(record.sessionId, { keepDormant: true });\n await options.removeDormantSession(record);\n options.headlessHub.notifySessionRemoved(record.sessionId);\n json(response, 200, { ok: true });\n return;\n }\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n if (suffix === '' && request.method === 'GET') {\n json(response, 200, sessionView(session));\n return;\n }\n if (suffix === '' && request.method === 'DELETE') {\n await sessionMcp.closeSessionBinding(sessionId);\n // Keep a retryable dormant record until output cleanup succeeds. Shutdown/release never calls this hook.\n await options.headlessHub.closeSession(sessionId, options.removeSessionFiles ? { keepDormant: true } : undefined);\n if (options.removeSessionFiles) {\n await options.removeSessionFiles(sessionId);\n options.headlessHub.notifySessionRemoved(sessionId);\n }\n json(response, 200, { ok: true });\n return;\n }\n if (suffix === '/history' && request.method === 'GET' && options.sessionHistory) {\n json(response, 200, { sessions: await options.sessionHistory(session) });\n return;\n }\n if (suffix === '/avatar' && request.method === 'GET') {\n const avatar = options.headlessHub.sessionAvatar(sessionId);\n if (avatar === undefined) {\n json(response, 404, { error: 'This session has no avatar.' });\n return;\n }\n const current = url.searchParams.get('v') === session.profile?.iconVersion;\n response.writeHead(200, {\n 'content-type': avatar.mimeType,\n 'content-length': String(avatar.bytes.byteLength),\n 'cache-control': current ? 'private, max-age=31536000, immutable' : 'no-store',\n 'x-content-type-options': 'nosniff',\n });\n response.end(avatar.bytes);\n return;\n }\n if (suffix === '/file' && request.method === 'GET') {\n // The session host owns the folders a session may open, so it reads the file.\n const forwarded = new Headers();\n for (const name of ['range', 'if-match'] as const) {\n const value = request.headers[name];\n if (typeof value === 'string') forwarded.set(name, value);\n }\n const target = new URL('http://po.local/');\n const requested = url.searchParams.get('path');\n if (requested !== null) target.searchParams.set('path', requested);\n await writeResponse(\n response,\n await options.headlessHub.requestApi(\n { scope: 'session', sessionId },\n SESSION_FILES_API,\n new Request(target, { headers: forwarded }),\n ),\n );\n return;\n }\n if (suffix === '/attachments' && request.method === 'POST') {\n let bytes: Uint8Array;\n try {\n bytes = await readBody(request);\n } catch (error) {\n if (!(error instanceof RequestBodyTooLargeError)) throw error;\n json(response, 413, { error: 'The attachment exceeds the 8 MB upload limit.' });\n return;\n }\n json(response, 201, await writeSessionAttachment(sessionId, url.searchParams.get('name') ?? 'file', bytes));\n return;\n }\n if (suffix === '/restart' && request.method === 'POST' && options.restartSession) {\n // A restart closes the host, and closing aborts the running turn.\n if ((session.phase ?? 'idle') !== 'idle') {\n json(response, 409, { error: RESTART_WHILE_RUNNING_ERROR });\n return;\n }\n const restart = options.restartSession(session);\n // Settled either way: a failed restart leaves the session dormant, and waiters then see that.\n const settled = restart.then(\n () => undefined,\n () => undefined,\n );\n restarting.set(sessionId, settled);\n try {\n await restart;\n } finally {\n if (restarting.get(sessionId) === settled) restarting.delete(sessionId);\n }\n json(response, 200, { ok: true });\n return;\n }\n if (suffix === '/resume' && request.method === 'POST' && options.resumeSession) {\n const body = parseJson(await readBody(request));\n const targetSessionId =\n body && typeof body === 'object' && 'targetSessionId' in body ? body.targetSessionId : undefined;\n if (typeof targetSessionId !== 'string' || !/^[A-Za-z0-9_-]+$/u.test(targetSessionId)) {\n json(response, 400, { error: 'Invalid target session id.' });\n return;\n }\n if (\n options.headlessHub.computerUse?.ownsSession?.(targetSessionId) &&\n !computerUseAuthorized(targetSessionId, request)\n ) {\n json(response, 404, { error: 'This session belongs to its Desktop instance.' });\n return;\n }\n json(response, 200, { sessionId: await options.resumeSession(session, targetSessionId) });\n return;\n }\n json(response, 404, { error: 'Not found.' });\n }\n\n /** Checks one connection request against its mount; the result says why it may not connect. */\n const accessFor = (request: IncomingMessage): ConnectionAccess | 401 | 404 => {\n const mount = parsePoSocketPath(requestPath(request).pathname);\n if (!mount) return 404;\n if (!authorized(request, options.token)) return 401;\n if (\n mount.scope !== 'global' &&\n (!options.headlessHub.workspaces().some((entry) => entry.id === mount.workspaceId && entry.available !== false) ||\n (mount.scope === 'session' && options.headlessHub.session(mount.sessionId)?.workspaceId !== mount.workspaceId))\n )\n return 404;\n return {\n mount,\n authorizeSession: (id) =>\n !options.headlessHub.computerUse?.ownsSession?.(id) || computerUseAuthorized(id, request),\n authorizeComputerUse: (id) => computerUseAuthorized(id, request),\n authorizeDesktop: () => desktopAuthorized(request),\n };\n };\n\n server.on('upgrade', (request, socket, head) => {\n const networkUrl = requestPath(request);\n if (/^\\/api\\/networks\\/[^/]+\\/relay$/.test(networkUrl.pathname) && options.acceptNetworkRelay) {\n if (closed) {\n socket.destroy();\n return;\n }\n publicSockets.handleUpgrade(request, socket, head, (client) => {\n client.on('error', (error) => {\n options.onNotice?.(`Network relay socket failed: ${harnessErrorMessage(error)}`);\n client.close();\n });\n void options.acceptNetworkRelay!(apiSocket(client), networkUrl).catch((error: unknown) => {\n options.onNotice?.(`Network relay failed: ${harnessErrorMessage(error)}`);\n client.close();\n });\n });\n return;\n }\n const publicRoute = publicRouteFor(networkUrl);\n if (publicRoute !== undefined) {\n void upgradePublicRoute(request, socket, head, publicRoute).catch((error: unknown) => {\n options.onNotice?.(`Public socket upgrade failed: ${harnessErrorMessage(error)}`);\n socket.destroy();\n });\n return;\n }\n const access = accessFor(request);\n if (typeof access === 'number' || closed) {\n if (access === 401) socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n else if (access === 404) socket.write('HTTP/1.1 404 Not Found\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n webSockets.handleUpgrade(request, socket, head, (client) => {\n const entry: Client = { socket: client };\n clients.add(entry);\n client.on('close', () => clients.delete(entry));\n // An invalid or oversized frame lands here; ws then closes the socket (1002 or 1009) instead of an\n // unhandled 'error' event crashing the server.\n client.on('error', (error) => options.onNotice?.(`Protocol socket failed: ${error.message}`));\n // Browser clients send text frames only; refusing packed ones keeps a deflate bomb out.\n protocol.accept(webSocketLink(client as unknown as WebSocketLike, { acceptPacked: false }), access);\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, options.host ?? '127.0.0.1', () => resolve());\n });\n const address = server.address();\n if (address === null || typeof address === 'string') {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n throw new Error('The headless server did not expose a TCP address.');\n }\n const host = options.host ?? '127.0.0.1';\n const url = `http://${host}:${address.port}`;\n return {\n url,\n sessionReservations: sessionMcp.reservations,\n acceptProtocol(pathname, link, headers) {\n // In process, so it carries the token the listener would have checked.\n const access = accessFor({\n url: pathname,\n headers: { ...headers, ...(options.token === undefined ? {} : { 'x-po-token': options.token }) },\n } as IncomingMessage);\n if (typeof access === 'number' || closed) {\n link.close(access === 401 ? 'unauthorized' : 'not found');\n return false;\n }\n protocol.accept(link, access);\n return true;\n },\n async close() {\n if (closed) return;\n closed = true;\n for (const client of clients) client.socket.terminate();\n clients.clear();\n await sessionMcp.close();\n if (options.sessionMcpStateDir === undefined) await fs.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.close();\n for (const socket of publicSockets.clients) socket.terminate();\n publicSockets.close();\n server.closeAllConnections();\n await new Promise<void>((resolve, reject) =>\n server.close((error) => (error === undefined ? resolve() : reject(error))),\n );\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"headlessServer.cjs","names":["PO_API_CALLER_HEADERS","createHash","timingSafeEqual","os","path","fs","Readable","pipeline","WebSocketServer","harnessErrorMessage","createHeadlessProtocol","createSessionMcpRoutes","createSessionMcpActivityStore","createSessionMcpConversationStore","createSessionMcpRegistrationStore","createServer","isPoSessionSetupError","isPublicSessionMcpRoute","isSessionMcpHostRoute","normalizeSessionGroups","createContextApi","readContextDetail","PO_API_CALLER_LOCALITY_HEADER","PO_API_CALLER_STEP_UP_HEADER","contentClass","BACKGROUND_CONTEXT","SESSION_FILES_API","writeSessionAttachment","parsePoSocketPath","webSocketLink"],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import { createHash, timingSafeEqual } from 'node:crypto';\nimport type { Dirent } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { type Duplex, Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nimport { webSocketLink, type Context, type Link, type WebSocketLike } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { WebSocket } from 'ws';\nimport { WebSocketServer } from 'ws';\n\nimport { API_BASE_PATH as CONTEXT_API_BASE_PATH } from '../constants/contextApi';\nimport { SESSION_FILES_API } from '../constants/sessionFiles';\nimport {\n PO_API_CALLER_HEADERS,\n PO_API_CALLER_LOCALITY_HEADER,\n PO_API_CALLER_STEP_UP_HEADER,\n parsePoSocketPath,\n type PoApiHandler,\n type PoApiMount,\n type PoApiPublicRoutes,\n type PoApiSocket,\n} from '../exports/packageApi';\nimport type { TranscriptPage, TranscriptPageRequest } from '../exports/sessionProtocol';\nimport { isPoSessionSetupError } from '../schemas/headless';\nimport type { PoHubSessionReservations } from '../schemas/hubChannel';\nimport { normalizeSessionGroups } from '../schemas/sessionProtocol';\nimport { readContextDetail } from '../services/contextDetailStore';\nimport type { OpenSessionRecord } from '../services/openSessionRegistry';\nimport { observe, type ServerTelemetry } from '../services/serverTelemetry';\nimport { writeSessionAttachment } from '../services/sessionAttachments';\nimport { createSessionMcpActivityStore } from '../services/sessionMcpActivity';\nimport { createSessionMcpConversationStore } from '../services/sessionMcpConversations';\nimport { createSessionMcpRegistrationStore } from '../services/sessionMcpRegistrationStore';\nimport type { RemovedSession, SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspace, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\nimport { contentClass } from './packageApiServer';\nimport { createSessionMcpRoutes, isPublicSessionMcpRoute, isSessionMcpHostRoute } from './sessionMcpRoutes';\n\n/**\n * The canonical public shape of a package API request, as dispatch reads it.\n *\n * Groups: workspace id, session id, plugin base path, and the remainder handed\n * to the package. `settings` is the host's own API and sits beside `plugins`\n * rather than under it.\n *\n * Exported so the browser's URL construction can be pinned against it. The two\n * are written independently, in halves of this package that may not import each\n * other, and a disagreement between them is not a 404 from the route: the\n * service worker answers an unrecognised path out of the signed bundle cache,\n * so the symptom appears nowhere near the cause.\n */\nexport const PO_PACKAGE_API_PATH_PATTERN =\n /^\\/api(?:\\/workspaces\\/([^/]+)(?:\\/sessions\\/([^/]+))?)?\\/(?:plugins\\/([^/]+)|settings)(?:\\/(.*))?$/u;\n\nconst HEALTH_ROLE = 'hub';\nconst PROTOCOL_VERSION = 1;\nconst MAX_BODY_BYTES = 8 * 1024 * 1024;\n/** Body and WebSocket frame cap for package public routes. */\nconst PUBLIC_MAX_BYTES = 1024 * 1024;\nconst PUBLIC_PLUGIN_PATH = /^\\/api\\/plugins\\/([^/]+)(\\/.*)?$/u;\nconst LOOPBACK_HOST = /^(?:127\\.0\\.0\\.1|localhost|\\[::1\\])(?::\\d+)?$/iu;\nconst LOOPBACK_PEERS = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);\nconst EXTENSION_ORIGIN_PREFIX = 'chrome-extension://';\n/**\n * Headers that mark a forwarded request. The remote runtime's forward always attaches the host token\n * and sealed requests carry caller stamps, so a public route answers any of these with 404.\n */\nconst FORWARDED_MARKERS = [\n 'x-po-token',\n ...PO_API_CALLER_HEADERS,\n 'forwarded',\n 'x-forwarded-for',\n 'x-forwarded-host',\n 'cf-connecting-ip',\n 'cf-ray',\n];\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\nconst WORKSPACE_INSTRUCTIONS_MAX_LENGTH = 100_000;\nconst WORKSPACE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9 ._-]*$/u;\n/** Restart closes the session host, which aborts a running turn, so it waits for idle. */\nexport const RESTART_WHILE_RUNNING_ERROR =\n 'The session is running a turn. Stop it or wait for it to finish before reloading extensions.';\n\nexport interface HeadlessServerOptions {\n headlessHub: HeadlessHub;\n port: number;\n host?: string;\n /** Requests other than health require this bearer token when set. */\n token?: string;\n telemetry?: ServerTelemetry;\n onNotice?: (message: string) => void;\n /** `nativeClient` is set when the phone app asks (`?client=native`), so the host can prepare its build. */\n compositions?: (request: { nativeClient: boolean }) => unknown;\n requestAsset?: (request: Request) => Promise<Response | undefined>;\n /** Independently authenticated by the destination federation boundary. */\n requestNetwork?: (request: Request) => Promise<Response | undefined>;\n acceptNetworkRelay?: (socket: PoApiSocket, url: URL) => Promise<void>;\n sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<string>;\n /** Sessions removed from a workspace's History that can still be restored, newest first. */\n removedSessions?: (workspaceId: string) => Promise<RemovedSession[]>;\n /** Returns a removed session to History; false once it is being deleted or is already gone. */\n restoreRemovedSession?: (workspaceId: string, sessionId: string) => Promise<boolean>;\n /**\n * Sets (a provider id) or clears (`null`) the sandbox provider of a workspace and re-registers it. The\n * change applies to new sessions only; sessions already running on the host are left alone.\n * Answers `{ error }` when the host refuses, for example for a provider id it does not know.\n */\n setWorkspaceSandbox?: (\n workspaceId: string,\n sandbox: string | null,\n ) => Promise<{ workspace: HeadlessWorkspace } | { error: string }>;\n declaredWorkspaces?: (path: string) => Promise<{\n root: string;\n declarations: { name: string; instructions?: string; workspaceId?: string }[];\n }>;\n setWorkspaceInstructions?: (\n workspaceId: string,\n instructions: string,\n ) => Promise<{ workspace: HeadlessWorkspace } | { error: string }>;\n readDormantTranscript?: (\n record: OpenSessionRecord,\n request: TranscriptPageRequest,\n context: Context,\n ) => Promise<TranscriptPage>;\n restartSession?: (session: HeadlessHubSession) => Promise<void>;\n resumeSession?: (session: HeadlessHubSession, targetSessionId: string) => Promise<string>;\n /** Recorded sessions this server has not reopened, surfaced so a client can ask for one. */\n dormantSessions?: () => readonly OpenSessionRecord[];\n removeDormantSession?: (record: OpenSessionRecord) => void | Promise<void>;\n /** Explicit Remove only, after live work stops. The host cleans output and removes the open-session record. */\n removeSessionFiles?: (sessionId: string) => Promise<void>;\n /** Stores new groups on a dormant session's record; a revived session adopts them. */\n setDormantGroups?: (record: OpenSessionRecord, groups: readonly string[]) => void | Promise<void>;\n reviveSession?: (record: OpenSessionRecord) => Promise<void>;\n /** Trusted HTTPS origin advertised for public session MCP and OAuth endpoints. */\n sessionMcpPublicOrigin?: () => string | undefined;\n /** Durable state directory for verified Session MCP clients. */\n sessionMcpStateDir?: string;\n /** Monotonic exposure revision, including disable/re-enable cycles. */\n sessionMcpPublicOriginRevision?: () => number;\n isSessionPersisted?: (sessionId: string, cwd: string) => boolean;\n /**\n * False serves no public route: neither a global API's declared public paths nor the public session MCP\n * endpoints, so every request but health needs the token. A contained server passes false. Default true.\n */\n publicRoutes?: boolean;\n /** Largest protocol WebSocket message accepted, in bytes. Defaults to the ws library's limit. */\n webSocketMaxPayload?: number;\n}\n\nexport interface HeadlessServer {\n readonly url: string;\n readonly sessionReservations: PoHubSessionReservations;\n /** Hands an in-process link (a relayed device) to the protocol as if it had upgraded at `pathname`. */\n acceptProtocol(pathname: string, link: Link, headers: IncomingHttpHeaders): boolean;\n close(): Promise<void>;\n}\n\ntype Client = { socket: WebSocket };\n\nfunction sessionView(session: HeadlessHubSession): Record<string, unknown> {\n return {\n id: session.id,\n workspaceId: session.workspaceId,\n webComposition: session.webComposition,\n nativeComposition: session.nativeComposition,\n name: session.name,\n cwd: session.cwd,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n attach: 'attached',\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n ...(session.lastSettledAt === undefined ? {} : { lastSettledAt: session.lastSettledAt }),\n ...(session.backgroundWorkActive === undefined ? {} : { backgroundWorkActive: session.backgroundWorkActive }),\n ...(session.git === undefined ? {} : { git: { ...session.git } }),\n ...(session.profile === undefined ? {} : { profile: { ...session.profile } }),\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n ...(session.interaction === undefined ? {} : { interaction: session.interaction }),\n ...(session.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n ...(session.pendingApprovalCount === undefined ? {} : { pendingApprovalCount: session.pendingApprovalCount }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord, pendingApprovalCount?: number): Record<string, unknown> {\n return {\n id: record.sessionId,\n workspaceId: record.workspaceId,\n name: record.name,\n cwd: record.cwd,\n createdAt: record.createdAt,\n updatedAt: record.createdAt,\n phase: 'idle',\n phaseSince: record.createdAt,\n attach: 'detached',\n pendingMessageCount: 0,\n everPrompted: false,\n awaitingInput: false,\n dormant: true,\n ...(pendingApprovalCount === undefined ? {} : { pendingApprovalCount }),\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n ...(record.interaction === undefined ? {} : { interaction: record.interaction }),\n ...(record.groups === undefined || record.groups.length === 0 ? {} : { groups: [...record.groups] }),\n };\n}\n\nfunction json(response: ServerResponse, status: number, value: unknown): void {\n const body = JSON.stringify(value);\n response.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'content-length': Buffer.byteLength(body),\n });\n response.end(body);\n}\n\nconst tokenDigest = (value: string): Buffer => createHash('sha256').update(value).digest();\n\n/** Compares fixed-length digests, so neither the length nor the content of the token leaks through timing. */\nfunction tokenMatches(candidate: string | null | undefined, token: string): boolean {\n return typeof candidate === 'string' && timingSafeEqual(tokenDigest(candidate), tokenDigest(token));\n}\n\nfunction authorized(request: IncomingMessage, token: string | undefined): boolean {\n if (token === undefined) return true;\n const authorization = request.headers.authorization;\n if (authorization?.startsWith('Bearer ') && tokenMatches(authorization.slice('Bearer '.length), token)) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && tokenMatches(header, token)) return true;\n try {\n return tokenMatches(new URL(request.url ?? '/', 'http://po.local').searchParams.get('token'), token);\n } catch {\n return false;\n }\n}\n\n/** Why a public route refuses a request before authentication: 404 when forwarded, 403 when not local. */\nfunction publicRefusal(request: IncomingMessage): 403 | 404 | undefined {\n if (FORWARDED_MARKERS.some((name) => request.headers[name] !== undefined)) return 404;\n const origin = request.headers.origin;\n if (\n !LOOPBACK_HOST.test(request.headers.host ?? '') ||\n !LOOPBACK_PEERS.has(request.socket.remoteAddress ?? '') ||\n (origin !== undefined && !origin.startsWith(EXTENSION_ORIGIN_PREFIX))\n )\n return 403;\n return undefined;\n}\n\n/** Headers a public route sees: never Host, and never the host token or caller stamps. */\nfunction publicHeaders(request: IncomingMessage, token: string | undefined): Headers {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value === undefined || name === 'host') continue;\n const joined = Array.isArray(value) ? value.join(', ') : value;\n if (\n name === 'authorization' &&\n token !== undefined &&\n joined.startsWith('Bearer ') &&\n tokenMatches(joined.slice('Bearer '.length), token)\n )\n continue;\n headers.set(name, joined);\n }\n return headers;\n}\n\n/** Adapts an accepted `ws` socket. Its default binary type delivers every frame as one Buffer. */\nfunction apiSocket(client: WebSocket): PoApiSocket {\n return {\n get isOpen() {\n return client.readyState === client.OPEN;\n },\n send: (data) => client.send(data),\n close: (code, reason) => client.close(code, reason),\n onMessage: (listener) => {\n client.on('message', (data, isBinary) => {\n const bytes = data as Buffer;\n listener(isBinary ? bytes : bytes.toString('utf8'));\n });\n },\n onClose: (listener) => {\n client.on('close', (code, reason) => listener(code, reason.toString('utf8')));\n },\n };\n}\n\nfunction requestPath(request: IncomingMessage): URL {\n return new URL(request.url ?? '/', 'http://po.local');\n}\n\nfunction parseTranscriptRequest(url: URL): TranscriptPageRequest {\n const request: TranscriptPageRequest = {};\n const cursor = url.searchParams.get('cursor');\n const direction = url.searchParams.get('direction');\n const limit = url.searchParams.get('limit');\n if (cursor !== null) request.cursor = cursor;\n if (direction !== null) {\n if (direction !== 'older' && direction !== 'newer') throw new Error('Invalid transcript direction');\n request.direction = direction;\n }\n if (limit !== null) {\n if (!/^\\d+$/u.test(limit)) throw new Error('Invalid transcript page limit');\n const parsed = Number(limit);\n if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 100) throw new Error('Invalid transcript page limit');\n request.limit = parsed;\n }\n const entry = url.searchParams.get('entry');\n if (entry !== null) request.entryId = entry;\n return request;\n}\n\n/** Expands a leading `~` the way a shell would, so typed paths match what the user sees in a terminal. */\nfunction expandHome(value: string): string {\n if (value === HOME_PREFIX) return os.homedir();\n return value.startsWith(`${HOME_PREFIX}${path.sep}`) ? path.join(os.homedir(), value.slice(2)) : value;\n}\n\n/**\n * Validates an add-workspace request. A name alone asks for a new default folder,\n * so it must be safe to use as one folder name.\n */\nfunction parseWorkspaceAdmission(body: unknown): HeadlessWorkspaceAdmission | { error: string } {\n if (typeof body !== 'object' || body === null) return { error: 'A workspace root or name is required.' };\n const record = body as Record<string, unknown>;\n if (record.root !== undefined && typeof record.root !== 'string')\n return { error: 'The workspace root must be text.' };\n if (record.name !== undefined && typeof record.name !== 'string')\n return { error: 'The workspace name must be text.' };\n if (record.declaration !== undefined && typeof record.declaration !== 'string')\n return { error: 'The workspace declaration must be text.' };\n if (\n record.instructions !== undefined &&\n (typeof record.instructions !== 'string' || record.instructions.length > WORKSPACE_INSTRUCTIONS_MAX_LENGTH)\n )\n return {\n error: `Workspace instructions must be text up to ${String(WORKSPACE_INSTRUCTIONS_MAX_LENGTH)} characters.`,\n };\n const declaration = typeof record.declaration === 'string' ? record.declaration.trim() : undefined;\n const root =\n typeof record.root === 'string' && record.root.trim() !== '' ? expandHome(record.root.trim()) : undefined;\n const name = typeof record.name === 'string' && record.name.trim() !== '' ? record.name.trim() : undefined;\n if (root === undefined && name === undefined) return { error: 'A workspace root or name is required.' };\n if (root !== undefined && !path.isAbsolute(root))\n return { error: `Use a full folder path, such as ~/${root}, or pick a suggestion.` };\n if (\n [name, declaration].some(\n (value) =>\n value !== undefined &&\n (value.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(value) || value.includes('..')),\n )\n )\n return {\n error: `Workspace names use letters, numbers, spaces, dots, dashes, or underscores (up to ${String(WORKSPACE_NAME_MAX_LENGTH)} characters).`,\n };\n return {\n ...(root === undefined ? {} : { root }),\n ...(name === undefined ? {} : { name }),\n ...(declaration === undefined ? {} : { declaration }),\n ...(typeof record.instructions === 'string' ? { instructions: record.instructions } : {}),\n };\n}\n\nasync function directorySuggestions(query: string, sessions: readonly HeadlessHubSession[]): Promise<string[]> {\n const typed = expandHome(query.trim());\n if (typed === '') return [];\n const matches = (value: string): boolean => value.toLowerCase().includes(typed.toLowerCase());\n const known = [...new Set([process.cwd(), ...sessions.map((session) => session.cwd)])].filter(matches);\n const candidates = path.isAbsolute(typed)\n ? [typed]\n : typed.includes(path.sep)\n ? [path.resolve(process.cwd(), typed)]\n : [path.join(path.dirname(process.cwd()), typed), path.join(process.cwd(), typed)];\n const completed: string[] = [];\n for (const candidate of candidates) {\n const drilling = typed.endsWith(path.sep);\n const parent = drilling ? candidate : path.dirname(candidate);\n const partial = drilling ? '' : path.basename(candidate).toLowerCase();\n try {\n const entries = await fs.readdir(parent, { withFileTypes: true });\n completed.push(\n ...entries\n .filter((entry) => entry.isDirectory() && entry.name.toLowerCase().includes(partial))\n .map((entry) => path.join(parent, entry.name)),\n );\n } catch {\n // A missing or unreadable parent simply has no completions.\n }\n }\n return [...new Set([...known, ...completed.sort((left, right) => left.localeCompare(right))])].slice(\n 0,\n DIRECTORY_SUGGESTION_LIMIT,\n );\n}\n\n/**\n * Lists the visible child directories of one folder for the workspace folder browser.\n * Resolves undefined for a relative, missing, or unreadable path.\n */\nasync function directoryChildren(\n requested: string | null,\n): Promise<{ path: string; parent?: string; directories: string[] } | undefined> {\n const directory = requested === null || requested.trim() === '' ? os.homedir() : expandHome(requested.trim());\n if (!path.isAbsolute(directory)) return undefined;\n const resolved = path.resolve(directory);\n let entries: Dirent[];\n try {\n entries = await fs.readdir(resolved, { withFileTypes: true });\n } catch {\n return undefined;\n }\n const directories = entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))\n .map((entry) => path.join(resolved, entry.name))\n .sort((left, right) => left.localeCompare(right))\n .slice(0, DIRECTORY_CHILDREN_LIMIT);\n const parent = path.dirname(resolved);\n return { path: resolved, ...(parent === resolved ? {} : { parent }), directories };\n}\n\nconst PO_FOLDER_SCAN_DEPTH = 3;\nconst PO_FOLDER_SCAN_VISIT_LIMIT = 2000;\nconst PO_FOLDER_LIMIT = 20;\nconst PO_FOLDER_SKIP = new Set(['node_modules', 'Library']);\n\n/**\n * Folders under home that already hold a `.po` folder, for first-run onboarding.\n * Home itself is skipped: its `.po` is Po's own home, not a workspace.\n */\nasync function poFolders(): Promise<string[]> {\n // ponytail: a bounded breadth-first walk (depth, visits, results); a deeper or\n // indexed search can replace it if people keep projects further down.\n const found: string[] = [];\n let level = [os.homedir()];\n let visited = 0;\n for (let depth = 1; depth <= PO_FOLDER_SCAN_DEPTH && level.length > 0; depth++) {\n const next: string[] = [];\n for (const parent of level) {\n if (visited++ >= PO_FOLDER_SCAN_VISIT_LIMIT || found.length >= PO_FOLDER_LIMIT) return found;\n let entries: Dirent[];\n try {\n entries = await fs.readdir(parent, { withFileTypes: true });\n } catch {\n continue; // An unreadable folder simply has nothing to offer.\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || PO_FOLDER_SKIP.has(entry.name)) continue;\n const child = path.join(parent, entry.name);\n if (\n await fs.access(path.join(child, '.po')).then(\n () => true,\n () => false,\n )\n )\n found.push(child);\n else next.push(child);\n }\n }\n level = next;\n }\n return found.slice(0, PO_FOLDER_LIMIT);\n}\n\nclass RequestBodyTooLargeError extends Error {\n constructor() {\n super('Request body is too large.');\n }\n}\n\nasync function readBody(request: IncomingMessage, limit = MAX_BODY_BYTES): Promise<Uint8Array> {\n const chunks: Buffer[] = [];\n let size = 0;\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n size += buffer.byteLength;\n if (size > limit) throw new RequestBodyTooLargeError();\n chunks.push(buffer);\n }\n return Buffer.concat(chunks);\n}\n\nfunction parseJson(body: Uint8Array): unknown {\n if (body.byteLength === 0) return {};\n return JSON.parse(Buffer.from(body).toString('utf8')) as unknown;\n}\n\nfunction webRequest(request: IncomingMessage, url: URL, signal?: AbortSignal): Request {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n return new Request(url, {\n method: request.method,\n headers,\n signal,\n ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : {\n body: Readable.toWeb(request) as never,\n duplex: 'half' as const,\n }),\n });\n}\n\nasync function writeResponse(\n response: ServerResponse,\n result: Response,\n onChunk?: (bytes: number) => void,\n): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n const body = Readable.fromWeb(result.body as import('node:stream/web').ReadableStream);\n if (onChunk === undefined) {\n await pipeline(body, response);\n return;\n }\n await pipeline(\n body,\n async function* (chunks: AsyncIterable<Uint8Array>) {\n for await (const chunk of chunks) {\n onChunk(chunk.byteLength);\n yield chunk;\n }\n },\n response,\n );\n}\n\n/**\n * Client-neutral HTTP and WebSocket boundary for the process-local headless hub.\n * It deliberately delegates every session operation to HeadlessHub, so transport\n * clients cannot create a second session backend or bypass its lifecycle.\n */\nexport async function serveHeadlessServer(options: HeadlessServerOptions): Promise<HeadlessServer> {\n const clients = new Set<Client>();\n const desktopAuthorized = (request: IncomingMessage): boolean => {\n const proof = request.headers['x-po-desktop'];\n return (\n typeof proof === 'string' &&\n options.headlessHub.computerUse?.authorize?.(new Headers({ 'x-po-desktop': proof })) === true\n );\n };\n const computerUseAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (desktopAuthorized(request)) return true;\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeSession?.(sessionId, headers) === true;\n };\n const activationAuthorized = (request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeActivation?.(headers) === true;\n };\n const pendingAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizePending?.(sessionId, headers) === true;\n };\n const recordingAuthorized = (sessionId: string, request: IncomingMessage): boolean => {\n if (!authorized(request, options.token)) return false;\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers))\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n return options.headlessHub.computerUse?.authorizeRecording?.(sessionId, headers) === true;\n };\n let closed = false;\n const webSockets = new WebSocketServer({\n noServer: true,\n ...(options.webSocketMaxPayload === undefined ? {} : { maxPayload: options.webSocketMaxPayload }),\n });\n const publicRoutes = options.publicRoutes !== false;\n const publicSockets = new WebSocketServer({ noServer: true, maxPayload: PUBLIC_MAX_BYTES });\n type PublicRoute = { path: string; routes: PoApiPublicRoutes; handler: PoApiHandler };\n /** A declared public route of a global API; every other plugin path keeps the host token. */\n const publicRouteFor = (url: URL): PublicRoute | undefined => {\n if (!publicRoutes) return undefined;\n const match = PUBLIC_PLUGIN_PATH.exec(url.pathname);\n if (match === null) return undefined;\n let basePath: string;\n try {\n basePath = decodeURIComponent(match[1]);\n } catch {\n return undefined;\n }\n const api = options.headlessHub.publicApi(basePath);\n const routePath = match[2] ?? '/';\n const declared = api?.routes.paths.some(\n (prefix) => routePath === prefix || routePath.startsWith(prefix.endsWith('/') ? prefix : `${prefix}/`),\n );\n return api === undefined || declared !== true ? undefined : { path: routePath, ...api };\n };\n /** The request a public route sees, without the host's own `token` query parameter. */\n const publicRequest = (request: IncomingMessage, url: URL, route: PublicRoute, body?: Uint8Array): Request => {\n const target = new URL(`http://po.local${route.path}${url.search}`);\n target.searchParams.delete('token');\n return new Request(target, {\n method: request.method,\n headers: publicHeaders(request, options.token),\n ...(body === undefined ? {} : { body: Buffer.from(body) }),\n });\n };\n const servePublicRoute = async (\n request: IncomingMessage,\n response: ServerResponse,\n url: URL,\n route: PublicRoute,\n ): Promise<void> => {\n const refusal = publicRefusal(request);\n if (refusal !== undefined) {\n json(response, refusal, { error: refusal === 404 ? 'Not found.' : 'Forbidden.' });\n return;\n }\n let body: Uint8Array | undefined;\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n try {\n body = await readBody(request, PUBLIC_MAX_BYTES);\n } catch (error) {\n if (!(error instanceof RequestBodyTooLargeError)) throw error;\n json(response, 413, { error: error.message });\n return;\n }\n }\n const forwarded = publicRequest(request, url, route, body);\n if (!(await route.routes.authenticate(forwarded.clone()))) {\n json(response, 401, { error: 'Unauthorized.' });\n return;\n }\n await writeResponse(response, await route.handler.fetch(forwarded));\n };\n const upgradePublicRoute = async (\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n route: PublicRoute,\n ): Promise<void> => {\n const refuse = (status: string): void => {\n socket.write(`HTTP/1.1 ${status}\\r\\n\\r\\n`);\n socket.destroy();\n };\n const refusal = publicRefusal(request);\n const upgrade = route.handler.upgrade?.bind(route.handler);\n if (refusal === 404 || upgrade === undefined) return refuse('404 Not Found');\n if (refusal === 403) return refuse('403 Forbidden');\n const forwarded = publicRequest(request, requestPath(request), route);\n if (!(await route.routes.authenticate(forwarded.clone()))) return refuse('401 Unauthorized');\n if (closed || socket.destroyed) {\n socket.destroy();\n return;\n }\n publicSockets.handleUpgrade(request, socket, head, (client) => {\n const entry: Client = { socket: client };\n clients.add(entry);\n client.on('close', () => clients.delete(entry));\n // An oversized frame lands here; ws then closes the socket with 1009.\n client.on('error', (error) => options.onNotice?.(`Public socket failed: ${error.message}`));\n try {\n upgrade(forwarded, apiSocket(client));\n } catch (error) {\n options.onNotice?.(`Public socket handler failed: ${harnessErrorMessage(error)}`);\n client.close(1011);\n }\n });\n };\n /**\n * A recorded session is dormant exactly while the hub has no session for its\n * id, so reviving one needs no bookkeeping beyond the hub itself.\n */\n const dormant = (): readonly OpenSessionRecord[] =>\n (options.dormantSessions?.() ?? []).filter((record) => options.headlessHub.session(record.sessionId) === undefined);\n const protocol = createHeadlessProtocol({\n hub: options.headlessHub,\n telemetry: options.telemetry,\n onNotice: options.onNotice,\n dormantSessions: dormant,\n });\n const sessionMcpStateDir =\n options.sessionMcpStateDir ?? (await fs.mkdtemp(path.join(os.tmpdir(), 'po-session-mcp-')));\n const sessionMcp = createSessionMcpRoutes({\n headlessHub: options.headlessHub,\n publicOrigin: options.sessionMcpPublicOrigin ?? (() => undefined),\n publicOriginRevision: options.sessionMcpPublicOriginRevision,\n onNotice: options.onNotice,\n isSessionPersisted: options.isSessionPersisted,\n activityStore: await createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: await createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: await createSessionMcpRegistrationStore({\n stateDir: sessionMcpStateDir,\n onNotice: options.onNotice,\n }),\n });\n /** Sessions being restarted, keyed by id, settled once the reopen succeeds or fails. */\n const restarting = new Map<string, Promise<void>>();\n /**\n * Stores already-normalized groups where a session keeps them: the journal of a live\n * session, which announces the change itself, or the record of a dormant one.\n */\n const writeGroups = async (sessionId: string, groups: string[]): Promise<boolean> => {\n const runtime = options.headlessHub.runtime(sessionId);\n if (runtime !== undefined) {\n await runtime.setGroups(groups);\n return true;\n }\n const record = dormant().find((candidate) => candidate.sessionId === sessionId);\n if (record === undefined || options.setDormantGroups === undefined) return false;\n await options.setDormantGroups(record, groups);\n options.headlessHub.notifyDormantChanged(sessionId);\n return true;\n };\n const server = createServer((request, response) => {\n void handleRequest(request, response).catch((error: unknown) => {\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\n if (response.headersSent) {\n response.destroy();\n return;\n }\n // A setup problem the user must fix carries its own instructions; anything else stays generic.\n if (isPoSessionSetupError(error)) json(response, 422, { error: error.message });\n else json(response, 500, { error: 'Internal server error.' });\n });\n });\n\n async function handleRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const url = requestPath(request);\n if (url.pathname === '/api/health' && request.method === 'GET') {\n json(response, 200, {\n ok: true,\n role: HEALTH_ROLE,\n protocol: PROTOCOL_VERSION,\n sessions: options.headlessHub.snapshot().length,\n });\n return;\n }\n if (\n (url.pathname.startsWith('/api/network/') || /^\\/api\\/networks\\/[^/]+\\/network\\//.test(url.pathname)) &&\n options.requestNetwork\n ) {\n const result = await options.requestNetwork(webRequest(request, url));\n if (result) {\n await writeResponse(response, result);\n return;\n }\n }\n const publicRoute = publicRouteFor(url);\n if (publicRoute !== undefined) {\n await servePublicRoute(request, response, url, publicRoute);\n return;\n }\n const scopedSession = /^\\/api\\/workspaces\\/[^/]+\\/sessions\\/([^/]+)(?:\\/|$)/u.exec(url.pathname)?.[1];\n if (\n scopedSession &&\n options.headlessHub.computerUse?.ownsSession?.(decodeURIComponent(scopedSession)) &&\n !computerUseAuthorized(decodeURIComponent(scopedSession), request) &&\n !(\n request.method === 'GET' &&\n url.pathname.endsWith('/plugins/computer-use/artifact') &&\n recordingAuthorized(decodeURIComponent(scopedSession), request)\n ) &&\n !(\n request.method === 'POST' &&\n url.pathname.endsWith('/plugins/computer-use/activate') &&\n activationAuthorized(request)\n ) &&\n !(\n url.pathname.endsWith('/plugins/computer-use/activate') &&\n ((request.method === 'GET' &&\n (pendingAuthorized(decodeURIComponent(scopedSession), request) ||\n recordingAuthorized(decodeURIComponent(scopedSession), request))) ||\n (request.method === 'DELETE' && pendingAuthorized(decodeURIComponent(scopedSession), request)))\n )\n ) {\n json(response, 404, { error: 'This session belongs to its Desktop instance.' });\n return;\n }\n if (publicRoutes && isPublicSessionMcpRoute(request.method ?? 'GET', url.pathname)) {\n const sessionMcpAbort = new AbortController();\n const abortSessionMcp = (): void => {\n if (!response.writableEnded) sessionMcpAbort.abort();\n };\n response.once('close', abortSessionMcp);\n const publicSessionMcp = await sessionMcp.handlePublic(webRequest(request, url, sessionMcpAbort.signal));\n if (publicSessionMcp !== undefined) {\n try {\n await writeResponse(response, publicSessionMcp);\n } finally {\n response.off('close', abortSessionMcp);\n }\n return;\n }\n response.off('close', abortSessionMcp);\n }\n // The optional identity package authenticates its own routes, not with the host attach token.\n const identity =\n publicRoutes && url.pathname.startsWith('/api/auth/') ? options.headlessHub.publicApi('auth') : undefined;\n if (identity) {\n await writeResponse(response, await identity.handler.fetch(webRequest(request, url)));\n return;\n }\n if (!authorized(request, options.token)) {\n json(response, 401, { error: 'Unauthorized.' });\n return;\n }\n // A restart closes the session before reopening it under the same id. Any session-scoped\n // request that lands in that gap, such as a plugin's poll, waits for the reopened session.\n const reopening = scopedSession === undefined ? undefined : restarting.get(decodeURIComponent(scopedSession));\n if (reopening !== undefined && options.headlessHub.session(decodeURIComponent(scopedSession!)) === undefined)\n await reopening;\n if (isSessionMcpHostRoute(url.pathname)) {\n const hostSessionMcp = await sessionMcp.handleHost(webRequest(request, url));\n if (hostSessionMcp !== undefined) {\n await writeResponse(response, hostSessionMcp);\n return;\n }\n }\n if (url.pathname === '/api/remote' || url.pathname.startsWith('/api/remote/')) {\n const headers = new Headers();\n for (const [name, value] of Object.entries(request.headers)) {\n if (value !== undefined && name !== 'authorization' && name !== 'x-po-token')\n headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n const result = await options.headlessHub.requestApi(\n { scope: 'global' },\n 'remote',\n new Request(`http://po.local${url.pathname.slice('/api/remote'.length)}${url.search}`, {\n method: request.method,\n headers,\n ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n await writeResponse(response, result);\n return;\n }\n if (url.pathname === '/api/telemetry/browser' && request.method === 'POST') {\n const body = JSON.parse(new TextDecoder().decode(await readBody(request))) as { v?: unknown; events?: unknown };\n if (body.v !== 1 || !Array.isArray(body.events) || body.events.length > 10) {\n json(response, 400, { error: 'Invalid browser telemetry batch.' });\n return;\n }\n for (const event of body.events) {\n if (\n !event ||\n typeof event !== 'object' ||\n typeof event.name !== 'string' ||\n !/^web\\.browser\\.[a-z_]{1,40}$/u.test(event.name)\n )\n continue;\n if (!options.telemetry) continue;\n const attributes: Record<string, unknown> = {\n ...(typeof event.duration_ms === 'number' && Number.isFinite(event.duration_ms) && event.duration_ms >= 0\n ? { duration_ms: event.duration_ms }\n : {}),\n ...(typeof event.count === 'number' && Number.isFinite(event.count) && event.count >= 0\n ? { count: event.count }\n : {}),\n };\n // UI trace rollups carry a few named scalars; the telemetry sanitizer still filters every key.\n if (event.attributes && typeof event.attributes === 'object' && !Array.isArray(event.attributes))\n for (const [key, value] of Object.entries(event.attributes as Record<string, unknown>).slice(0, 12))\n if (\n /^[a-z_]{1,32}$/u.test(key) &&\n ((typeof value === 'number' && Number.isFinite(value)) ||\n (typeof value === 'string' && value.length <= 256))\n )\n attributes[key] = value;\n observe(\n event.level === 'warn'\n ? options.telemetry.recordWarning(event.name, undefined, attributes)\n : options.telemetry.recordEvent(event.name, attributes),\n );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n const nativeClient = url.searchParams.get('client') === 'native';\n json(response, 200, (await options.compositions?.({ nativeClient })) ?? { workspaces: [] });\n return;\n }\n if (\n (url.pathname.startsWith('/api/web-plugins/') ||\n url.pathname === '/bundle-manifest.json' ||\n url.pathname.startsWith('/bundle-assets/')) &&\n options.requestAsset\n ) {\n const result = await options.requestAsset(new Request(url, { method: request.method }));\n if (result) {\n await writeResponse(response, result);\n return;\n }\n }\n if (url.pathname === '/api/directories/workspaces' && request.method === 'GET' && options.declaredWorkspaces) {\n const requestedPath = url.searchParams.get('path');\n if (!requestedPath?.trim()) {\n json(response, 400, { error: 'A folder path is required.' });\n return;\n }\n try {\n json(response, 200, await options.declaredWorkspaces(expandHome(requestedPath.trim())));\n } catch (error) {\n json(response, 422, { error: harnessErrorMessage(error) });\n }\n return;\n }\n if (url.pathname === '/api/directories/children' && request.method === 'GET') {\n const listing = await directoryChildren(url.searchParams.get('path'));\n if (listing === undefined) json(response, 404, { error: 'That folder cannot be read.' });\n else json(response, 200, listing);\n return;\n }\n if (url.pathname === '/api/directories/po' && request.method === 'GET') {\n json(response, 200, { directories: await poFolders() });\n return;\n }\n if (url.pathname === '/api/directories' && request.method === 'GET') {\n json(response, 200, {\n directories: await directorySuggestions(url.searchParams.get('q') ?? '', options.headlessHub.snapshot()),\n });\n return;\n }\n // Verified browser bundles can remain active across a server upgrade. Keep\n // their former create route working while they refresh to workspace routes.\n if (url.pathname === '/api/sessions' && request.method === 'POST') {\n const body = parseJson(await readBody(request));\n if (\n !body ||\n typeof body !== 'object' ||\n !('cwd' in body) ||\n typeof body.cwd !== 'string' ||\n !body.cwd.trim() ||\n ('name' in body && typeof body.name !== 'string')\n ) {\n json(response, 400, { error: 'A session needs a working directory and an optional name.' });\n return;\n }\n const created = await options.headlessHub.sessionService.create({\n cwd: body.cwd,\n name: 'name' in body ? String(body.name) : path.basename(body.cwd),\n });\n json(response, 201, { sessionId: created.sessionId });\n return;\n }\n const workspaceSessions = /^\\/api\\/workspaces\\/([^/]+)\\/sessions$/u.exec(url.pathname);\n if (workspaceSessions) {\n const workspaceId = decodeURIComponent(workspaceSessions[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (request.method === 'GET') {\n json(response, 200, {\n sessions: [\n ...options.headlessHub\n .snapshot()\n .filter(\n (session) =>\n session.workspaceId === workspaceId &&\n (!options.headlessHub.computerUse?.ownsSession?.(session.id) ||\n computerUseAuthorized(session.id, request)),\n )\n .map(sessionView),\n ...dormant()\n .filter(\n (record) =>\n record.workspaceId === workspaceId &&\n (!options.headlessHub.computerUse?.ownsSession?.(record.sessionId) ||\n computerUseAuthorized(record.sessionId, request)),\n )\n .map((record) =>\n dormantView(record, options.headlessHub.sessionPendingApprovalCount?.(record.sessionId)),\n ),\n ],\n });\n return;\n }\n if (request.method === 'POST') {\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n const body = parseJson(await readBody(request));\n if (!body || typeof body !== 'object' || ('name' in body && typeof body.name !== 'string')) {\n json(response, 400, { error: 'A session accepts an optional name.' });\n return;\n }\n const created = await options.headlessHub.sessionService.create({\n workspaceId,\n cwd: workspace.root,\n name: 'name' in body ? String(body.name) : path.basename(workspace.root),\n });\n json(response, 201, { sessionId: created.sessionId });\n return;\n }\n }\n // Renames a group (PATCH { name }) or removes it (DELETE) on every session this caller can see.\n const groupMatch = /^\\/api\\/session-groups\\/([^/]+)$/u.exec(url.pathname);\n if (groupMatch && (request.method === 'PATCH' || request.method === 'DELETE')) {\n const from = decodeURIComponent(groupMatch[1]);\n let to: string[] = [];\n if (request.method === 'PATCH') {\n const body = parseJson(await readBody(request));\n const name = body && typeof body === 'object' && 'name' in body ? body.name : undefined;\n if (typeof name !== 'string' || name.trim() === '') {\n json(response, 400, { error: 'A group needs a new name.' });\n return;\n }\n to = [name];\n }\n const members = [\n ...options.headlessHub.snapshot().map((session) => ({ id: session.id, groups: session.groups ?? [] })),\n ...dormant().map((record) => ({ id: record.sessionId, groups: record.groups ?? [] })),\n ].filter(\n (member) =>\n member.groups.includes(from) &&\n (!options.headlessHub.computerUse?.ownsSession?.(member.id) || computerUseAuthorized(member.id, request)),\n );\n // Every session's new list is validated before any is written, so a bad name changes nothing.\n let updates: { id: string; groups: string[] }[];\n try {\n updates = members.map((member) => ({\n id: member.id,\n groups: normalizeSessionGroups(member.groups.flatMap((group) => (group === from ? to : [group]))),\n }));\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n for (const update of updates) await writeGroups(update.id, update.groups);\n json(response, 200, { sessions: updates.length });\n return;\n }\n if (url.pathname === '/api/workspaces') {\n if (request.method === 'GET') {\n json(response, 200, { workspaces: options.headlessHub.workspaces() });\n return;\n }\n if (request.method === 'POST') {\n const admission = parseWorkspaceAdmission(parseJson(await readBody(request)));\n if ('error' in admission) {\n json(response, 400, admission);\n return;\n }\n let workspace: Awaited<ReturnType<HeadlessHub['admitWorkspace']>>;\n try {\n workspace = await options.headlessHub.admitWorkspace(admission);\n } catch (error) {\n json(response, 422, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n json(response, 201, { workspace });\n return;\n }\n }\n const workspaceHistoryMatch = /^\\/api\\/workspaces\\/([^/]+)\\/history$/u.exec(url.pathname);\n if (workspaceHistoryMatch && request.method === 'GET' && options.workspaceHistory) {\n const workspaceId = decodeURIComponent(workspaceHistoryMatch[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n json(response, 200, { sessions: await options.workspaceHistory(workspaceId) });\n return;\n }\n const workspaceResumeMatch = /^\\/api\\/workspaces\\/([^/]+)\\/resume$/u.exec(url.pathname);\n if (workspaceResumeMatch && request.method === 'POST' && options.resumeWorkspaceSession) {\n const workspaceId = decodeURIComponent(workspaceResumeMatch[1]);\n const workspace = options.headlessHub.workspaces().find((entry) => entry.id === workspaceId);\n if (!workspace) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (workspace.available === false) {\n json(response, 409, { error: 'Workspace is unavailable.' });\n return;\n }\n const body = parseJson(await readBody(request));\n const targetSessionId =\n body && typeof body === 'object' && 'targetSessionId' in body ? body.targetSessionId : undefined;\n if (typeof targetSessionId !== 'string' || !/^[A-Za-z0-9_-]+$/u.test(targetSessionId)) {\n json(response, 400, { error: 'Invalid target session id.' });\n return;\n }\n json(response, 200, { sessionId: await options.resumeWorkspaceSession(workspaceId, targetSessionId) });\n return;\n }\n const workspaceRemovedMatch = /^\\/api\\/workspaces\\/([^/]+)\\/removed$/u.exec(url.pathname);\n if (workspaceRemovedMatch && request.method === 'GET' && options.removedSessions) {\n const workspaceId = decodeURIComponent(workspaceRemovedMatch[1]);\n if (!options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n json(response, 200, { sessions: await options.removedSessions(workspaceId) });\n return;\n }\n const workspaceRestoreMatch = /^\\/api\\/workspaces\\/([^/]+)\\/removed\\/([^/]+)\\/restore$/u.exec(url.pathname);\n if (workspaceRestoreMatch && request.method === 'POST' && options.restoreRemovedSession) {\n const workspaceId = decodeURIComponent(workspaceRestoreMatch[1]);\n const sessionId = decodeURIComponent(workspaceRestoreMatch[2]);\n if (!options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (!/^[A-Za-z0-9_-]+$/u.test(sessionId)) {\n json(response, 400, { error: 'Invalid session id.' });\n return;\n }\n if (!(await options.restoreRemovedSession(workspaceId, sessionId))) {\n json(response, 409, { error: 'This session is being deleted or is already gone.' });\n return;\n }\n json(response, 200, { ok: true });\n return;\n }\n const workspaceMatch = /^\\/api\\/workspaces\\/([^/]+)$/u.exec(url.pathname);\n if (workspaceMatch && request.method === 'GET') {\n const workspace = options.headlessHub\n .workspaces()\n .find((entry) => entry.id === decodeURIComponent(workspaceMatch[1]));\n json(response, workspace ? 200 : 404, workspace ? { workspace } : { error: 'Workspace not found.' });\n return;\n }\n if (workspaceMatch && request.method === 'PATCH') {\n const id = decodeURIComponent(workspaceMatch[1]);\n const body = parseJson(await readBody(request));\n if (\n !body ||\n typeof body !== 'object' ||\n Array.isArray(body) ||\n Object.keys(body).length !== 1 ||\n (!('sandbox' in body) && !('instructions' in body))\n ) {\n json(response, 400, { error: 'Provide exactly one of sandbox or instructions.' });\n return;\n }\n const instructions = 'instructions' in body ? body.instructions : undefined;\n const sandbox = 'sandbox' in body ? body.sandbox : undefined;\n if ('instructions' in body) {\n if (typeof instructions !== 'string' || instructions.length > WORKSPACE_INSTRUCTIONS_MAX_LENGTH) {\n json(response, 400, {\n error: `Workspace instructions must be text up to ${String(WORKSPACE_INSTRUCTIONS_MAX_LENGTH)} characters.`,\n });\n return;\n }\n } else if (sandbox !== null && (typeof sandbox !== 'string' || sandbox.trim() === '')) {\n json(response, 400, { error: 'The sandbox must be a provider id, or null to run locally.' });\n return;\n }\n if (!options.headlessHub.workspaces().some((workspace) => workspace.id === id)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (typeof instructions === 'string' ? !options.setWorkspaceInstructions : !options.setWorkspaceSandbox) {\n json(response, 404, { error: 'Workspace settings are unavailable.' });\n return;\n }\n const result =\n typeof instructions === 'string'\n ? await options.setWorkspaceInstructions!(id, instructions)\n : await options.setWorkspaceSandbox!(id, sandbox as string | null);\n json(response, 'error' in result ? 409 : 200, result);\n return;\n }\n if (workspaceMatch && request.method === 'DELETE') {\n const id = decodeURIComponent(workspaceMatch[1]);\n if (!options.headlessHub.workspaces().some((workspace) => workspace.id === id)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (\n options.headlessHub.snapshot().some((session) => session.workspaceId === id) ||\n dormant().some((session) => session.workspaceId === id)\n ) {\n json(response, 409, { error: 'Workspace still has sessions.' });\n return;\n }\n await options.headlessHub.removeWorkspace(id);\n json(response, 200, { ok: true });\n return;\n }\n const pluginMatch = PO_PACKAGE_API_PATH_PATTERN.exec(url.pathname);\n if (pluginMatch !== null && request.method !== 'CONNECT') {\n const workspaceId = pluginMatch[1] === undefined ? undefined : decodeURIComponent(pluginMatch[1]);\n const sessionId = pluginMatch[2] === undefined ? undefined : decodeURIComponent(pluginMatch[2]);\n if (workspaceId !== undefined && !options.headlessHub.workspaces().some((entry) => entry.id === workspaceId)) {\n json(response, 404, { error: 'Workspace not found.' });\n return;\n }\n if (sessionId !== undefined && options.headlessHub.session(sessionId)?.workspaceId !== workspaceId) {\n // A stopped session still shows the composition it last published, so its context detail\n // is served from the file it wrote. Nothing else answers until it is woken.\n const stopped = dormant().some(\n (record) => record.sessionId === sessionId && record.workspaceId === workspaceId,\n );\n if (stopped && pluginMatch[3] === CONTEXT_API_BASE_PATH && request.method === 'GET') {\n const detail = await createContextApi({ sessionId, environment: process.env }).fetch(\n new Request(`http://po.local/${pluginMatch[4] ?? ''}${url.search}`),\n );\n const body = (await detail.json()) as { error?: string };\n // The detail file is only kept while the session runs, so a stopped session usually has none.\n if (readContextDetail(sessionId, process.env) === undefined)\n json(response, 404, { error: 'This session is stopped. Wake it to read this item.' });\n else json(response, detail.status, body);\n return;\n }\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n const mount: PoApiMount =\n sessionId !== undefined\n ? { scope: 'session', sessionId }\n : workspaceId !== undefined\n ? { scope: 'workspace', workspaceId }\n : { scope: 'global' };\n const basePath = pluginMatch[3] === undefined ? 'settings' : decodeURIComponent(pluginMatch[3]);\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(basePath)) {\n json(response, 400, { error: 'Invalid package API base path.' });\n return;\n }\n if (pluginMatch[3] === 'settings' || (sessionId !== undefined && basePath === 'settings')) {\n json(response, 404, { error: 'Not found.' });\n return;\n }\n const headers = new Headers();\n // Only the authenticated loopback proxy knows the server token and may\n // forward caller stamps. Browser-supplied stamps remain untrusted.\n const trustedCaller = options.token !== undefined && authorized(request, options.token);\n for (const [name, value] of Object.entries(request.headers)) {\n if (\n value !== undefined &&\n !['host', 'authorization', 'x-po-token'].includes(name) &&\n (trustedCaller || !PO_API_CALLER_HEADERS.includes(name as (typeof PO_API_CALLER_HEADERS)[number]))\n )\n headers.set(name, Array.isArray(value) ? value.join(', ') : value);\n }\n if (!trustedCaller) {\n headers.set(PO_API_CALLER_LOCALITY_HEADER, 'local');\n headers.set(PO_API_CALLER_STEP_UP_HEADER, 'not-required');\n }\n const abort = new AbortController();\n const disconnected = (): void => {\n if (!response.writableEnded) abort.abort();\n };\n response.once('close', disconnected);\n try {\n const started = performance.now();\n const attributes = {\n scope: mount.scope,\n 'plugin.name': basePath,\n 'http.operation': request.method,\n ...(mount.scope === 'workspace' ? { 'workspace.id': mount.workspaceId } : {}),\n ...(mount.scope === 'session' ? { 'session.id': mount.sessionId } : {}),\n };\n let requestBytes = 0;\n const dispatch = async () => {\n const body =\n request.method === 'GET' || request.method === 'HEAD' ? undefined : Buffer.from(await readBody(request));\n requestBytes = body?.byteLength ?? 0;\n return options.headlessHub.requestApi(\n mount,\n basePath,\n new Request(`http://po.local/${pluginMatch[4] ?? ''}${url.search}`, {\n method: request.method,\n headers,\n signal: abort.signal,\n ...(body === undefined ? {} : { body }),\n }),\n );\n };\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n const durationMs = performance.now() - started;\n let responseBytes = 0;\n try {\n await writeResponse(response, result, (bytes) => {\n responseBytes += bytes;\n });\n } finally {\n // Recorded after the body is written, so its size explains heap growth from large replies.\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs,\n request_bytes: requestBytes,\n response_bytes: responseBytes,\n response_kind: contentClass(result.headers.get('content-type')),\n flush_ms: performance.now() - started - durationMs,\n }),\n options.onNotice,\n );\n }\n } finally {\n response.off('close', disconnected);\n }\n return;\n }\n const sessionMatch = /^\\/api\\/workspaces\\/([^/]+)\\/sessions\\/([^/]+)(?:\\/(.*))?$/u.exec(url.pathname);\n if (sessionMatch === null) {\n json(response, 404, { error: 'Not found.' });\n return;\n }\n const sessionId = decodeURIComponent(sessionMatch[2]);\n const workspaceId = decodeURIComponent(sessionMatch[1]);\n const session = options.headlessHub.session(sessionId);\n const suffix = sessionMatch[3] === undefined ? '' : `/${sessionMatch[3]}`;\n if (suffix === '/transcript' && request.method === 'GET' && options.readDormantTranscript) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (record === undefined) {\n json(response, 404, { error: 'Dormant session not found.' });\n return;\n }\n let transcriptRequest: TranscriptPageRequest;\n try {\n transcriptRequest = parseTranscriptRequest(url);\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : 'Invalid transcript request.' });\n return;\n }\n try {\n const page = await options.readDormantTranscript(record, transcriptRequest, BACKGROUND_CONTEXT);\n json(response, 200, page);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const status = message === 'STALE_TRANSCRIPT_CURSOR' ? 409 : 422;\n json(response, status, {\n error: status === 409 ? 'STALE_TRANSCRIPT_CURSOR' : 'Saved transcript is unavailable.',\n });\n }\n return;\n }\n // Groups are set on live and dormant sessions alike: a dormant one keeps them on its record.\n if (suffix === '/groups' && request.method === 'PUT') {\n const known =\n session?.workspaceId === workspaceId ||\n dormant().some((candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId);\n if (!known) {\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n const body = parseJson(await readBody(request));\n let groups: string[];\n try {\n groups = normalizeSessionGroups(body && typeof body === 'object' && 'groups' in body ? body.groups : undefined);\n } catch (error) {\n json(response, 400, { error: error instanceof Error ? error.message : String(error) });\n return;\n }\n if (!(await writeGroups(sessionId, groups))) {\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n json(response, 200, { groups });\n return;\n }\n // Revive is the one session route that answers before a runtime exists: it\n // is what creates one.\n if (sessionMatch[3] === 'revive' && request.method === 'POST' && options.reviveSession) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (record === undefined) {\n json(response, 404, { error: 'Dormant session not found.' });\n return;\n }\n await options.reviveSession(record);\n json(response, 200, { ok: true });\n return;\n }\n if (session === undefined || session.workspaceId !== workspaceId) {\n const record = dormant().find(\n (candidate) => candidate.sessionId === sessionId && candidate.workspaceId === workspaceId,\n );\n if (\n suffix === '' &&\n request.method === 'DELETE' &&\n record !== undefined &&\n options.removeDormantSession !== undefined\n ) {\n await sessionMcp.closeSessionBinding(record.sessionId);\n // A previous live Remove may have failed while stopping. Do not clean its files until that stop is known safe.\n await options.headlessHub.closeSession(record.sessionId, { keepDormant: true });\n await options.removeDormantSession(record);\n options.headlessHub.notifySessionRemoved(record.sessionId);\n json(response, 200, { ok: true });\n return;\n }\n json(response, 404, { error: 'Session not found.' });\n return;\n }\n if (suffix === '' && request.method === 'GET') {\n json(response, 200, sessionView(session));\n return;\n }\n if (suffix === '' && request.method === 'DELETE') {\n await sessionMcp.closeSessionBinding(sessionId);\n // Keep a retryable dormant record until output cleanup succeeds. Shutdown/release never calls this hook.\n await options.headlessHub.closeSession(sessionId, options.removeSessionFiles ? { keepDormant: true } : undefined);\n if (options.removeSessionFiles) {\n await options.removeSessionFiles(sessionId);\n options.headlessHub.notifySessionRemoved(sessionId);\n }\n json(response, 200, { ok: true });\n return;\n }\n if (suffix === '/history' && request.method === 'GET' && options.sessionHistory) {\n json(response, 200, { sessions: await options.sessionHistory(session) });\n return;\n }\n if (suffix === '/avatar' && request.method === 'GET') {\n const avatar = options.headlessHub.sessionAvatar(sessionId);\n if (avatar === undefined) {\n json(response, 404, { error: 'This session has no avatar.' });\n return;\n }\n const current = url.searchParams.get('v') === session.profile?.iconVersion;\n response.writeHead(200, {\n 'content-type': avatar.mimeType,\n 'content-length': String(avatar.bytes.byteLength),\n 'cache-control': current ? 'private, max-age=31536000, immutable' : 'no-store',\n 'x-content-type-options': 'nosniff',\n });\n response.end(avatar.bytes);\n return;\n }\n if (suffix === '/file' && request.method === 'GET') {\n // The session host owns the folders a session may open, so it reads the file.\n const forwarded = new Headers();\n for (const name of ['range', 'if-match'] as const) {\n const value = request.headers[name];\n if (typeof value === 'string') forwarded.set(name, value);\n }\n const target = new URL('http://po.local/');\n const requested = url.searchParams.get('path');\n if (requested !== null) target.searchParams.set('path', requested);\n await writeResponse(\n response,\n await options.headlessHub.requestApi(\n { scope: 'session', sessionId },\n SESSION_FILES_API,\n new Request(target, { headers: forwarded }),\n ),\n );\n return;\n }\n if (suffix === '/attachments' && request.method === 'POST') {\n let bytes: Uint8Array;\n try {\n bytes = await readBody(request);\n } catch (error) {\n if (!(error instanceof RequestBodyTooLargeError)) throw error;\n json(response, 413, { error: 'The attachment exceeds the 8 MB upload limit.' });\n return;\n }\n json(response, 201, await writeSessionAttachment(sessionId, url.searchParams.get('name') ?? 'file', bytes));\n return;\n }\n if (suffix === '/restart' && request.method === 'POST' && options.restartSession) {\n // A restart closes the host, and closing aborts the running turn.\n if ((session.phase ?? 'idle') !== 'idle') {\n json(response, 409, { error: RESTART_WHILE_RUNNING_ERROR });\n return;\n }\n const restart = options.restartSession(session);\n // Settled either way: a failed restart leaves the session dormant, and waiters then see that.\n const settled = restart.then(\n () => undefined,\n () => undefined,\n );\n restarting.set(sessionId, settled);\n try {\n await restart;\n } finally {\n if (restarting.get(sessionId) === settled) restarting.delete(sessionId);\n }\n json(response, 200, { ok: true });\n return;\n }\n if (suffix === '/resume' && request.method === 'POST' && options.resumeSession) {\n const body = parseJson(await readBody(request));\n const targetSessionId =\n body && typeof body === 'object' && 'targetSessionId' in body ? body.targetSessionId : undefined;\n if (typeof targetSessionId !== 'string' || !/^[A-Za-z0-9_-]+$/u.test(targetSessionId)) {\n json(response, 400, { error: 'Invalid target session id.' });\n return;\n }\n if (\n options.headlessHub.computerUse?.ownsSession?.(targetSessionId) &&\n !computerUseAuthorized(targetSessionId, request)\n ) {\n json(response, 404, { error: 'This session belongs to its Desktop instance.' });\n return;\n }\n json(response, 200, { sessionId: await options.resumeSession(session, targetSessionId) });\n return;\n }\n json(response, 404, { error: 'Not found.' });\n }\n\n /** Checks one connection request against its mount; the result says why it may not connect. */\n const accessFor = (request: IncomingMessage): ConnectionAccess | 401 | 404 => {\n const mount = parsePoSocketPath(requestPath(request).pathname);\n if (!mount) return 404;\n if (!authorized(request, options.token)) return 401;\n if (\n mount.scope !== 'global' &&\n (!options.headlessHub.workspaces().some((entry) => entry.id === mount.workspaceId && entry.available !== false) ||\n (mount.scope === 'session' && options.headlessHub.session(mount.sessionId)?.workspaceId !== mount.workspaceId))\n )\n return 404;\n return {\n mount,\n authorizeSession: (id) =>\n !options.headlessHub.computerUse?.ownsSession?.(id) || computerUseAuthorized(id, request),\n authorizeComputerUse: (id) => computerUseAuthorized(id, request),\n authorizeDesktop: () => desktopAuthorized(request),\n };\n };\n\n server.on('upgrade', (request, socket, head) => {\n const networkUrl = requestPath(request);\n if (/^\\/api\\/networks\\/[^/]+\\/relay$/.test(networkUrl.pathname) && options.acceptNetworkRelay) {\n if (closed) {\n socket.destroy();\n return;\n }\n publicSockets.handleUpgrade(request, socket, head, (client) => {\n client.on('error', (error) => {\n options.onNotice?.(`Network relay socket failed: ${harnessErrorMessage(error)}`);\n client.close();\n });\n void options.acceptNetworkRelay!(apiSocket(client), networkUrl).catch((error: unknown) => {\n options.onNotice?.(`Network relay failed: ${harnessErrorMessage(error)}`);\n client.close();\n });\n });\n return;\n }\n const publicRoute = publicRouteFor(networkUrl);\n if (publicRoute !== undefined) {\n void upgradePublicRoute(request, socket, head, publicRoute).catch((error: unknown) => {\n options.onNotice?.(`Public socket upgrade failed: ${harnessErrorMessage(error)}`);\n socket.destroy();\n });\n return;\n }\n const access = accessFor(request);\n if (typeof access === 'number' || closed) {\n if (access === 401) socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n else if (access === 404) socket.write('HTTP/1.1 404 Not Found\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n webSockets.handleUpgrade(request, socket, head, (client) => {\n const entry: Client = { socket: client };\n clients.add(entry);\n client.on('close', () => clients.delete(entry));\n // An invalid or oversized frame lands here; ws then closes the socket (1002 or 1009) instead of an\n // unhandled 'error' event crashing the server.\n client.on('error', (error) => options.onNotice?.(`Protocol socket failed: ${error.message}`));\n // Browser clients send text frames only; refusing packed ones keeps a deflate bomb out.\n protocol.accept(webSocketLink(client as unknown as WebSocketLike, { acceptPacked: false }), access);\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, options.host ?? '127.0.0.1', () => resolve());\n });\n const address = server.address();\n if (address === null || typeof address === 'string') {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n throw new Error('The headless server did not expose a TCP address.');\n }\n const host = options.host ?? '127.0.0.1';\n const url = `http://${host}:${address.port}`;\n return {\n url,\n sessionReservations: sessionMcp.reservations,\n acceptProtocol(pathname, link, headers) {\n // In process, so it carries the token the listener would have checked.\n const access = accessFor({\n url: pathname,\n headers: { ...headers, ...(options.token === undefined ? {} : { 'x-po-token': options.token }) },\n } as IncomingMessage);\n if (typeof access === 'number' || closed) {\n link.close(access === 401 ? 'unauthorized' : 'not found');\n return false;\n }\n protocol.accept(link, access);\n return true;\n },\n async close() {\n if (closed) return;\n closed = true;\n for (const client of clients) client.socket.terminate();\n clients.clear();\n await sessionMcp.close();\n if (options.sessionMcpStateDir === undefined) await fs.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.close();\n for (const socket of publicSockets.clients) socket.terminate();\n publicSockets.close();\n server.closeAllConnections();\n await new Promise<void>((resolve, reject) =>\n server.close((error) => (error === undefined ? resolve() : reject(error))),\n );\n },\n };\n}\n"],"mappings":"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"}
@@ -35,7 +35,10 @@ export interface HeadlessServerOptions {
35
35
  token?: string;
36
36
  telemetry?: ServerTelemetry;
37
37
  onNotice?: (message: string) => void;
38
- compositions?: () => unknown;
38
+ /** `nativeClient` is set when the phone app asks (`?client=native`), so the host can prepare its build. */
39
+ compositions?: (request: {
40
+ nativeClient: boolean;
41
+ }) => unknown;
39
42
  requestAsset?: (request: Request) => Promise<Response | undefined>;
40
43
  /** Independently authenticated by the destination federation boundary. */
41
44
  requestNetwork?: (request: Request) => Promise<Response | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"headlessServer.d.mts","names":[],"sources":["../src/server/headlessServer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;qBA0Da,6BAA2B;;qBAgC3B;iBAGI;EACf,aAAa;EACb;EACA;;EAEA;EACA,YAAY;EACZ,YAAY;EACZ;EACA,gBAAgB,SAAS,YAAY,QAAQ;;EAE7C,kBAAkB,SAAS,YAAY,QAAQ;EAC/C,sBAAsB,QAAQ,aAAa,KAAK,QAAQ;EACxD,kBAAkB,SAAS,uBAAuB,QAAQ;EAC1D,oBAAoB,wBAAwB,QAAQ;EACpD,0BAA0B,qBAAqB,4BAA4B;;EAE3E,mBAAmB,wBAAwB,QAAQ;;EAEnD,yBAAyB,qBAAqB,sBAAsB;;;;;;EAMpE,uBACE,qBACA,2BACG;IAAU,WAAW;;IAAwB;;EAClD,sBAAsB,iBAAiB;IACrC;IACA;MAAgB;MAAc;MAAuB;;;EAEvD,4BACE,qBACA,yBACG;IAAU,WAAW;;IAAwB;;EAClD,yBACE,QAAQ,mBACR,SAAS,uBACT,SAAS,YACN,QAAQ;EACb,kBAAkB,SAAS,uBAAuB;EAClD,iBAAiB,SAAS,oBAAoB,4BAA4B;;EAE1E,iCAAiC;EACjC,wBAAwB,QAAQ,6BAA6B;;EAE7D,sBAAsB,sBAAsB;;EAE5C,oBAAoB,QAAQ,mBAAmB,qCAAqC;EACpF,iBAAiB,QAAQ,sBAAsB;;EAE/C;;EAEA;;EAEA;EACA,sBAAsB,mBAAmB;;;;;EAKzC;;EAEA;;iBAGe;WACN;WACA,qBAAqB;;EAE9B,eAAe,kBAAkB,MAAM,MAAM,SAAS;EACtD,SAAS;;;;;;;wBAoYW,oBAAoB,SAAS,wBAAwB,QAAQ"}
1
+ {"version":3,"file":"headlessServer.d.mts","names":[],"sources":["../src/server/headlessServer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;qBA0Da,6BAA2B;;qBAgC3B;iBAGI;EACf,aAAa;EACb;EACA;;EAEA;EACA,YAAY;EACZ,YAAY;;EAEZ,gBAAgB;IAAW;;EAC3B,gBAAgB,SAAS,YAAY,QAAQ;;EAE7C,kBAAkB,SAAS,YAAY,QAAQ;EAC/C,sBAAsB,QAAQ,aAAa,KAAK,QAAQ;EACxD,kBAAkB,SAAS,uBAAuB,QAAQ;EAC1D,oBAAoB,wBAAwB,QAAQ;EACpD,0BAA0B,qBAAqB,4BAA4B;;EAE3E,mBAAmB,wBAAwB,QAAQ;;EAEnD,yBAAyB,qBAAqB,sBAAsB;;;;;;EAMpE,uBACE,qBACA,2BACG;IAAU,WAAW;;IAAwB;;EAClD,sBAAsB,iBAAiB;IACrC;IACA;MAAgB;MAAc;MAAuB;;;EAEvD,4BACE,qBACA,yBACG;IAAU,WAAW;;IAAwB;;EAClD,yBACE,QAAQ,mBACR,SAAS,uBACT,SAAS,YACN,QAAQ;EACb,kBAAkB,SAAS,uBAAuB;EAClD,iBAAiB,SAAS,oBAAoB,4BAA4B;;EAE1E,iCAAiC;EACjC,wBAAwB,QAAQ,6BAA6B;;EAE7D,sBAAsB,sBAAsB;;EAE5C,oBAAoB,QAAQ,mBAAmB,qCAAqC;EACpF,iBAAiB,QAAQ,sBAAsB;;EAE/C;;EAEA;;EAEA;EACA,sBAAsB,mBAAmB;;;;;EAKzC;;EAEA;;iBAGe;WACN;WACA,qBAAqB;;EAE9B,eAAe,kBAAkB,MAAM,MAAM,SAAS;EACtD,SAAS;;;;;;;wBAoYW,oBAAoB,SAAS,wBAAwB,QAAQ"}
@@ -636,7 +636,8 @@ async function serveHeadlessServer(options) {
636
636
  return;
637
637
  }
638
638
  if (url.pathname === "/api/compositions" && request.method === "GET") {
639
- json(response, 200, await options.compositions?.() ?? { workspaces: [] });
639
+ const nativeClient = url.searchParams.get("client") === "native";
640
+ json(response, 200, await options.compositions?.({ nativeClient }) ?? { workspaces: [] });
640
641
  return;
641
642
  }
642
643
  if ((url.pathname.startsWith("/api/web-plugins/") || url.pathname === "/bundle-manifest.json" || url.pathname.startsWith("/bundle-assets/")) && options.requestAsset) {