@agimon-ai/po-core 0.0.0-alpha.23 → 0.0.0-alpha.25

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.
@@ -159,6 +159,7 @@ function parseWorkspaceAdmission(body) {
159
159
  const root = typeof record.root === "string" && record.root.trim() !== "" ? expandHome(record.root.trim()) : void 0;
160
160
  const name = typeof record.name === "string" && record.name.trim() !== "" ? record.name.trim() : void 0;
161
161
  if (root === void 0 && name === void 0) return { error: "A workspace root or name is required." };
162
+ if (root !== void 0 && !node_path.default.isAbsolute(root)) return { error: `Use a full folder path, such as ~/${root}, or pick a suggestion.` };
162
163
  if (name !== void 0 && (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes(".."))) return { error: `Workspace names use letters, numbers, spaces, dots, dashes, or underscores (up to ${String(WORKSPACE_NAME_MAX_LENGTH)} characters).` };
163
164
  return {
164
165
  ...root === void 0 ? {} : { root },
@@ -1 +1 @@
1
- {"version":3,"file":"headlessServer.cjs","names":["os","path","fs","Readable","pipeline","WebSocketServer","createHeadlessProtocol","createSessionMcpRoutes","createSessionMcpActivityStore","createSessionMcpConversationStore","createSessionMcpRegistrationStore","createServer","harnessErrorMessage","isPoSessionSetupError","isPublicSessionMcpRoute","isSessionMcpHostRoute","normalizeSessionGroups","createContextApi","readContextDetail","PO_API_CALLER_HEADERS","PO_API_CALLER_LOCALITY_HEADER","PO_API_CALLER_STEP_UP_HEADER","BACKGROUND_CONTEXT","SESSION_FILES_API","writeSessionAttachment","parsePoSocketPath","webSocketLink"],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { 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 PoApiMount,\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 { SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\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;\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\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 sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<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\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.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord): 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 ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\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\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 ') && authorization.slice('Bearer '.length) === token) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && header === token) return true;\n try {\n return new URL(request.url ?? '/', 'http://po.local').searchParams.get('token') === token;\n } catch {\n return false;\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 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 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 (\n name !== undefined &&\n (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes('..'))\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 { ...(root === undefined ? {} : { root }), ...(name === undefined ? {} : { name }) };\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.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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 (fs.existsSync(path.join(child, '.po'))) 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): 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 > MAX_BODY_BYTES) 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(response: ServerResponse, result: Response): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n await pipeline(Readable.fromWeb(result.body as import('node:stream/web').ReadableStream), response);\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({ noServer: true });\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 = options.sessionMcpStateDir ?? fs.mkdtempSync(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: createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: createSessionMcpRegistrationStore({ stateDir: sessionMcpStateDir, onNotice: options.onNotice }),\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 if (response.headersSent) {\n response.destroy();\n return;\n }\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\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 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 (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 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)\n observe(\n options.telemetry.recordEvent(event.name, {\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 );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n json(response, 200, 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/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(dormantView),\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 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 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 === '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 const dispatch = async () =>\n 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 ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs: performance.now() - started,\n }),\n options.onNotice,\n );\n await writeResponse(response, result);\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 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 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 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 // 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 sessionMcp.close();\n if (options.sessionMcpStateDir === undefined)\n await fs.promises.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.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":["os","path","fs","Readable","pipeline","WebSocketServer","createHeadlessProtocol","createSessionMcpRoutes","createSessionMcpActivityStore","createSessionMcpConversationStore","createSessionMcpRegistrationStore","createServer","harnessErrorMessage","isPoSessionSetupError","isPublicSessionMcpRoute","isSessionMcpHostRoute","normalizeSessionGroups","createContextApi","readContextDetail","PO_API_CALLER_HEADERS","PO_API_CALLER_LOCALITY_HEADER","PO_API_CALLER_STEP_UP_HEADER","BACKGROUND_CONTEXT","SESSION_FILES_API","writeSessionAttachment","parsePoSocketPath","webSocketLink"],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { 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 PoApiMount,\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 { SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\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;\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\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 sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<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\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.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord): 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 ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\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\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 ') && authorization.slice('Bearer '.length) === token) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && header === token) return true;\n try {\n return new URL(request.url ?? '/', 'http://po.local').searchParams.get('token') === token;\n } catch {\n return false;\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 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 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 !== undefined &&\n (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes('..'))\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 { ...(root === undefined ? {} : { root }), ...(name === undefined ? {} : { name }) };\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.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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 (fs.existsSync(path.join(child, '.po'))) 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): 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 > MAX_BODY_BYTES) 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(response: ServerResponse, result: Response): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n await pipeline(Readable.fromWeb(result.body as import('node:stream/web').ReadableStream), response);\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({ noServer: true });\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 = options.sessionMcpStateDir ?? fs.mkdtempSync(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: createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: createSessionMcpRegistrationStore({ stateDir: sessionMcpStateDir, onNotice: options.onNotice }),\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 if (response.headersSent) {\n response.destroy();\n return;\n }\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\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 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 (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 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)\n observe(\n options.telemetry.recordEvent(event.name, {\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 );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n json(response, 200, 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/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(dormantView),\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 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 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 === '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 const dispatch = async () =>\n 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 ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs: performance.now() - started,\n }),\n options.onNotice,\n );\n await writeResponse(response, result);\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 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 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 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 // 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 sessionMcp.close();\n if (options.sessionMcpStateDir === undefined)\n await fs.promises.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.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 +1 @@
1
- {"version":3,"file":"headlessServer.d.mts","names":[],"sources":["../src/server/headlessServer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;qBAoDa,6BAA2B;;qBAY3B;iBAGI;EACf,aAAa;EACb;EACA;;EAEA;EACA,YAAY;EACZ,YAAY;EACZ;EACA,gBAAgB,SAAS,YAAY,QAAQ;EAC7C,kBAAkB,SAAS,uBAAuB,QAAQ;EAC1D,oBAAoB,wBAAwB,QAAQ;EACpD,0BAA0B,qBAAqB,4BAA4B;EAC3E,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;;iBAG1B;WACN;WACA,qBAAqB;;EAE9B,eAAe,kBAAkB,MAAM,MAAM,SAAS;EACtD,SAAS;;;;;;;wBAwRW,oBAAoB,SAAS,wBAAwB,QAAQ"}
1
+ {"version":3,"file":"headlessServer.d.mts","names":[],"sources":["../src/server/headlessServer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;qBAoDa,6BAA2B;;qBAY3B;iBAGI;EACf,aAAa;EACb;EACA;;EAEA;EACA,YAAY;EACZ,YAAY;EACZ;EACA,gBAAgB,SAAS,YAAY,QAAQ;EAC7C,kBAAkB,SAAS,uBAAuB,QAAQ;EAC1D,oBAAoB,wBAAwB,QAAQ;EACpD,0BAA0B,qBAAqB,4BAA4B;EAC3E,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;;iBAG1B;WACN;WACA,qBAAqB;;EAE9B,eAAe,kBAAkB,MAAM,MAAM,SAAS;EACtD,SAAS;;;;;;;wBA0RW,oBAAoB,SAAS,wBAAwB,QAAQ"}
@@ -154,6 +154,7 @@ function parseWorkspaceAdmission(body) {
154
154
  const root = typeof record.root === "string" && record.root.trim() !== "" ? expandHome(record.root.trim()) : void 0;
155
155
  const name = typeof record.name === "string" && record.name.trim() !== "" ? record.name.trim() : void 0;
156
156
  if (root === void 0 && name === void 0) return { error: "A workspace root or name is required." };
157
+ if (root !== void 0 && !path.isAbsolute(root)) return { error: `Use a full folder path, such as ~/${root}, or pick a suggestion.` };
157
158
  if (name !== void 0 && (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes(".."))) return { error: `Workspace names use letters, numbers, spaces, dots, dashes, or underscores (up to ${String(WORKSPACE_NAME_MAX_LENGTH)} characters).` };
158
159
  return {
159
160
  ...root === void 0 ? {} : { root },
@@ -1 +1 @@
1
- {"version":3,"file":"headlessServer.mjs","names":[],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { 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 PoApiMount,\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 { SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\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;\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\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 sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<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\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.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord): 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 ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\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\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 ') && authorization.slice('Bearer '.length) === token) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && header === token) return true;\n try {\n return new URL(request.url ?? '/', 'http://po.local').searchParams.get('token') === token;\n } catch {\n return false;\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 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 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 (\n name !== undefined &&\n (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes('..'))\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 { ...(root === undefined ? {} : { root }), ...(name === undefined ? {} : { name }) };\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.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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 (fs.existsSync(path.join(child, '.po'))) 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): 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 > MAX_BODY_BYTES) 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(response: ServerResponse, result: Response): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n await pipeline(Readable.fromWeb(result.body as import('node:stream/web').ReadableStream), response);\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({ noServer: true });\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 = options.sessionMcpStateDir ?? fs.mkdtempSync(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: createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: createSessionMcpRegistrationStore({ stateDir: sessionMcpStateDir, onNotice: options.onNotice }),\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 if (response.headersSent) {\n response.destroy();\n return;\n }\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\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 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 (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 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)\n observe(\n options.telemetry.recordEvent(event.name, {\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 );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n json(response, 200, 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/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(dormantView),\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 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 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 === '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 const dispatch = async () =>\n 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 ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs: performance.now() - started,\n }),\n options.onNotice,\n );\n await writeResponse(response, result);\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 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 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 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 // 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 sessionMcp.close();\n if (options.sessionMcpStateDir === undefined)\n await fs.promises.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,8BACX;AAEF,MAAM,cAAc;AACpB,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AACvB,MAAM,6BAA6B;AACnC,MAAM,2BAA2B;AACjC,MAAM,cAAc;AACpB,MAAM,4BAA4B;AAClC,MAAM,yBAAyB;;AAE/B,MAAa,8BACX;AAiDF,SAAS,YAAY,SAAsD;CACzE,OAAO;EACL,IAAI,QAAQ;EACZ,aAAa,QAAQ;EACrB,gBAAgB,QAAQ;EACxB,mBAAmB,QAAQ;EAC3B,MAAM,QAAQ;EACd,KAAK,QAAQ;EACb,WAAW,QAAQ;EACnB,WAAW,QAAQ,aAAa,QAAQ;EACxC,OAAO,QAAQ,SAAS;EACxB,YAAY,QAAQ,cAAc,QAAQ;EAC1C,QAAQ;EACR,qBAAqB,QAAQ,uBAAuB;EACpD,cAAc,QAAQ,gBAAgB;EACtC,eAAe,QAAQ,iBAAiB;EACxC,GAAI,QAAQ,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,QAAQ,cAAc;EACtF,GAAI,QAAQ,yBAAyB,KAAA,IAAY,CAAC,IAAI,EAAE,sBAAsB,QAAQ,qBAAqB;EAC3G,GAAI,QAAQ,QAAQ,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,IAAI,EAAE;EAC/D,GAAI,QAAQ,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,QAAQ,QAAQ,EAAE;EAC3E,GAAI,QAAQ,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,QAAQ,gBAAgB;EAC5F,GAAI,QAAQ,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,QAAQ,kBAAkB;EAClG,GAAI,QAAQ,WAAW,KAAA,KAAa,QAAQ,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,QAAQ,MAAM,EAAE;EACrG,GAAI,QAAQ,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,QAAQ,cAAc;EACtF,GAAI,QAAQ,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,QAAQ,SAAS,EAAE;CAChF;AACF;;AAGA,SAAS,YAAY,QAAoD;CACvE,OAAO;EACL,IAAI,OAAO;EACX,aAAa,OAAO;EACpB,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,WAAW,OAAO;EAClB,WAAW,OAAO;EAClB,OAAO;EACP,YAAY,OAAO;EACnB,QAAQ;EACR,qBAAqB;EACrB,cAAc;EACd,eAAe;EACf,SAAS;EACT,GAAI,OAAO,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO,gBAAgB;EAC1F,GAAI,OAAO,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,OAAO,kBAAkB;EAChG,GAAI,OAAO,WAAW,KAAA,KAAa,OAAO,OAAO,WAAW,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,OAAO,MAAM,EAAE;CACpG;AACF;AAEA,SAAS,KAAK,UAA0B,QAAgB,OAAsB;CAC5E,MAAM,OAAO,KAAK,UAAU,KAAK;CACjC,SAAS,UAAU,QAAQ;EACzB,gBAAgB;EAChB,kBAAkB,OAAO,WAAW,IAAI;CAC1C,CAAC;CACD,SAAS,IAAI,IAAI;AACnB;AAEA,SAAS,WAAW,SAA0B,OAAoC;CAChF,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,MAAM,gBAAgB,QAAQ,QAAQ;CACtC,IAAI,eAAe,WAAW,SAAS,KAAK,cAAc,MAAM,CAAgB,MAAM,OAAO,OAAO;CACpG,MAAM,SAAS,QAAQ,QAAQ;CAC/B,IAAI,OAAO,WAAW,YAAY,WAAW,OAAO,OAAO;CAC3D,IAAI;EACF,OAAO,IAAI,IAAI,QAAQ,OAAO,KAAK,iBAAiB,CAAC,CAAC,aAAa,IAAI,OAAO,MAAM;CACtF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,YAAY,SAA+B;CAClD,OAAO,IAAI,IAAI,QAAQ,OAAO,KAAK,iBAAiB;AACtD;AAEA,SAAS,uBAAuB,KAAiC;CAC/D,MAAM,UAAiC,CAAC;CACxC,MAAM,SAAS,IAAI,aAAa,IAAI,QAAQ;CAC5C,MAAM,YAAY,IAAI,aAAa,IAAI,WAAW;CAClD,MAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;CAC1C,IAAI,WAAW,MAAM,QAAQ,SAAS;CACtC,IAAI,cAAc,MAAM;EACtB,IAAI,cAAc,WAAW,cAAc,SAAS,MAAM,IAAI,MAAM,8BAA8B;EAClG,QAAQ,YAAY;CACtB;CACA,IAAI,UAAU,MAAM;EAClB,IAAI,CAAC,SAAS,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,+BAA+B;EAC1E,MAAM,SAAS,OAAO,KAAK;EAC3B,IAAI,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,KAAK,SAAS,KAAK,MAAM,IAAI,MAAM,+BAA+B;EAChH,QAAQ,QAAQ;CAClB;CACA,OAAO;AACT;;AAGA,SAAS,WAAW,OAAuB;CACzC,IAAI,UAAU,aAAa,OAAO,GAAG,QAAQ;CAC7C,OAAO,MAAM,WAAW,GAAG,cAAc,KAAK,KAAK,IAAI,KAAK,KAAK,GAAG,QAAQ,GAAG,MAAM,MAAM,CAAC,CAAC,IAAI;AACnG;;;;;AAMA,SAAS,wBAAwB,MAA+D;CAC9F,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO,EAAE,OAAO,wCAAwC;CACvG,MAAM,SAAS;CACf,IAAI,OAAO,SAAS,KAAA,KAAa,OAAO,OAAO,SAAS,UACtD,OAAO,EAAE,OAAO,mCAAmC;CACrD,IAAI,OAAO,SAAS,KAAA,KAAa,OAAO,OAAO,SAAS,UACtD,OAAO,EAAE,OAAO,mCAAmC;CACrD,MAAM,OACJ,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,KAAK,MAAM,KAAK,WAAW,OAAO,KAAK,KAAK,CAAC,IAAI,KAAA;CAClG,MAAM,OAAO,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,IAAI,KAAA;CACjG,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GAAW,OAAO,EAAE,OAAO,wCAAwC;CACtG,IACE,SAAS,KAAA,MACR,KAAK,SAAS,6BAA6B,CAAC,uBAAuB,KAAK,IAAI,KAAK,KAAK,SAAS,IAAI,IAEpG,OAAO,EACL,OAAO,qFAAqF,OAAO,yBAAyB,EAAE,eAChI;CACF,OAAO;EAAE,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;EAAI,GAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,KAAK;CAAG;AAC5F;AAEA,eAAe,qBAAqB,OAAe,UAA4D;CAC7G,MAAM,QAAQ,WAAW,MAAM,KAAK,CAAC;CACrC,IAAI,UAAU,IAAI,OAAO,CAAC;CAC1B,MAAM,WAAW,UAA2B,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,YAAY,CAAC;CAC5F,MAAM,QAAQ,CAAC,mBAAG,IAAI,IAAI,CAAC,QAAQ,IAAI,GAAG,GAAG,SAAS,KAAK,YAAY,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,OAAO;CACrG,MAAM,aAAa,KAAK,WAAW,KAAK,IACpC,CAAC,KAAK,IACN,MAAM,SAAS,KAAK,GAAG,IACrB,CAAC,KAAK,QAAQ,QAAQ,IAAI,GAAG,KAAK,CAAC,IACnC,CAAC,KAAK,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,GAAG,KAAK,GAAG,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC;CACrF,MAAM,YAAsB,CAAC;CAC7B,KAAK,MAAM,aAAa,YAAY;EAClC,MAAM,WAAW,MAAM,SAAS,KAAK,GAAG;EACxC,MAAM,SAAS,WAAW,YAAY,KAAK,QAAQ,SAAS;EAC5D,MAAM,UAAU,WAAW,KAAK,KAAK,SAAS,SAAS,CAAC,CAAC,YAAY;EACrE,IAAI;GACF,MAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;GACzE,UAAU,KACR,GAAG,QACA,QAAQ,UAAU,MAAM,YAAY,KAAK,MAAM,KAAK,YAAY,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CACpF,KAAK,UAAU,KAAK,KAAK,QAAQ,MAAM,IAAI,CAAC,CACjD;EACF,QAAQ,CAER;CACF;CACA,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,OAAO,GAAG,UAAU,MAAM,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAC7F,GACA,0BACF;AACF;;;;;AAMA,eAAe,kBACb,WAC+E;CAC/E,MAAM,YAAY,cAAc,QAAQ,UAAU,KAAK,MAAM,KAAK,GAAG,QAAQ,IAAI,WAAW,UAAU,KAAK,CAAC;CAC5G,IAAI,CAAC,KAAK,WAAW,SAAS,GAAG,OAAO,KAAA;CACxC,MAAM,WAAW,KAAK,QAAQ,SAAS;CACvC,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,GAAG,SAAS,QAAQ,UAAU,EAAE,eAAe,KAAK,CAAC;CACvE,QAAQ;EACN;CACF;CACA,MAAM,cAAc,QACjB,QAAQ,UAAU,MAAM,YAAY,KAAK,CAAC,MAAM,KAAK,WAAW,GAAG,CAAC,CAAC,CACrE,KAAK,UAAU,KAAK,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,CAC/C,MAAM,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC,CAAC,CAChD,MAAM,GAAG,wBAAwB;CACpC,MAAM,SAAS,KAAK,QAAQ,QAAQ;CACpC,OAAO;EAAE,MAAM;EAAU,GAAI,WAAW,WAAW,CAAC,IAAI,EAAE,OAAO;EAAI;CAAY;AACnF;AAEA,MAAM,uBAAuB;AAC7B,MAAM,6BAA6B;AACnC,MAAM,kBAAkB;AACxB,MAAM,iCAAiB,IAAI,IAAI,CAAC,gBAAgB,SAAS,CAAC;;;;;AAM1D,eAAe,YAA+B;CAG5C,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ,CAAC,GAAG,QAAQ,CAAC;CACzB,IAAI,UAAU;CACd,KAAK,IAAI,QAAQ,GAAG,SAAS,wBAAwB,MAAM,SAAS,GAAG,SAAS;EAC9E,MAAM,OAAiB,CAAC;EACxB,KAAK,MAAM,UAAU,OAAO;GAC1B,IAAI,aAAa,8BAA8B,MAAM,UAAU,iBAAiB,OAAO;GACvF,IAAI;GACJ,IAAI;IACF,UAAU,MAAM,GAAG,SAAS,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;GACrE,QAAQ;IACN;GACF;GACA,KAAK,MAAM,SAAS,SAAS;IAC3B,IAAI,CAAC,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,KAAK,eAAe,IAAI,MAAM,IAAI,GAAG;IAC1F,MAAM,QAAQ,KAAK,KAAK,QAAQ,MAAM,IAAI;IAC1C,IAAI,GAAG,WAAW,KAAK,KAAK,OAAO,KAAK,CAAC,GAAG,MAAM,KAAK,KAAK;SACvD,KAAK,KAAK,KAAK;GACtB;EACF;EACA,QAAQ;CACV;CACA,OAAO,MAAM,MAAM,GAAG,eAAe;AACvC;AAEA,IAAM,2BAAN,cAAuC,MAAM;CAC3C,cAAc;EACZ,MAAM,4BAA4B;CACpC;AACF;AAEA,eAAe,SAAS,SAA+C;CACrE,MAAM,SAAmB,CAAC;CAC1B,IAAI,OAAO;CACX,WAAW,MAAM,SAAS,SAAS;EACjC,MAAM,SAAS,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;EACjE,QAAQ,OAAO;EACf,IAAI,OAAO,gBAAgB,MAAM,IAAI,yBAAyB;EAC9D,OAAO,KAAK,MAAM;CACpB;CACA,OAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAS,UAAU,MAA2B;CAC5C,IAAI,KAAK,eAAe,GAAG,OAAO,CAAC;CACnC,OAAO,KAAK,MAAM,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC;AACtD;AAEA,SAAS,WAAW,SAA0B,KAAU,QAA+B;CACrF,MAAM,UAAU,IAAI,QAAQ;CAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;CAE5F,OAAO,IAAI,QAAQ,KAAK;EACtB,QAAQ,QAAQ;EAChB;EACA;EACA,GAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAC/C,CAAC,IACD;GACE,MAAM,SAAS,MAAM,OAAO;GAC5B,QAAQ;EACV;CACN,CAAC;AACH;AAEA,eAAe,cAAc,UAA0B,QAAiC;CACtF,SAAS,UAAU,OAAO,QAAQ,OAAO,YAAY,OAAO,QAAQ,QAAQ,CAAC,CAAC;CAC9E,IAAI,OAAO,SAAS,MAAM;EACxB,SAAS,IAAI;EACb;CACF;CACA,MAAM,SAAS,SAAS,QAAQ,OAAO,IAAgD,GAAG,QAAQ;AACpG;;;;;;AAOA,eAAsB,oBAAoB,SAAyD;CACjG,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,qBAAqB,YAAsC;EAC/D,MAAM,QAAQ,QAAQ,QAAQ;EAC9B,OACE,OAAO,UAAU,YACjB,QAAQ,YAAY,aAAa,YAAY,IAAI,QAAQ,EAAE,gBAAgB,MAAM,CAAC,CAAC,MAAM;CAE7F;CACA,MAAM,yBAAyB,WAAmB,YAAsC;EACtF,IAAI,kBAAkB,OAAO,GAAG,OAAO;EACvC,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG,OAAO;EAChD,MAAM,UAAU,IAAI,QAAQ;EAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;EAC5F,OAAO,QAAQ,YAAY,aAAa,mBAAmB,WAAW,OAAO,MAAM;CACrF;CACA,MAAM,wBAAwB,YAAsC;EAClE,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG,OAAO;EAChD,MAAM,UAAU,IAAI,QAAQ;EAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;EAC5F,OAAO,QAAQ,YAAY,aAAa,sBAAsB,OAAO,MAAM;CAC7E;CACA,MAAM,qBAAqB,WAAmB,YAAsC;EAClF,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG,OAAO;EAChD,MAAM,UAAU,IAAI,QAAQ;EAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;EAC5F,OAAO,QAAQ,YAAY,aAAa,mBAAmB,WAAW,OAAO,MAAM;CACrF;CACA,MAAM,uBAAuB,WAAmB,YAAsC;EACpF,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG,OAAO;EAChD,MAAM,UAAU,IAAI,QAAQ;EAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,GAAW,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;EAC5F,OAAO,QAAQ,YAAY,aAAa,qBAAqB,WAAW,OAAO,MAAM;CACvF;CACA,IAAI,SAAS;CACb,MAAM,aAAa,IAAI,gBAAgB,EAAE,UAAU,KAAK,CAAC;;;;;CAKzD,MAAM,iBACH,QAAQ,kBAAkB,KAAK,CAAC,EAAA,CAAG,QAAQ,WAAW,QAAQ,YAAY,QAAQ,OAAO,SAAS,MAAM,KAAA,CAAS;CACpH,MAAM,WAAW,uBAAuB;EACtC,KAAK,QAAQ;EACb,WAAW,QAAQ;EACnB,UAAU,QAAQ;EAClB,iBAAiB;CACnB,CAAC;CACD,MAAM,qBAAqB,QAAQ,sBAAsB,GAAG,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,iBAAiB,CAAC;CACjH,MAAM,aAAa,uBAAuB;EACxC,aAAa,QAAQ;EACrB,cAAc,QAAQ,iCAAiC,KAAA;EACvD,sBAAsB,QAAQ;EAC9B,UAAU,QAAQ;EAClB,oBAAoB,QAAQ;EAC5B,eAAe,8BAA8B,kBAAkB;EAC/D,mBAAmB,kCAAkC,kBAAkB;EACvE,mBAAmB,kCAAkC;GAAE,UAAU;GAAoB,UAAU,QAAQ;EAAS,CAAC;CACnH,CAAC;;CAED,MAAM,6BAAa,IAAI,IAA2B;;;;;CAKlD,MAAM,cAAc,OAAO,WAAmB,WAAuC;EACnF,MAAM,UAAU,QAAQ,YAAY,QAAQ,SAAS;EACrD,IAAI,YAAY,KAAA,GAAW;GACzB,MAAM,QAAQ,UAAU,MAAM;GAC9B,OAAO;EACT;EACA,MAAM,SAAS,QAAQ,CAAC,CAAC,MAAM,cAAc,UAAU,cAAc,SAAS;EAC9E,IAAI,WAAW,KAAA,KAAa,QAAQ,qBAAqB,KAAA,GAAW,OAAO;EAC3E,MAAM,QAAQ,iBAAiB,QAAQ,MAAM;EAC7C,QAAQ,YAAY,qBAAqB,SAAS;EAClD,OAAO;CACT;CACA,MAAM,SAAS,cAAc,SAAS,aAAa;EACjD,cAAmB,SAAS,QAAQ,CAAC,CAAC,OAAO,UAAmB;GAC9D,IAAI,SAAS,aAAa;IACxB,SAAS,QAAQ;IACjB;GACF;GACA,QAAQ,WAAW,4BAA4B,oBAAoB,KAAK,GAAG;GAE3E,IAAI,sBAAsB,KAAK,GAAG,KAAK,UAAU,KAAK,EAAE,OAAO,MAAM,QAAQ,CAAC;QACzE,KAAK,UAAU,KAAK,EAAE,OAAO,yBAAyB,CAAC;EAC9D,CAAC;CACH,CAAC;CAED,eAAe,cAAc,SAA0B,UAAyC;EAC9F,MAAM,MAAM,YAAY,OAAO;EAC/B,IAAI,IAAI,aAAa,iBAAiB,QAAQ,WAAW,OAAO;GAC9D,KAAK,UAAU,KAAK;IAClB,IAAI;IACJ,MAAM;IACN,UAAU;IACV,UAAU,QAAQ,YAAY,SAAS,CAAC,CAAC;GAC3C,CAAC;GACD;EACF;EACA,MAAM,gBAAgB,wDAAwD,KAAK,IAAI,QAAQ,CAAC,GAAG;EACnG,IACE,iBACA,QAAQ,YAAY,aAAa,cAAc,mBAAmB,aAAa,CAAC,KAChF,CAAC,sBAAsB,mBAAmB,aAAa,GAAG,OAAO,KACjE,EACE,QAAQ,WAAW,SACnB,IAAI,SAAS,SAAS,gCAAgC,KACtD,oBAAoB,mBAAmB,aAAa,GAAG,OAAO,MAEhE,EACE,QAAQ,WAAW,UACnB,IAAI,SAAS,SAAS,gCAAgC,KACtD,qBAAqB,OAAO,MAE9B,EACE,IAAI,SAAS,SAAS,gCAAgC,MACpD,QAAQ,WAAW,UAClB,kBAAkB,mBAAmB,aAAa,GAAG,OAAO,KAC3D,oBAAoB,mBAAmB,aAAa,GAAG,OAAO,MAC/D,QAAQ,WAAW,YAAY,kBAAkB,mBAAmB,aAAa,GAAG,OAAO,KAEhG;GACA,KAAK,UAAU,KAAK,EAAE,OAAO,gDAAgD,CAAC;GAC9E;EACF;EACA,IAAI,wBAAwB,QAAQ,UAAU,OAAO,IAAI,QAAQ,GAAG;GAClE,MAAM,kBAAkB,IAAI,gBAAgB;GAC5C,MAAM,wBAA8B;IAClC,IAAI,CAAC,SAAS,eAAe,gBAAgB,MAAM;GACrD;GACA,SAAS,KAAK,SAAS,eAAe;GACtC,MAAM,mBAAmB,MAAM,WAAW,aAAa,WAAW,SAAS,KAAK,gBAAgB,MAAM,CAAC;GACvG,IAAI,qBAAqB,KAAA,GAAW;IAClC,IAAI;KACF,MAAM,cAAc,UAAU,gBAAgB;IAChD,UAAU;KACR,SAAS,IAAI,SAAS,eAAe;IACvC;IACA;GACF;GACA,SAAS,IAAI,SAAS,eAAe;EACvC;EACA,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG;GACvC,KAAK,UAAU,KAAK,EAAE,OAAO,gBAAgB,CAAC;GAC9C;EACF;EAGA,MAAM,YAAY,kBAAkB,KAAA,IAAY,KAAA,IAAY,WAAW,IAAI,mBAAmB,aAAa,CAAC;EAC5G,IAAI,cAAc,KAAA,KAAa,QAAQ,YAAY,QAAQ,mBAAmB,aAAc,CAAC,MAAM,KAAA,GACjG,MAAM;EACR,IAAI,sBAAsB,IAAI,QAAQ,GAAG;GACvC,MAAM,iBAAiB,MAAM,WAAW,WAAW,WAAW,SAAS,GAAG,CAAC;GAC3E,IAAI,mBAAmB,KAAA,GAAW;IAChC,MAAM,cAAc,UAAU,cAAc;IAC5C;GACF;EACF;EACA,IAAI,IAAI,aAAa,iBAAiB,IAAI,SAAS,WAAW,cAAc,GAAG;GAC7E,MAAM,UAAU,IAAI,QAAQ;GAC5B,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IAAI,UAAU,KAAA,KAAa,SAAS,mBAAmB,SAAS,cAC9D,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;GAarE,MAAM,cAAc,UAAU,MAXT,QAAQ,YAAY,WACvC,EAAE,OAAO,SAAS,GAClB,UACA,IAAI,QAAQ,kBAAkB,IAAI,SAAS,MAAM,EAAoB,IAAI,IAAI,UAAU;IACrF,QAAQ,QAAQ;IAChB;IACA,GAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAC/C,CAAC,IACD,EAAE,MAAM,OAAO,KAAK,MAAM,SAAS,OAAO,CAAC,EAAE;GACnD,CAAC,CACH,CACoC;GACpC;EACF;EACA,IAAI,IAAI,aAAa,4BAA4B,QAAQ,WAAW,QAAQ;GAC1E,MAAM,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,MAAM,SAAS,OAAO,CAAC,CAAC;GACzE,IAAI,KAAK,MAAM,KAAK,CAAC,MAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,OAAO,SAAS,IAAI;IAC1E,KAAK,UAAU,KAAK,EAAE,OAAO,mCAAmC,CAAC;IACjE;GACF;GACA,KAAK,MAAM,SAAS,KAAK,QAAQ;IAC/B,IACE,CAAC,SACD,OAAO,UAAU,YACjB,OAAO,MAAM,SAAS,YACtB,CAAC,gCAAgC,KAAK,MAAM,IAAI,GAEhD;IACF,IAAI,QAAQ,WACV,QACE,QAAQ,UAAU,YAAY,MAAM,MAAM;KACxC,GAAI,OAAO,MAAM,gBAAgB,YAAY,OAAO,SAAS,MAAM,WAAW,KAAK,MAAM,eAAe,IACpG,EAAE,aAAa,MAAM,YAAY,IACjC,CAAC;KACL,GAAI,OAAO,MAAM,UAAU,YAAY,OAAO,SAAS,MAAM,KAAK,KAAK,MAAM,SAAS,IAClF,EAAE,OAAO,MAAM,MAAM,IACrB,CAAC;IACP,CAAC,CACH;GACJ;GACA,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;GAChC;EACF;EACA,IAAI,IAAI,aAAa,uBAAuB,QAAQ,WAAW,OAAO;GACpE,KAAK,UAAU,KAAK,QAAQ,eAAe,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;GAClE;EACF;EACA,KACG,IAAI,SAAS,WAAW,mBAAmB,KAC1C,IAAI,aAAa,2BACjB,IAAI,SAAS,WAAW,iBAAiB,MAC3C,QAAQ,cACR;GACA,MAAM,SAAS,MAAM,QAAQ,aAAa,IAAI,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,CAAC;GACtF,IAAI,QAAQ;IACV,MAAM,cAAc,UAAU,MAAM;IACpC;GACF;EACF;EACA,IAAI,IAAI,aAAa,+BAA+B,QAAQ,WAAW,OAAO;GAC5E,MAAM,UAAU,MAAM,kBAAkB,IAAI,aAAa,IAAI,MAAM,CAAC;GACpE,IAAI,YAAY,KAAA,GAAW,KAAK,UAAU,KAAK,EAAE,OAAO,8BAA8B,CAAC;QAClF,KAAK,UAAU,KAAK,OAAO;GAChC;EACF;EACA,IAAI,IAAI,aAAa,yBAAyB,QAAQ,WAAW,OAAO;GACtE,KAAK,UAAU,KAAK,EAAE,aAAa,MAAM,UAAU,EAAE,CAAC;GACtD;EACF;EACA,IAAI,IAAI,aAAa,sBAAsB,QAAQ,WAAW,OAAO;GACnE,KAAK,UAAU,KAAK,EAClB,aAAa,MAAM,qBAAqB,IAAI,aAAa,IAAI,GAAG,KAAK,IAAI,QAAQ,YAAY,SAAS,CAAC,EACzG,CAAC;GACD;EACF;EAGA,IAAI,IAAI,aAAa,mBAAmB,QAAQ,WAAW,QAAQ;GACjE,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;GAC9C,IACE,CAAC,QACD,OAAO,SAAS,YAChB,EAAE,SAAS,SACX,OAAO,KAAK,QAAQ,YACpB,CAAC,KAAK,IAAI,KAAK,KACd,UAAU,QAAQ,OAAO,KAAK,SAAS,UACxC;IACA,KAAK,UAAU,KAAK,EAAE,OAAO,4DAA4D,CAAC;IAC1F;GACF;GAKA,KAAK,UAAU,KAAK,EAAE,YAAW,MAJX,QAAQ,YAAY,eAAe,OAAO;IAC9D,KAAK,KAAK;IACV,MAAM,UAAU,OAAO,OAAO,KAAK,IAAI,IAAI,KAAK,SAAS,KAAK,GAAG;GACnE,CAAC,EAAA,CACwC,UAAU,CAAC;GACpD;EACF;EACA,MAAM,oBAAoB,0CAA0C,KAAK,IAAI,QAAQ;EACrF,IAAI,mBAAmB;GACrB,MAAM,cAAc,mBAAmB,kBAAkB,EAAE;GAC3D,MAAM,YAAY,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW;GAC3F,IAAI,CAAC,WAAW;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,uBAAuB,CAAC;IACrD;GACF;GACA,IAAI,QAAQ,WAAW,OAAO;IAC5B,KAAK,UAAU,KAAK,EAClB,UAAU,CACR,GAAG,QAAQ,YACR,SAAS,CAAC,CACV,QACE,YACC,QAAQ,gBAAgB,gBACvB,CAAC,QAAQ,YAAY,aAAa,cAAc,QAAQ,EAAE,KACzD,sBAAsB,QAAQ,IAAI,OAAO,EAC/C,CAAC,CACA,IAAI,WAAW,GAClB,GAAG,QAAQ,CAAC,CACT,QACE,WACC,OAAO,gBAAgB,gBACtB,CAAC,QAAQ,YAAY,aAAa,cAAc,OAAO,SAAS,KAC/D,sBAAsB,OAAO,WAAW,OAAO,EACrD,CAAC,CACA,IAAI,WAAW,CACpB,EACF,CAAC;IACD;GACF;GACA,IAAI,QAAQ,WAAW,QAAQ;IAC7B,IAAI,UAAU,cAAc,OAAO;KACjC,KAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;KAC1D;IACF;IACA,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;IAC9C,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAa,UAAU,QAAQ,OAAO,KAAK,SAAS,UAAW;KAC1F,KAAK,UAAU,KAAK,EAAE,OAAO,sCAAsC,CAAC;KACpE;IACF;IAKA,KAAK,UAAU,KAAK,EAAE,YAAW,MAJX,QAAQ,YAAY,eAAe,OAAO;KAC9D,KAAK,UAAU;KACf,MAAM,UAAU,OAAO,OAAO,KAAK,IAAI,IAAI,KAAK,SAAS,UAAU,IAAI;IACzE,CAAC,EAAA,CACwC,UAAU,CAAC;IACpD;GACF;EACF;EAEA,MAAM,aAAa,oCAAoC,KAAK,IAAI,QAAQ;EACxE,IAAI,eAAe,QAAQ,WAAW,WAAW,QAAQ,WAAW,WAAW;GAC7E,MAAM,OAAO,mBAAmB,WAAW,EAAE;GAC7C,IAAI,KAAe,CAAC;GACpB,IAAI,QAAQ,WAAW,SAAS;IAC9B,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;IAC9C,MAAM,OAAO,QAAQ,OAAO,SAAS,YAAY,UAAU,OAAO,KAAK,OAAO,KAAA;IAC9E,IAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,IAAI;KAClD,KAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;KAC1D;IACF;IACA,KAAK,CAAC,IAAI;GACZ;GACA,MAAM,UAAU,CACd,GAAG,QAAQ,YAAY,SAAS,CAAC,CAAC,KAAK,aAAa;IAAE,IAAI,QAAQ;IAAI,QAAQ,QAAQ,UAAU,CAAC;GAAE,EAAE,GACrG,GAAG,QAAQ,CAAC,CAAC,KAAK,YAAY;IAAE,IAAI,OAAO;IAAW,QAAQ,OAAO,UAAU,CAAC;GAAE,EAAE,CACtF,CAAC,CAAC,QACC,WACC,OAAO,OAAO,SAAS,IAAI,MAC1B,CAAC,QAAQ,YAAY,aAAa,cAAc,OAAO,EAAE,KAAK,sBAAsB,OAAO,IAAI,OAAO,EAC3G;GAEA,IAAI;GACJ,IAAI;IACF,UAAU,QAAQ,KAAK,YAAY;KACjC,IAAI,OAAO;KACX,QAAQ,uBAAuB,OAAO,OAAO,SAAS,UAAW,UAAU,OAAO,KAAK,CAAC,KAAK,CAAE,CAAC;IAClG,EAAE;GACJ,SAAS,OAAO;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;IACrF;GACF;GACA,KAAK,MAAM,UAAU,SAAS,MAAM,YAAY,OAAO,IAAI,OAAO,MAAM;GACxE,KAAK,UAAU,KAAK,EAAE,UAAU,QAAQ,OAAO,CAAC;GAChD;EACF;EACA,IAAI,IAAI,aAAa,mBAAmB;GACtC,IAAI,QAAQ,WAAW,OAAO;IAC5B,KAAK,UAAU,KAAK,EAAE,YAAY,QAAQ,YAAY,WAAW,EAAE,CAAC;IACpE;GACF;GACA,IAAI,QAAQ,WAAW,QAAQ;IAC7B,MAAM,YAAY,wBAAwB,UAAU,MAAM,SAAS,OAAO,CAAC,CAAC;IAC5E,IAAI,WAAW,WAAW;KACxB,KAAK,UAAU,KAAK,SAAS;KAC7B;IACF;IACA,IAAI;IACJ,IAAI;KACF,YAAY,MAAM,QAAQ,YAAY,eAAe,SAAS;IAChE,SAAS,OAAO;KACd,KAAK,UAAU,KAAK,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;KACrF;IACF;IACA,KAAK,UAAU,KAAK,EAAE,UAAU,CAAC;IACjC;GACF;EACF;EACA,MAAM,wBAAwB,yCAAyC,KAAK,IAAI,QAAQ;EACxF,IAAI,yBAAyB,QAAQ,WAAW,SAAS,QAAQ,kBAAkB;GACjF,MAAM,cAAc,mBAAmB,sBAAsB,EAAE;GAC/D,MAAM,YAAY,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW;GAC3F,IAAI,CAAC,WAAW;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,uBAAuB,CAAC;IACrD;GACF;GACA,IAAI,UAAU,cAAc,OAAO;IACjC,KAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;IAC1D;GACF;GACA,KAAK,UAAU,KAAK,EAAE,UAAU,MAAM,QAAQ,iBAAiB,WAAW,EAAE,CAAC;GAC7E;EACF;EACA,MAAM,uBAAuB,wCAAwC,KAAK,IAAI,QAAQ;EACtF,IAAI,wBAAwB,QAAQ,WAAW,UAAU,QAAQ,wBAAwB;GACvF,MAAM,cAAc,mBAAmB,qBAAqB,EAAE;GAC9D,MAAM,YAAY,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW;GAC3F,IAAI,CAAC,WAAW;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,uBAAuB,CAAC;IACrD;GACF;GACA,IAAI,UAAU,cAAc,OAAO;IACjC,KAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;IAC1D;GACF;GACA,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;GAC9C,MAAM,kBACJ,QAAQ,OAAO,SAAS,YAAY,qBAAqB,OAAO,KAAK,kBAAkB,KAAA;GACzF,IAAI,OAAO,oBAAoB,YAAY,CAAC,oBAAoB,KAAK,eAAe,GAAG;IACrF,KAAK,UAAU,KAAK,EAAE,OAAO,6BAA6B,CAAC;IAC3D;GACF;GACA,KAAK,UAAU,KAAK,EAAE,WAAW,MAAM,QAAQ,uBAAuB,aAAa,eAAe,EAAE,CAAC;GACrG;EACF;EACA,MAAM,iBAAiB,gCAAgC,KAAK,IAAI,QAAQ;EACxE,IAAI,kBAAkB,QAAQ,WAAW,OAAO;GAC9C,MAAM,YAAY,QAAQ,YACvB,WAAW,CAAC,CACZ,MAAM,UAAU,MAAM,OAAO,mBAAmB,eAAe,EAAE,CAAC;GACrE,KAAK,UAAU,YAAY,MAAM,KAAK,YAAY,EAAE,UAAU,IAAI,EAAE,OAAO,uBAAuB,CAAC;GACnG;EACF;EACA,IAAI,kBAAkB,QAAQ,WAAW,UAAU;GACjD,MAAM,KAAK,mBAAmB,eAAe,EAAE;GAC/C,IAAI,CAAC,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,cAAc,UAAU,OAAO,EAAE,GAAG;IAC9E,KAAK,UAAU,KAAK,EAAE,OAAO,uBAAuB,CAAC;IACrD;GACF;GACA,IACE,QAAQ,YAAY,SAAS,CAAC,CAAC,MAAM,YAAY,QAAQ,gBAAgB,EAAE,KAC3E,QAAQ,CAAC,CAAC,MAAM,YAAY,QAAQ,gBAAgB,EAAE,GACtD;IACA,KAAK,UAAU,KAAK,EAAE,OAAO,gCAAgC,CAAC;IAC9D;GACF;GACA,MAAM,QAAQ,YAAY,gBAAgB,EAAE;GAC5C,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;GAChC;EACF;EACA,MAAM,cAAc,4BAA4B,KAAK,IAAI,QAAQ;EACjE,IAAI,gBAAgB,QAAQ,QAAQ,WAAW,WAAW;GACxD,MAAM,cAAc,YAAY,OAAO,KAAA,IAAY,KAAA,IAAY,mBAAmB,YAAY,EAAE;GAChG,MAAM,YAAY,YAAY,OAAO,KAAA,IAAY,KAAA,IAAY,mBAAmB,YAAY,EAAE;GAC9F,IAAI,gBAAgB,KAAA,KAAa,CAAC,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW,GAAG;IAC5G,KAAK,UAAU,KAAK,EAAE,OAAO,uBAAuB,CAAC;IACrD;GACF;GACA,IAAI,cAAc,KAAA,KAAa,QAAQ,YAAY,QAAQ,SAAS,CAAC,EAAE,gBAAgB,aAAa;IAMlG,IAHgB,QAAQ,CAAC,CAAC,MACvB,WAAW,OAAO,cAAc,aAAa,OAAO,gBAAgB,WAE7D,KAAK,YAAY,OAAA,aAAgC,QAAQ,WAAW,OAAO;KACnF,MAAM,SAAS,MAAM,iBAAiB;MAAE;MAAW,aAAa,QAAQ;KAAI,CAAC,CAAC,CAAC,MAC7E,IAAI,QAAQ,mBAAmB,YAAY,MAAM,KAAK,IAAI,QAAQ,CACpE;KACA,MAAM,OAAQ,MAAM,OAAO,KAAK;KAEhC,IAAI,kBAAkB,WAAW,QAAQ,GAAG,MAAM,KAAA,GAChD,KAAK,UAAU,KAAK,EAAE,OAAO,sDAAsD,CAAC;UACjF,KAAK,UAAU,OAAO,QAAQ,IAAI;KACvC;IACF;IACA,KAAK,UAAU,KAAK,EAAE,OAAO,qBAAqB,CAAC;IACnD;GACF;GACA,MAAM,QACJ,cAAc,KAAA,IACV;IAAE,OAAO;IAAW;GAAU,IAC9B,gBAAgB,KAAA,IACd;IAAE,OAAO;IAAa;GAAY,IAClC,EAAE,OAAO,SAAS;GAC1B,MAAM,WAAW,YAAY,OAAO,KAAA,IAAY,aAAa,mBAAmB,YAAY,EAAE;GAC9F,IAAI,CAAC,mCAAmC,KAAK,QAAQ,GAAG;IACtD,KAAK,UAAU,KAAK,EAAE,OAAO,iCAAiC,CAAC;IAC/D;GACF;GACA,IAAI,YAAY,OAAO,cAAe,cAAc,KAAA,KAAa,aAAa,YAAa;IACzF,KAAK,UAAU,KAAK,EAAE,OAAO,aAAa,CAAC;IAC3C;GACF;GACA,MAAM,UAAU,IAAI,QAAQ;GAG5B,MAAM,gBAAgB,QAAQ,UAAU,KAAA,KAAa,WAAW,SAAS,QAAQ,KAAK;GACtF,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GACxD,IACE,UAAU,KAAA,KACV,CAAC;IAAC;IAAQ;IAAiB;GAAY,CAAC,CAAC,SAAS,IAAI,MACrD,iBAAiB,CAAC,sBAAsB,SAAS,IAA8C,IAEhG,QAAQ,IAAI,MAAM,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK;GAErE,IAAI,CAAC,eAAe;IAClB,QAAQ,IAAI,+BAA+B,OAAO;IAClD,QAAQ,IAAI,8BAA8B,cAAc;GAC1D;GACA,MAAM,QAAQ,IAAI,gBAAgB;GAClC,MAAM,qBAA2B;IAC/B,IAAI,CAAC,SAAS,eAAe,MAAM,MAAM;GAC3C;GACA,SAAS,KAAK,SAAS,YAAY;GACnC,IAAI;IACF,MAAM,UAAU,YAAY,IAAI;IAChC,MAAM,aAAa;KACjB,OAAO,MAAM;KACb,eAAe;KACf,kBAAkB,QAAQ;KAC1B,GAAI,MAAM,UAAU,cAAc,EAAE,gBAAgB,MAAM,YAAY,IAAI,CAAC;KAC3E,GAAI,MAAM,UAAU,YAAY,EAAE,cAAc,MAAM,UAAU,IAAI,CAAC;IACvE;IACA,MAAM,WAAW,YACf,QAAQ,YAAY,WAClB,OACA,UACA,IAAI,QAAQ,mBAAmB,YAAY,MAAM,KAAK,IAAI,UAAU;KAClE,QAAQ,QAAQ;KAChB;KACA,QAAQ,MAAM;KACd,GAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAC/C,CAAC,IACD,EAAE,MAAM,OAAO,KAAK,MAAM,SAAS,OAAO,CAAC,EAAE;IACnD,CAAC,CACH;IACF,MAAM,SAAS,QAAQ,YACnB,MAAM,QAAQ,UAAU,UAAU,4BAA4B,YAAY,QAAQ,IAClF,MAAM,SAAS;IACnB,IAAI,QAAQ,WACV,QACE,QAAQ,UAAU,YAAY,6BAA6B;KACzD,GAAG;KACH,QAAQ,OAAO;KACf,YAAY,YAAY,IAAI,IAAI;IAClC,CAAC,GACD,QAAQ,QACV;IACF,MAAM,cAAc,UAAU,MAAM;GACtC,UAAU;IACR,SAAS,IAAI,SAAS,YAAY;GACpC;GACA;EACF;EACA,MAAM,eAAe,8DAA8D,KAAK,IAAI,QAAQ;EACpG,IAAI,iBAAiB,MAAM;GACzB,KAAK,UAAU,KAAK,EAAE,OAAO,aAAa,CAAC;GAC3C;EACF;EACA,MAAM,YAAY,mBAAmB,aAAa,EAAE;EACpD,MAAM,cAAc,mBAAmB,aAAa,EAAE;EACtD,MAAM,UAAU,QAAQ,YAAY,QAAQ,SAAS;EACrD,MAAM,SAAS,aAAa,OAAO,KAAA,IAAY,KAAK,IAAI,aAAa;EACrE,IAAI,WAAW,iBAAiB,QAAQ,WAAW,SAAS,QAAQ,uBAAuB;GACzF,MAAM,SAAS,QAAQ,CAAC,CAAC,MACtB,cAAc,UAAU,cAAc,aAAa,UAAU,gBAAgB,WAChF;GACA,IAAI,WAAW,KAAA,GAAW;IACxB,KAAK,UAAU,KAAK,EAAE,OAAO,6BAA6B,CAAC;IAC3D;GACF;GACA,IAAI;GACJ,IAAI;IACF,oBAAoB,uBAAuB,GAAG;GAChD,SAAS,OAAO;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,8BAA8B,CAAC;IACrG;GACF;GACA,IAAI;IAEF,KAAK,UAAU,KAAK,MADD,QAAQ,sBAAsB,QAAQ,mBAAmB,kBAAkB,CACtE;GAC1B,SAAS,OAAO;IAEd,MAAM,UADU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,OAC1C,4BAA4B,MAAM;IAC7D,KAAK,UAAU,QAAQ,EACrB,OAAO,WAAW,MAAM,4BAA4B,mCACtD,CAAC;GACH;GACA;EACF;EAEA,IAAI,WAAW,aAAa,QAAQ,WAAW,OAAO;GAIpD,IAAI,EAFF,SAAS,gBAAgB,eACzB,QAAQ,CAAC,CAAC,MAAM,cAAc,UAAU,cAAc,aAAa,UAAU,gBAAgB,WAAW,IAC9F;IACV,KAAK,UAAU,KAAK,EAAE,OAAO,qBAAqB,CAAC;IACnD;GACF;GACA,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;GAC9C,IAAI;GACJ,IAAI;IACF,SAAS,uBAAuB,QAAQ,OAAO,SAAS,YAAY,YAAY,OAAO,KAAK,SAAS,KAAA,CAAS;GAChH,SAAS,OAAO;IACd,KAAK,UAAU,KAAK,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;IACrF;GACF;GACA,IAAI,CAAE,MAAM,YAAY,WAAW,MAAM,GAAI;IAC3C,KAAK,UAAU,KAAK,EAAE,OAAO,qBAAqB,CAAC;IACnD;GACF;GACA,KAAK,UAAU,KAAK,EAAE,OAAO,CAAC;GAC9B;EACF;EAGA,IAAI,aAAa,OAAO,YAAY,QAAQ,WAAW,UAAU,QAAQ,eAAe;GACtF,MAAM,SAAS,QAAQ,CAAC,CAAC,MACtB,cAAc,UAAU,cAAc,aAAa,UAAU,gBAAgB,WAChF;GACA,IAAI,WAAW,KAAA,GAAW;IACxB,KAAK,UAAU,KAAK,EAAE,OAAO,6BAA6B,CAAC;IAC3D;GACF;GACA,MAAM,QAAQ,cAAc,MAAM;GAClC,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;GAChC;EACF;EACA,IAAI,YAAY,KAAA,KAAa,QAAQ,gBAAgB,aAAa;GAChE,MAAM,SAAS,QAAQ,CAAC,CAAC,MACtB,cAAc,UAAU,cAAc,aAAa,UAAU,gBAAgB,WAChF;GACA,IACE,WAAW,MACX,QAAQ,WAAW,YACnB,WAAW,KAAA,KACX,QAAQ,yBAAyB,KAAA,GACjC;IACA,WAAW,oBAAoB,OAAO,SAAS;IAE/C,MAAM,QAAQ,YAAY,aAAa,OAAO,WAAW,EAAE,aAAa,KAAK,CAAC;IAC9E,MAAM,QAAQ,qBAAqB,MAAM;IACzC,QAAQ,YAAY,qBAAqB,OAAO,SAAS;IACzD,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;IAChC;GACF;GACA,KAAK,UAAU,KAAK,EAAE,OAAO,qBAAqB,CAAC;GACnD;EACF;EACA,IAAI,WAAW,MAAM,QAAQ,WAAW,OAAO;GAC7C,KAAK,UAAU,KAAK,YAAY,OAAO,CAAC;GACxC;EACF;EACA,IAAI,WAAW,MAAM,QAAQ,WAAW,UAAU;GAChD,WAAW,oBAAoB,SAAS;GAExC,MAAM,QAAQ,YAAY,aAAa,WAAW,QAAQ,qBAAqB,EAAE,aAAa,KAAK,IAAI,KAAA,CAAS;GAChH,IAAI,QAAQ,oBAAoB;IAC9B,MAAM,QAAQ,mBAAmB,SAAS;IAC1C,QAAQ,YAAY,qBAAqB,SAAS;GACpD;GACA,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;GAChC;EACF;EACA,IAAI,WAAW,cAAc,QAAQ,WAAW,SAAS,QAAQ,gBAAgB;GAC/E,KAAK,UAAU,KAAK,EAAE,UAAU,MAAM,QAAQ,eAAe,OAAO,EAAE,CAAC;GACvE;EACF;EACA,IAAI,WAAW,aAAa,QAAQ,WAAW,OAAO;GACpD,MAAM,SAAS,QAAQ,YAAY,cAAc,SAAS;GAC1D,IAAI,WAAW,KAAA,GAAW;IACxB,KAAK,UAAU,KAAK,EAAE,OAAO,8BAA8B,CAAC;IAC5D;GACF;GACA,MAAM,UAAU,IAAI,aAAa,IAAI,GAAG,MAAM,QAAQ,SAAS;GAC/D,SAAS,UAAU,KAAK;IACtB,gBAAgB,OAAO;IACvB,kBAAkB,OAAO,OAAO,MAAM,UAAU;IAChD,iBAAiB,UAAU,yCAAyC;IACpE,0BAA0B;GAC5B,CAAC;GACD,SAAS,IAAI,OAAO,KAAK;GACzB;EACF;EACA,IAAI,WAAW,WAAW,QAAQ,WAAW,OAAO;GAElD,MAAM,YAAY,IAAI,QAAQ;GAC9B,KAAK,MAAM,QAAQ,CAAC,SAAS,UAAU,GAAY;IACjD,MAAM,QAAQ,QAAQ,QAAQ;IAC9B,IAAI,OAAO,UAAU,UAAU,UAAU,IAAI,MAAM,KAAK;GAC1D;GACA,MAAM,SAAS,IAAI,IAAI,kBAAkB;GACzC,MAAM,YAAY,IAAI,aAAa,IAAI,MAAM;GAC7C,IAAI,cAAc,MAAM,OAAO,aAAa,IAAI,QAAQ,SAAS;GACjE,MAAM,cACJ,UACA,MAAM,QAAQ,YAAY,WACxB;IAAE,OAAO;IAAW;GAAU,GAC9B,mBACA,IAAI,QAAQ,QAAQ,EAAE,SAAS,UAAU,CAAC,CAC5C,CACF;GACA;EACF;EACA,IAAI,WAAW,kBAAkB,QAAQ,WAAW,QAAQ;GAC1D,IAAI;GACJ,IAAI;IACF,QAAQ,MAAM,SAAS,OAAO;GAChC,SAAS,OAAO;IACd,IAAI,EAAE,iBAAiB,2BAA2B,MAAM;IACxD,KAAK,UAAU,KAAK,EAAE,OAAO,gDAAgD,CAAC;IAC9E;GACF;GACA,KAAK,UAAU,KAAK,MAAM,uBAAuB,WAAW,IAAI,aAAa,IAAI,MAAM,KAAK,QAAQ,KAAK,CAAC;GAC1G;EACF;EACA,IAAI,WAAW,cAAc,QAAQ,WAAW,UAAU,QAAQ,gBAAgB;GAEhF,KAAK,QAAQ,SAAS,YAAY,QAAQ;IACxC,KAAK,UAAU,KAAK,EAAE,OAAO,4BAA4B,CAAC;IAC1D;GACF;GACA,MAAM,UAAU,QAAQ,eAAe,OAAO;GAE9C,MAAM,UAAU,QAAQ,WAChB,KAAA,SACA,KAAA,CACR;GACA,WAAW,IAAI,WAAW,OAAO;GACjC,IAAI;IACF,MAAM;GACR,UAAU;IACR,IAAI,WAAW,IAAI,SAAS,MAAM,SAAS,WAAW,OAAO,SAAS;GACxE;GACA,KAAK,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;GAChC;EACF;EACA,IAAI,WAAW,aAAa,QAAQ,WAAW,UAAU,QAAQ,eAAe;GAC9E,MAAM,OAAO,UAAU,MAAM,SAAS,OAAO,CAAC;GAC9C,MAAM,kBACJ,QAAQ,OAAO,SAAS,YAAY,qBAAqB,OAAO,KAAK,kBAAkB,KAAA;GACzF,IAAI,OAAO,oBAAoB,YAAY,CAAC,oBAAoB,KAAK,eAAe,GAAG;IACrF,KAAK,UAAU,KAAK,EAAE,OAAO,6BAA6B,CAAC;IAC3D;GACF;GACA,IACE,QAAQ,YAAY,aAAa,cAAc,eAAe,KAC9D,CAAC,sBAAsB,iBAAiB,OAAO,GAC/C;IACA,KAAK,UAAU,KAAK,EAAE,OAAO,gDAAgD,CAAC;IAC9E;GACF;GACA,KAAK,UAAU,KAAK,EAAE,WAAW,MAAM,QAAQ,cAAc,SAAS,eAAe,EAAE,CAAC;GACxF;EACF;EACA,KAAK,UAAU,KAAK,EAAE,OAAO,aAAa,CAAC;CAC7C;;CAGA,MAAM,aAAa,YAA2D;EAC5E,MAAM,QAAQ,kBAAkB,YAAY,OAAO,CAAC,CAAC,QAAQ;EAC7D,IAAI,CAAC,OAAO,OAAO;EACnB,IAAI,CAAC,WAAW,SAAS,QAAQ,KAAK,GAAG,OAAO;EAChD,IACE,MAAM,UAAU,aACf,CAAC,QAAQ,YAAY,WAAW,CAAC,CAAC,MAAM,UAAU,MAAM,OAAO,MAAM,eAAe,MAAM,cAAc,KAAK,KAC3G,MAAM,UAAU,aAAa,QAAQ,YAAY,QAAQ,MAAM,SAAS,CAAC,EAAE,gBAAgB,MAAM,cAEpG,OAAO;EACT,OAAO;GACL;GACA,mBAAmB,OACjB,CAAC,QAAQ,YAAY,aAAa,cAAc,EAAE,KAAK,sBAAsB,IAAI,OAAO;GAC1F,uBAAuB,OAAO,sBAAsB,IAAI,OAAO;GAC/D,wBAAwB,kBAAkB,OAAO;EACnD;CACF;CAEA,OAAO,GAAG,YAAY,SAAS,QAAQ,SAAS;EAC9C,MAAM,SAAS,UAAU,OAAO;EAChC,IAAI,OAAO,WAAW,YAAY,QAAQ;GACxC,IAAI,WAAW,KAAK,OAAO,MAAM,mCAAmC;QAC/D,IAAI,WAAW,KAAK,OAAO,MAAM,gCAAgC;GACtE,OAAO,QAAQ;GACf;EACF;EACA,WAAW,cAAc,SAAS,QAAQ,OAAO,WAAW;GAC1D,MAAM,QAAgB,EAAE,QAAQ,OAAO;GACvC,QAAQ,IAAI,KAAK;GACjB,OAAO,GAAG,eAAe,QAAQ,OAAO,KAAK,CAAC;GAE9C,SAAS,OAAO,cAAc,QAAoC,EAAE,cAAc,MAAM,CAAC,GAAG,MAAM;EACpG,CAAC;CACH,CAAC;CAED,MAAM,IAAI,SAAe,SAAS,WAAW;EAC3C,OAAO,KAAK,SAAS,MAAM;EAC3B,OAAO,OAAO,QAAQ,MAAM,QAAQ,QAAQ,mBAAmB,QAAQ,CAAC;CAC1E,CAAC;CACD,MAAM,UAAU,OAAO,QAAQ;CAC/B,IAAI,YAAY,QAAQ,OAAO,YAAY,UAAU;EACnD,MAAM,IAAI,SAAe,YAAY,OAAO,YAAY,QAAQ,CAAC,CAAC;EAClE,MAAM,IAAI,MAAM,mDAAmD;CACrE;CAGA,OAAO;EACL,KAAA,UAHW,QAAQ,QAAQ,YACF,GAAG,QAAQ;EAGpC,qBAAqB,WAAW;EAChC,eAAe,UAAU,MAAM,SAAS;GAEtC,MAAM,SAAS,UAAU;IACvB,KAAK;IACL,SAAS;KAAE,GAAG;KAAS,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,cAAc,QAAQ,MAAM;IAAG;GACjG,CAAoB;GACpB,IAAI,OAAO,WAAW,YAAY,QAAQ;IACxC,KAAK,MAAM,WAAW,MAAM,iBAAiB,WAAW;IACxD,OAAO;GACT;GACA,SAAS,OAAO,MAAM,MAAM;GAC5B,OAAO;EACT;EACA,MAAM,QAAQ;GACZ,IAAI,QAAQ;GACZ,SAAS;GACT,KAAK,MAAM,UAAU,SAAS,OAAO,OAAO,UAAU;GACtD,QAAQ,MAAM;GACd,WAAW,MAAM;GACjB,IAAI,QAAQ,uBAAuB,KAAA,GACjC,MAAM,GAAG,SAAS,GAAG,oBAAoB;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;GAC3E,MAAM,SAAS,MAAM;GACrB,WAAW,MAAM;GACjB,OAAO,oBAAoB;GAC3B,MAAM,IAAI,SAAe,SAAS,WAChC,OAAO,OAAO,UAAW,UAAU,KAAA,IAAY,QAAQ,IAAI,OAAO,KAAK,CAAE,CAC3E;EACF;CACF;AACF"}
1
+ {"version":3,"file":"headlessServer.mjs","names":[],"sources":["../src/server/headlessServer.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createServer, type IncomingHttpHeaders, type IncomingMessage, type ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { 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 PoApiMount,\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 { SavedSession } from '../services/sqliteSessionHistory';\nimport { createContextApi } from './contextApi';\nimport { harnessErrorMessage } from './harnessErrorMessage';\nimport type { HeadlessHub, HeadlessHubSession, HeadlessWorkspaceAdmission } from './headlessHub';\nimport { createHeadlessProtocol, type ConnectionAccess } from './headlessProtocol';\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;\nconst DIRECTORY_SUGGESTION_LIMIT = 12;\nconst DIRECTORY_CHILDREN_LIMIT = 500;\nconst HOME_PREFIX = '~';\nconst WORKSPACE_NAME_MAX_LENGTH = 80;\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 sessionHistory?: (session: HeadlessHubSession) => Promise<SavedSession[]>;\n workspaceHistory?: (workspaceId: string) => Promise<SavedSession[]>;\n resumeWorkspaceSession?: (workspaceId: string, targetSessionId: string) => Promise<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\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.groups === undefined || session.groups.length === 0 ? {} : { groups: [...session.groups] }),\n ...(session.pendingSetups === undefined ? {} : { pendingSetups: session.pendingSetups }),\n ...(session.activity === undefined ? {} : { activity: { ...session.activity } }),\n };\n}\n\n/** The dormant counterpart of `sessionView`; same shape, no runtime behind it. */\nfunction dormantView(record: OpenSessionRecord): 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 ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\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\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 ') && authorization.slice('Bearer '.length) === token) return true;\n const header = request.headers['x-po-token'];\n if (typeof header === 'string' && header === token) return true;\n try {\n return new URL(request.url ?? '/', 'http://po.local').searchParams.get('token') === token;\n } catch {\n return false;\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 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 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 !== undefined &&\n (name.length > WORKSPACE_NAME_MAX_LENGTH || !WORKSPACE_NAME_PATTERN.test(name) || name.includes('..'))\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 { ...(root === undefined ? {} : { root }), ...(name === undefined ? {} : { name }) };\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.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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: fs.Dirent[];\n try {\n entries = await fs.promises.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 (fs.existsSync(path.join(child, '.po'))) 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): 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 > MAX_BODY_BYTES) 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(response: ServerResponse, result: Response): Promise<void> {\n response.writeHead(result.status, Object.fromEntries(result.headers.entries()));\n if (result.body === null) {\n response.end();\n return;\n }\n await pipeline(Readable.fromWeb(result.body as import('node:stream/web').ReadableStream), response);\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({ noServer: true });\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 = options.sessionMcpStateDir ?? fs.mkdtempSync(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: createSessionMcpActivityStore(sessionMcpStateDir),\n conversationStore: createSessionMcpConversationStore(sessionMcpStateDir),\n registrationStore: createSessionMcpRegistrationStore({ stateDir: sessionMcpStateDir, onNotice: options.onNotice }),\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 if (response.headersSent) {\n response.destroy();\n return;\n }\n options.onNotice?.(`Headless request failed: ${harnessErrorMessage(error)}`);\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 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 (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 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)\n observe(\n options.telemetry.recordEvent(event.name, {\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 );\n }\n json(response, 200, { ok: true });\n return;\n }\n if (url.pathname === '/api/compositions' && request.method === 'GET') {\n json(response, 200, 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/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(dormantView),\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 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 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 === '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 const dispatch = async () =>\n 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 ...(request.method === 'GET' || request.method === 'HEAD'\n ? {}\n : { body: Buffer.from(await readBody(request)) }),\n }),\n );\n const result = options.telemetry\n ? await options.telemetry.runInSpan('po_server.plugin.request', attributes, dispatch)\n : await dispatch();\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('po_server.plugin.response', {\n ...attributes,\n status: result.status,\n durationMs: performance.now() - started,\n }),\n options.onNotice,\n );\n await writeResponse(response, result);\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 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 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 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 // 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 sessionMcp.close();\n if (options.sessionMcpStateDir === undefined)\n await fs.promises.rm(sessionMcpStateDir, { recursive: true, force: true });\n await protocol.close();\n webSockets.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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"}
package/dist/native.cjs CHANGED
@@ -30,7 +30,9 @@ exports.defineNativeTemplate = require_webPlugin.defineNativeTemplate;
30
30
  exports.defineSelectionAxis = require_webPlugin.defineSelectionAxis;
31
31
  exports.defineSessionChannel = require_webPlugin.defineSessionChannel;
32
32
  exports.defineSessionStore = require_sessionStore.defineSessionStore;
33
+ exports.defineSettingsPanel = require_webPlugin.defineSettingsPanel;
33
34
  exports.defineSettingsSection = require_webPlugin.defineSettingsSection;
35
+ exports.defineSlot = require_webPlugin.defineSlot;
34
36
  exports.defineSlotFile = require_webPlugin.defineSlotFile;
35
37
  exports.defineTab = require_webPlugin.defineTab;
36
38
  exports.defineToolRenderer = require_webPlugin.defineToolRenderer;
package/dist/native.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, HomeContribution, HomeCoverage, HomeEntity, HomeItem, HomeKind, HomeProjection, HomeRequest, HomeSnapshot, HomeSourceStatus, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot } from "./src/schemas/home.mjs";
2
2
  import { WebTemplateRailActions, WebTemplateRailDirectoryListing, WebTemplateRailPendingSetup, WebTemplateRailSession, WebTemplateRailWorkspace } from "./src/web/types/template.mjs";
3
3
  import { NativeTemplateContribution, NativeTemplateScreens, NativeTemplateSessionsActions, NativeTemplateSessionsProps } from "./src/web/types/nativeTemplate.mjs";
4
- import { ActivityGroupContribution, GlobalStore, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsSectionContribution, SlotDeclaration, SlotFillContribution, TabContribution, TabHeader, ToolMessageRenderProps, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, UserMessageActionContribution, UserMessageActionRunContext, WebPluginContributions, WebPluginDefinition, WebPluginRuntime, WebPluginSessionContext, WebPluginSlotProps, WorkspaceRecords, WorkspaceStore } from "./src/web/types/webPlugin.mjs";
5
- import { ActivityGroupFile, ChannelFile, FillFile, NativeTemplateFile, SelectionAxisFile, SettingsSectionFile, SlotFile, TabFile, ToolRendererFile, UserMessageActionFile } from "./src/web/types/extensionFile.mjs";
6
- import { defineActivityGroup, defineChannelFile, defineFileLinks, defineFill, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSettingsSection, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWebPlugin } from "./src/extensions/webPlugin.mjs";
4
+ import { ActivityGroupContribution, GlobalStore, SelectionAxisContribution, SessionChannelContribution, SessionFrameSender, SessionRecords, SessionStore, SessionStoreChannel, SettingsPanelContribution, SettingsPanelProps, SettingsSectionContribution, SlotDeclaration, SlotFillContribution, TabContribution, TabHeader, ToolMessageRenderProps, ToolPromptRenderProps, ToolRendererContribution, ToolResultView, UserMessageActionContribution, UserMessageActionRunContext, WebPluginContributions, WebPluginDefinition, WebPluginRuntime, WebPluginSessionContext, WebPluginSlotProps, WorkspaceRecords, WorkspaceStore } from "./src/web/types/webPlugin.mjs";
5
+ import { ActivityGroupFile, ChannelFile, FillFile, NativeTemplateFile, SelectionAxisFile, SettingsPanelFile, SettingsSectionFile, SlotFile, TabFile, ToolRendererFile, UserMessageActionFile } from "./src/web/types/extensionFile.mjs";
6
+ import { defineActivityGroup, defineChannelFile, defineFileLinks, defineFill, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSettingsPanel, defineSettingsSection, defineSlot, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWebPlugin } from "./src/extensions/webPlugin.mjs";
7
7
  import { defineGlobalStore } from "./src/web/models/globalStore.mjs";
8
8
  import { defineSessionStore } from "./src/web/models/sessionStore.mjs";
9
9
  import { defineWorkspaceStore } from "./src/web/models/workspaceStore.mjs";
@@ -13,4 +13,4 @@ import { sessionApiAddress, sessionApiPath } from "./src/web/services/apiRoutes/
13
13
  import { nativeApiTransport } from "./src/web/services/nativeApiTransport/index.mjs";
14
14
  import { parseNativeTemplate } from "./src/web/schemas/template.mjs";
15
15
  import { NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX } from "./src/constants/nativeHost.mjs";
16
- export { type ActivityGroupContribution, type ActivityGroupFile, type ApiCallInit, type ApiResult, type ApiRoutes, type ApiTransport, type ChannelFile, type FillFile, type GlobalStore, HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, HomeContribution, HomeCoverage, HomeEntity, HomeItem, HomeKind, HomeProjection, HomeRequest, HomeSnapshot, HomeSourceStatus, NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX, type NativeTemplateContribution, type NativeTemplateFile, type NativeTemplateScreens, type NativeTemplateSessionsActions, type NativeTemplateSessionsProps, type SelectionAxisContribution, type SelectionAxisFile, type SessionChannelContribution, type SessionFrameSender, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsSectionContribution, type SettingsSectionFile, type SlotDeclaration, type SlotFile, type SlotFillContribution, type TabContribution, type TabFile, type TabHeader, type ToolMessageRenderProps, type ToolPromptRenderProps, type ToolRendererContribution, type ToolRendererFile, type ToolResultView, type UserMessageActionContribution, type UserMessageActionFile, type UserMessageActionRunContext, type WebPluginContributions, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSessionContext, type WebPluginSlotProps, type WebTemplateRailActions, type WebTemplateRailDirectoryListing, type WebTemplateRailPendingSetup, type WebTemplateRailSession, type WebTemplateRailWorkspace, type WorkspaceRecords, type WorkspaceStore, apiResponse, createApiClient, defineActivityGroup, defineApiRoutes, defineChannelFile, defineFileLinks, defineFill, defineGlobalStore, defineWebPlugin as defineNativePlugin, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSessionStore, defineSettingsSection, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWorkspaceStore, nativeApiTransport, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot, parseNativeTemplate, sessionApiAddress, sessionApiPath, toolResultText, toolResultTextLines };
16
+ export { type ActivityGroupContribution, type ActivityGroupFile, type ApiCallInit, type ApiResult, type ApiRoutes, type ApiTransport, type ChannelFile, type FillFile, type GlobalStore, HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, HomeContribution, HomeCoverage, HomeEntity, HomeItem, HomeKind, HomeProjection, HomeRequest, HomeSnapshot, HomeSourceStatus, NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX, type NativeTemplateContribution, type NativeTemplateFile, type NativeTemplateScreens, type NativeTemplateSessionsActions, type NativeTemplateSessionsProps, type SelectionAxisContribution, type SelectionAxisFile, type SessionChannelContribution, type SessionFrameSender, type SessionRecords, type SessionStore, type SessionStoreChannel, type SettingsPanelContribution, type SettingsPanelFile, type SettingsPanelProps, type SettingsSectionContribution, type SettingsSectionFile, type SlotDeclaration, type SlotFile, type SlotFillContribution, type TabContribution, type TabFile, type TabHeader, type ToolMessageRenderProps, type ToolPromptRenderProps, type ToolRendererContribution, type ToolRendererFile, type ToolResultView, type UserMessageActionContribution, type UserMessageActionFile, type UserMessageActionRunContext, type WebPluginContributions, type WebPluginDefinition, type WebPluginRuntime, type WebPluginSessionContext, type WebPluginSlotProps, type WebTemplateRailActions, type WebTemplateRailDirectoryListing, type WebTemplateRailPendingSetup, type WebTemplateRailSession, type WebTemplateRailWorkspace, type WorkspaceRecords, type WorkspaceStore, apiResponse, createApiClient, defineActivityGroup, defineApiRoutes, defineChannelFile, defineFileLinks, defineFill, defineGlobalStore, defineWebPlugin as defineNativePlugin, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSessionStore, defineSettingsPanel, defineSettingsSection, defineSlot, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWorkspaceStore, nativeApiTransport, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot, parseNativeTemplate, sessionApiAddress, sessionApiPath, toolResultText, toolResultTextLines };
package/dist/native.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot } from "./src/schemas/home.mjs";
2
- import { defineActivityGroup, defineChannelFile, defineFileLinks, defineFill, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSettingsSection, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWebPlugin } from "./src/extensions/webPlugin.mjs";
2
+ import { defineActivityGroup, defineChannelFile, defineFileLinks, defineFill, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSettingsPanel, defineSettingsSection, defineSlot, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWebPlugin } from "./src/extensions/webPlugin.mjs";
3
3
  import { defineGlobalStore } from "./src/web/models/globalStore.mjs";
4
4
  import { defineSessionStore } from "./src/web/models/sessionStore.mjs";
5
5
  import { defineWorkspaceStore } from "./src/web/models/workspaceStore.mjs";
@@ -9,4 +9,4 @@ import { sessionApiAddress, sessionApiPath } from "./src/web/services/apiRoutes/
9
9
  import { nativeApiTransport } from "./src/web/services/nativeApiTransport/index.mjs";
10
10
  import { parseNativeTemplate } from "./src/web/schemas/template.mjs";
11
11
  import { NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX } from "./src/constants/nativeHost.mjs";
12
- export { HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX, apiResponse, createApiClient, defineActivityGroup, defineApiRoutes, defineChannelFile, defineFileLinks, defineFill, defineGlobalStore, defineWebPlugin as defineNativePlugin, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSessionStore, defineSettingsSection, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWorkspaceStore, nativeApiTransport, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot, parseNativeTemplate, sessionApiAddress, sessionApiPath, toolResultText, toolResultTextLines };
12
+ export { HOME_ENTITY_LIMIT, HOME_KINDS, HOME_PAGE_LIMIT, NATIVE_HOST_MODULES, NATIVE_HOST_MODULE_IDS, NATIVE_UNISTYLES_COMPONENTS, NATIVE_UNISTYLES_COMPONENT_PREFIX, apiResponse, createApiClient, defineActivityGroup, defineApiRoutes, defineChannelFile, defineFileLinks, defineFill, defineGlobalStore, defineWebPlugin as defineNativePlugin, defineNativeTemplate, defineSelectionAxis, defineSessionChannel, defineSessionStore, defineSettingsPanel, defineSettingsSection, defineSlot, defineSlotFile, defineTab, defineToolRenderer, defineUserMessageAction, defineWebLifecycle, defineWorkspaceStore, nativeApiTransport, parseHomeContribution, parseHomeEntity, parseHomeProjection, parseHomeSnapshot, parseNativeTemplate, sessionApiAddress, sessionApiPath, toolResultText, toolResultTextLines };
@@ -528,20 +528,24 @@ export interface SettingsPanelProps {
528
528
  request: (input: string, init?: RequestInit) => Promise<Response>;
529
529
  /** The same transport, retrying once after the host's fresh passkey gesture. */
530
530
  requestWithStepUp: (input: string, init?: RequestInit) => Promise<Response>;
531
+ /**
532
+ * Host navigation to another settings page, such as the sign-in a panel
533
+ * needs. Matches the slot props' `openSettings`; absent where the host has none.
534
+ */
535
+ openSettings?: (section: string) => void;
531
536
  }
532
537
  /**
533
- * A settings page a package draws itself, for a page that reports rather
534
- * than writes.
538
+ * A settings page a package draws itself.
535
539
  *
536
540
  * A contributed section is data because the host owns what a plugin cannot:
537
541
  * which file an edit lands in. That reasoning runs out when a page has
538
- * nothing to write. A page whose content is a chart, a table, or anything
539
- * else the host cannot know the shape of has no keyPath to declare and no
540
- * scope to switch, so declaring it as fields would mean inventing a field
541
- * kind per picture. Such a page takes a component and the host's transport,
542
- * exactly as a repository panel does, and gives up the scope switch and the
543
- * write plumbing it would not use. A package that needs both contributes
544
- * both, and the two appear in the menu as two pages.
542
+ * nothing to write, or when a host draws a page the section fields cannot
543
+ * shape. A page whose content is a chart, a table, or a layout of its own
544
+ * takes a component and the host's transport, exactly as a repository panel
545
+ * does, and gives up the scope switch. A panel that writes owns its own
546
+ * write plumbing: it saves global keys through `requestWithStepUp`, as the
547
+ * native Voice page does. A package that needs both contributes both, and the
548
+ * two appear in the menu as two pages.
545
549
  */
546
550
  export interface SettingsPanelContribution {
547
551
  /** The URL segment (/settings/:id) and testid suffix; unique across plugins. */
@@ -1 +1 @@
1
- {"version":3,"file":"webPlugin.d.mts","names":[],"sources":["../../../../src/web/types/webPlugin.ts"],"mappings":"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"}
1
+ {"version":3,"file":"webPlugin.d.mts","names":[],"sources":["../../../../src/web/types/webPlugin.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-core",
3
- "version": "0.0.0-alpha.23",
3
+ "version": "0.0.0-alpha.25",
4
4
  "description": "Po runtime systems and reusable core services.",
5
5
  "keywords": [
6
6
  "ai",
@@ -529,8 +529,8 @@
529
529
  "registry": "https://registry.npmjs.org/"
530
530
  },
531
531
  "dependencies": {
532
- "@agimon-ai/po-telemetry": "0.0.0-alpha.23",
533
- "@agimon-ai/po-web-security": "0.0.0-alpha.23",
532
+ "@agimon-ai/po-telemetry": "0.0.0-alpha.25",
533
+ "@agimon-ai/po-web-security": "0.0.0-alpha.25",
534
534
  "@deepseek-ai/cordis": "4.0.5",
535
535
  "@earendil-works/chord": "1.3.0",
536
536
  "@earendil-works/pi-agent-core": "1.3.0",
@@ -553,7 +553,7 @@
553
553
  "yaml": "2.9.1"
554
554
  },
555
555
  "devDependencies": {
556
- "@agimon-ai/vibe-lint-plugin-po-core": "0.0.0-alpha.23",
556
+ "@agimon-ai/vibe-lint-plugin-po-core": "0.0.0-alpha.25",
557
557
  "@apidevtools/swagger-parser": "^13.1.0",
558
558
  "@asyncapi/parser": "^3.6.4",
559
559
  "@earendil-works/pi-ai": "1.3.0",