@agimon-ai/po-core 0.0.0-alpha.5 → 0.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/headlessHub.cjs +5 -2
- package/dist/headlessHub.cjs.map +1 -1
- package/dist/headlessHub.mjs +5 -2
- package/dist/headlessHub.mjs.map +1 -1
- package/dist/moduleResolution.cjs +11 -0
- package/dist/moduleResolution.cjs.map +1 -1
- package/dist/moduleResolution.d.mts +2 -0
- package/dist/moduleResolution.d.mts.map +1 -1
- package/dist/moduleResolution.mjs +11 -1
- package/dist/moduleResolution.mjs.map +1 -1
- package/dist/src/schemas/hubChannel.cjs.map +1 -1
- package/dist/src/schemas/hubChannel.d.mts +2 -2
- package/dist/src/schemas/hubChannel.mjs.map +1 -1
- package/dist/src/services/headlessClient/index.cjs +17 -10
- package/dist/src/services/headlessClient/index.cjs.map +1 -1
- package/dist/src/services/headlessClient/index.mjs +17 -10
- package/dist/src/services/headlessClient/index.mjs.map +1 -1
- package/dist/src/systems/main/adapters/headlessSessionHost.cjs +1 -0
- package/dist/src/systems/main/adapters/headlessSessionHost.cjs.map +1 -1
- package/dist/src/systems/main/adapters/headlessSessionHost.mjs +1 -0
- package/dist/src/systems/main/adapters/headlessSessionHost.mjs.map +1 -1
- package/package.json +4 -4
package/dist/headlessHub.cjs
CHANGED
|
@@ -254,13 +254,16 @@ function createHeadlessHub(options) {
|
|
|
254
254
|
if (!canCommunicate(sessionId, peerSessionId)) return void 0;
|
|
255
255
|
const peer = sessions.get(peerSessionId);
|
|
256
256
|
if (peer === void 0) return void 0;
|
|
257
|
-
const
|
|
257
|
+
const source = sessions.get(sessionId);
|
|
258
|
+
const own = source.groups ?? [];
|
|
259
|
+
const sharedGroups = (peer.groups ?? []).filter((group) => own.includes(group));
|
|
260
|
+
if (source.parentSessionId !== peer.id && peer.parentSessionId !== source.id && sharedGroups.length === 0) return void 0;
|
|
258
261
|
const profile = peer.profile?.displayName ?? peer.profile?.name;
|
|
259
262
|
return {
|
|
260
263
|
sessionId: peerSessionId,
|
|
261
264
|
name: peer.name,
|
|
262
265
|
...profile === void 0 ? {} : { profile },
|
|
263
|
-
sharedGroups
|
|
266
|
+
sharedGroups
|
|
264
267
|
};
|
|
265
268
|
},
|
|
266
269
|
close() {
|
package/dist/headlessHub.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headlessHub.cjs","names":["SessionMetadataDoc","BACKGROUND_CONTEXT","readSessionGitStatus","createNodePlatform","createPoPluginRegistry","crypto","createPoServerHost","installServerFacets","parseHomeProjection","PROFILE_ICON_MIME_TYPES"],"sources":["../src/server/headlessHub.ts"],"sourcesContent":["import crypto from 'node:crypto';\n\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\n\nimport { AGENT_SETTLED_ENTRY_TYPE } from '../constants/agentSettled';\nimport type { PoHeadlessSelection } from '../exports/headless';\nimport type {\n PoComputerUseHostBinding,\n PoDirectEventBus,\n PoHubChannel,\n PoHubChannelConnection,\n PoHubChannelHost,\n PoHubReservedWorktreeProvisioner,\n PoHubSessionApiRequest,\n PoHubSessionCreateRequest,\n PoHubSessionScope,\n PoHubSessionService,\n PoSessionCommunicationEndpoint,\n PoHubSessionReservations,\n PoPendingSessionSetup,\n PoSessionActivity,\n} from '../exports/hubChannel';\nimport { REMOTE_CONVERSATION_SESSION_PROVENANCE } from '../exports/hubChannel';\nimport type { PoNativeComposition, PoWebComposition } from '../exports/packageApi';\nimport type { PoApiContext, PoApiMount, PoEditPresenceLedger } from '../exports/packageApi';\nimport {\n createPoPluginRegistry,\n type PoPluginCaller,\n type PoPluginDirection,\n type PoPluginRegistry,\n} from '../exports/pluginProtocol';\nimport {\n createPoServerHost,\n installServerFacets,\n type PoServerFacet,\n type PoServerHost,\n type InstalledServerFacets,\n type LoadedServerFacet,\n} from '../exports/serverFacet';\nimport {\n HOME_ENTITY_LIMIT,\n HOME_PAGE_LIMIT,\n parseHomeProjection,\n type HomeRequest,\n type HomeSnapshot,\n type HomeItem,\n type HomeSourceStatus,\n} from '../schemas/home';\nimport { PO_NOTIFICATION_ENTRY_TYPE } from '../schemas/notification';\nimport type { PoPlatform } from '../schemas/platform';\nimport { PROFILE_ICON_MIME_TYPES } from '../schemas/profileIdentity';\nimport { SESSION_GROUPS_CHANGED_FRAME } from '../schemas/sessionProtocol';\nimport { createNodePlatform } from '../services/nodePlatform';\nimport { SessionMetadataDoc } from '../services/sessionDocs';\nimport { readSessionGitStatus } from '../services/sessionGitStatus';\nimport type { SessionGitStatus } from '../services/sessionGitStatus/type';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '../systems/main/types/headlessSessionHost';\nimport type { HeadlessSessionCloseOptions, HeadlessSessionManager } from '../systems/main/types/headlessSessionManager';\n\nconst AUTHORIZATION_HEADER = 'authorization';\nconst CHANNEL_PRIORITY = { global: 0, workspace: 1, session: 2 } as const;\nconst ICON_VERSION_LENGTH = 12;\nconst ICON_DATA_URL = /^data:([a-z/+.-]+);base64,([A-Za-z0-9+/=]+)$/u;\n/** A rail line, not a log: a longer label is cut to this. */\nconst MAX_ACTIVITY_LABEL = 80;\n\n/** The profile a session runs under, as shown on its rail card. The icon itself is served separately. */\nexport interface HeadlessSessionProfile {\n readonly name: string;\n readonly displayName?: string;\n /** Changes whenever the icon does, so a client can cache the avatar by it. */\n readonly iconVersion?: string;\n}\n\n/** A profile's persona presentation: display name and icon as a data: URL. */\nexport interface HeadlessProfileIdentity {\n readonly displayName?: string;\n readonly icon?: string;\n}\n\nexport interface HeadlessHubSession {\n readonly id: string;\n readonly workspaceId?: string;\n webComposition?: PoWebComposition;\n nativeComposition?: PoNativeComposition;\n readonly name: string;\n readonly cwd: string;\n readonly createdAt: string;\n readonly parentSessionId?: string;\n readonly sessionProvenance?: string;\n /** User-assigned groups; sessions sharing one may message each other. Empty when none. */\n readonly groups?: readonly string[];\n readonly updatedAt?: string;\n readonly phase?: 'idle' | 'turn' | 'compaction' | 'retry';\n readonly phaseSince?: string;\n readonly pendingMessageCount?: number;\n readonly everPrompted?: boolean;\n readonly awaitingInput?: boolean;\n readonly lastSettledAt?: string;\n /** Branch and dirty flag of the session cwd; absent outside a git work tree. */\n readonly git?: SessionGitStatus;\n /** Selected profile; absent when the session runs without one. */\n readonly profile?: HeadlessSessionProfile;\n readonly pendingSetups?: readonly PoPendingSessionSetup[];\n /** The line the session's extension last published about work it runs; absent when none. */\n readonly activity?: PoSessionActivity;\n /** Environment admitted for this session, when supplied by the host. */\n readonly environment?: Readonly<Record<string, string | undefined>>;\n readonly host: HeadlessSessionHost;\n}\n\nexport interface HeadlessWorkspace {\n readonly id: string;\n readonly root: string;\n readonly name?: string;\n readonly available?: boolean;\n}\n\n/** A workspace to admit: an existing folder, or a name alone for a new default folder. */\nexport interface HeadlessWorkspaceAdmission {\n readonly root?: string;\n readonly name?: string;\n}\n\nexport type HeadlessHubEvent =\n | { kind: 'upsert'; session: HeadlessHubSession }\n /** `dormant`: the session stopped running but keeps its record, so it lists as dormant. */\n | { kind: 'removed'; sessionId: string; dormant?: true }\n /** A dormant session's record changed; clients reread it from the dormant list. */\n | { kind: 'dormant_changed'; sessionId: string }\n | { kind: 'workspace_upsert'; workspace: HeadlessWorkspace }\n | { kind: 'workspace_removed'; workspaceId: string }\n | { kind: 'channel'; frameType: string; sessionId: string; payload: unknown; connectionId?: string }\n /** A live session frame every hub client needs: notification entries and agent dialogs. */\n | { kind: 'frame'; sessionId: string; frame: Record<string, unknown> };\n\nexport interface HeadlessHubOptions {\n manager: HeadlessSessionManager;\n /** Host capabilities for hub and workspace facet roots; defaults to the Node platform. */\n platform?: PoPlatform;\n /** Resolves the hub credential, because the server reads its token file after the hub exists. */\n hubToken?: () => string | undefined;\n /** Creates a session through the canonical cockpit lifecycle for hub channels. */\n createSession?: (\n request: PoHubSessionCreateRequest,\n /**\n * Set when a workspace-mounted package creates a session with no parent. The host must\n * refuse a cwd outside that workspace before admitting anything.\n */\n placement?: { workspaceId: string },\n ) => Promise<PoHubSessionScope>;\n onNotice?: (message: string) => void;\n sessionReservations?: PoHubSessionReservations;\n requestSessionApi?: (scope: PoHubSessionScope, request: PoHubSessionApiRequest) => Promise<Response>;\n computerUse?: PoComputerUseHostBinding;\n admitWorkspace?: (request: HeadlessWorkspaceAdmission) => Promise<HeadlessWorkspace>;\n onWorkspaceRemoved?: (workspaceId: string) => void;\n /** Reads a session cwd's git status; defaults to the git CLI. */\n readGitStatus?: (cwd: string) => Promise<SessionGitStatus | undefined>;\n /** Resolves a profile's persona presentation for a workspace root; sessions show no avatar without it. */\n resolveProfileIdentity?: (root: string, profile: string) => HeadlessProfileIdentity | undefined;\n /**\n * Publishes a session's web and native compositions for one major mode of a workspace root,\n * so the session mounts only that mode's plugins. Called when the session registers and\n * whenever its major mode changes; without it a session keeps its creation compositions.\n */\n publishSessionCompositions?: (\n sessionId: string,\n root: string,\n majorMode: string,\n ) => Pick<HeadlessHubSession, 'webComposition' | 'nativeComposition'>;\n}\n\nexport interface HeadlessHub {\n /** Canonical direct lifecycle shared by hub channels, APIs, and sessions. */\n readonly sessionService: PoHubSessionService;\n /** Lifecycle-owned event path shared by session facets and hub channels. */\n readonly directEvents: PoDirectEventBus;\n readonly computerUse?: PoComputerUseHostBinding;\n readHome?(request: HomeRequest, authorizeSession: (sessionId: string) => boolean): Promise<HomeSnapshot>;\n snapshot(): readonly HeadlessHubSession[];\n session(sessionId: string): HeadlessHubSession | undefined;\n runtime(sessionId: string): HeadlessSessionHost['runtime'] | undefined;\n /** The session's profile avatar image, when its profile has an icon. */\n sessionAvatar(sessionId: string): { mimeType: string; bytes: Uint8Array } | undefined;\n onEvent(listener: (event: HeadlessHubEvent) => void): () => void;\n register(session: HeadlessHubSession): void;\n create(options: HeadlessSessionHostOptions): Promise<HeadlessHubSession>;\n closeSession(sessionId: string, options?: HeadlessSessionCloseOptions): Promise<void>;\n /** Publishes removal of a persisted session that has no live host. */\n notifySessionRemoved(sessionId: string): void;\n /** Publishes a changed record of a persisted session that has no live host. */\n notifyDormantChanged(sessionId: string): void;\n /** Publishes setup-only children through the parent's normal session updates. */\n setPendingSessionSetups?(sessionId: string, pending: readonly PoPendingSessionSetup[]): void;\n /** Replaces the session's activity line; undefined clears it. Unknown sessions are ignored. */\n setSessionActivity?(sessionId: string, activity: PoSessionActivity | undefined): void;\n /** Dispatches an authenticated package API request inside the owning process. */\n requestSessionApi(scope: PoHubSessionScope, request: PoHubSessionApiRequest): Promise<Response>;\n /** Mounts the selected hub facets once, before the headless server accepts clients. */\n mountFacets(facets: readonly (PoServerFacet | LoadedServerFacet)[], context?: PoApiContext): Promise<void>;\n /**\n * Swaps a mounted global or workspace scope to a new facet set, with the context it was\n * mounted with. The old facets unwind through the same path `removeWorkspace` uses before\n * the new ones apply, so their API base paths and channels can be claimed again. When the\n * new set fails to install, the previous facets are reinstalled and the error is rethrown.\n */\n replaceFacets(mount: PoApiMount, facets: readonly (PoServerFacet | LoadedServerFacet)[]): Promise<void>;\n workspaces(): readonly HeadlessWorkspace[];\n registerWorkspace(workspace: HeadlessWorkspace): void;\n admitWorkspace(request: HeadlessWorkspaceAdmission): Promise<HeadlessWorkspace>;\n removeWorkspace(workspaceId: string): Promise<void>;\n requestApi(mount: PoApiMount, basePath: string, request: Request): Promise<Response>;\n /** The dispatch table hub facets mount into, shared with session hosts this hub serves. */\n readonly pluginRegistry: PoPluginRegistry;\n /** The edit presence ledger shared by every session host this hub serves. */\n readonly editPresence: PoEditPresenceLedger;\n invokePlugin(call: unknown, direction: PoPluginDirection, caller?: PoPluginCaller): Promise<unknown>;\n registerChannel(channel: PoHubChannel, mount?: PoApiMount): () => void;\n channelTypes(): readonly string[];\n channelFrames(sessionId: string): Array<{ type: string; sessionId: string; payload: unknown }>;\n /** Resolves a channel-owned child journal for the browser thread projection. */\n threadJournal(sessionId: string, threadId: string): string | undefined;\n receiveChannel(\n sessionId: string,\n frameType: string,\n payload: unknown,\n connectionId: string,\n desktopAuthorized?: boolean,\n computerUseAuthorized?: boolean,\n ): void;\n disconnectChannels(connectionId: string): void;\n close(): Promise<void>;\n}\n\ninterface StartedChannel {\n readonly channel: PoHubChannel;\n readonly source: ReturnType<PoHubChannel['start']>;\n readonly mount: PoApiMount;\n}\n\n/**\n * When a reopened session last settled, from the marker its runtime journals at every run end.\n * Without it a session with a whole history would read as fresh until its next turn.\n */\nasync function lastSettledAt(host: HeadlessSessionHost): Promise<string | undefined> {\n try {\n const entry = (await host.runtime.readEntries()).entries.findLast(\n (entry) => entry.type === 'custom' && entry.customType === AGENT_SETTLED_ENTRY_TYPE,\n );\n const data = entry?.type === 'custom' ? (entry.data as { timestamp?: unknown } | undefined) : undefined;\n return typeof data?.timestamp === 'number' && Number.isFinite(data.timestamp)\n ? new Date(data.timestamp).toISOString()\n : undefined;\n } catch {\n // A runtime without a readable journal has no history to report; the rail shows it as fresh.\n return undefined;\n }\n}\n\n/** The groups a resumed session was saved with. Sessions from before groups existed have none. */\nasync function storedGroups(host: HeadlessSessionHost, onNotice?: (message: string) => void): Promise<string[]> {\n try {\n const { groups } = (await host.runtime.session.snapshot(SessionMetadataDoc, BACKGROUND_CONTEXT)) as {\n groups?: unknown;\n };\n return Array.isArray(groups) ? groups.filter((group): group is string => typeof group === 'string') : [];\n } catch (error) {\n // The session still opens; it just starts outside its groups until they are set again.\n onNotice?.(`Session groups could not be read: ${String(error)}`);\n return [];\n }\n}\nfunction scopeOf(session: HeadlessHubSession): PoHubSessionScope {\n return {\n sessionId: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n cwd: session.cwd,\n ...(session.environment === undefined ? {} : { environment: session.environment }),\n ...(session.host.sessionContext === undefined ? {} : { sessionContext: session.host.sessionContext }),\n };\n}\n\n/** Owns direct, same-process session and channel state for presentation adapters. */\nexport function createHeadlessHub(options: HeadlessHubOptions): HeadlessHub {\n let gitPlatform = options.platform;\n const readGitStatus =\n options.readGitStatus ??\n ((cwd: string) => readSessionGitStatus((gitPlatform ??= createNodePlatform()).env(cwd), cwd));\n const sessions = new Map<string, HeadlessHubSession>();\n const pendingSetups = new Map<string, readonly PoPendingSessionSetup[]>();\n const activities = new Map<string, PoSessionActivity>();\n const present = (session: HeadlessHubSession): HeadlessHubSession => {\n const pending = pendingSetups.get(session.id);\n const activity = activities.get(session.id);\n if (pending === undefined && activity === undefined) return session;\n return {\n ...session,\n ...(pending === undefined ? {} : { pendingSetups: pending }),\n ...(activity === undefined ? {} : { activity }),\n };\n };\n const pluginRegistry = createPoPluginRegistry();\n const editPresence: PoEditPresenceLedger = new Map();\n const channels = new Map<string, StartedChannel>();\n const listeners = new Set<(event: HeadlessHubEvent) => void>();\n const subscriptions = new Set<() => void>();\n const sessionCleanups = new Map<string, () => void>();\n const presentationCleanups = new Map<string, () => void>();\n /** Profile icons by session, kept out of summaries because each can be hundreds of kilobytes. */\n const avatarIcons = new Map<string, string>();\n const sessionShutdowns = new Map<string, { session: HeadlessHubSession; promise: Promise<void>; pending: boolean }>();\n const directEventListeners = new Map<string, Set<(payload: unknown) => void>>();\n const directEventLatest = new Map<string, unknown>();\n const maxDirectEventLatest = 4096;\n const communicationEndpoints = new Map<\n string,\n {\n listeners: Map<string, Set<(sourceSessionId: string, payload: unknown) => void>>;\n readyListeners: Set<(peerSessionId: string) => void>;\n ready: boolean;\n endpoint: PoSessionCommunicationEndpoint;\n }\n >();\n let closed = false;\n interface FacetMount {\n host: PoServerHost;\n installed: InstalledServerFacets;\n /** Kept so `replaceFacets` remounts with the same context and can roll back. */\n context: PoApiContext;\n facets: readonly (PoServerFacet | LoadedServerFacet)[];\n }\n const mounts = new Map<string, FacetMount>();\n const disposeMount = async (mounted: FacetMount): Promise<void> => {\n try {\n await mounted.installed.dispose();\n } finally {\n mounted.host.dispose();\n }\n };\n const workspaces = new Map<string, HeadlessWorkspace>();\n const worktreeProvisioners = new Map<string, { mount: PoApiMount; provisioner: PoHubReservedWorktreeProvisioner }>();\n let sessionService: PoHubSessionService;\n\n const mountKey = (mount: PoApiMount): string =>\n mount.scope === 'global'\n ? 'global'\n : mount.scope === 'workspace'\n ? `workspace:${mount.workspaceId}`\n : `session:${mount.sessionId}`;\n const belongs = (mount: PoApiMount, session: HeadlessHubSession): boolean =>\n mount.scope === 'global' ||\n (mount.scope === 'workspace' ? session.workspaceId === mount.workspaceId : session.id === mount.sessionId);\n const canClose = (mount: PoApiMount, session: HeadlessHubSession): boolean =>\n belongs(mount, session) || (mount.scope === 'session' && session.parentSessionId === mount.sessionId);\n // Sessions executing in the same checkout share files, so they may message each other to resolve edits.\n // Sessions the user put in a shared group may message each other too.\n // Remote conversations are driven by an external client and keep the parent-child rule.\n const peers = (a: HeadlessHubSession, b: HeadlessHubSession): boolean => {\n if (\n a.sessionProvenance === REMOTE_CONVERSATION_SESSION_PROVENANCE ||\n b.sessionProvenance === REMOTE_CONVERSATION_SESSION_PROVENANCE\n )\n return false;\n const root = a.host.sessionContext?.checkoutRoot;\n if (root !== undefined && root === b.host.sessionContext?.checkoutRoot) return true;\n return (a.groups ?? []).some((group) => b.groups?.includes(group) === true);\n };\n const canCommunicate = (sourceId: string, targetId: string): boolean => {\n if (closed || sourceId === targetId) return false;\n const source = sessions.get(sourceId);\n const target = sessions.get(targetId);\n return (\n source !== undefined &&\n target !== undefined &&\n (source.parentSessionId === target.id || target.parentSessionId === source.id || peers(source, target))\n );\n };\n const registerReservedWorktreeProvisioner = (\n mount: PoApiMount,\n provisioner: PoHubReservedWorktreeProvisioner,\n ): (() => void) => {\n const key = mountKey(mount);\n if (worktreeProvisioners.has(key)) throw new Error('A worktree provisioner is already registered.');\n worktreeProvisioners.set(key, { mount, provisioner });\n return () => {\n if (worktreeProvisioners.get(key)?.provisioner === provisioner) worktreeProvisioners.delete(key);\n };\n };\n const worktreeProvisionerFor = (parent: HeadlessHubSession): PoHubReservedWorktreeProvisioner | undefined => {\n let provisioner: PoHubReservedWorktreeProvisioner | undefined;\n let priority = -1;\n for (const { mount, provisioner: candidate } of worktreeProvisioners.values()) {\n if (!belongs(mount, parent) || CHANNEL_PRIORITY[mount.scope] <= priority) continue;\n provisioner = candidate;\n priority = CHANNEL_PRIORITY[mount.scope];\n }\n return provisioner;\n };\n const selectedChannels = (session: HeadlessHubSession): StartedChannel[] => {\n const selected = new Map<string, StartedChannel>();\n for (const started of channels.values()) {\n if (!belongs(started.mount, session)) continue;\n const previous = selected.get(started.channel.frameType);\n if (!previous || CHANNEL_PRIORITY[started.mount.scope] > CHANNEL_PRIORITY[previous.mount.scope])\n selected.set(started.channel.frameType, started);\n }\n return [...selected.values()];\n };\n const selectedChannel = (session: HeadlessHubSession, frameType: string): StartedChannel | undefined =>\n selectedChannels(session).find((started) => started.channel.frameType === frameType);\n /**\n * One channel serves a session: the narrowest mount that reaches it. A package that\n * registers the same channel globally and per workspace would otherwise run two\n * sources against one session, and only the narrower one can publish or receive.\n *\n * Compared by mount scope rather than identity so a channel being started already\n * knows which sessions it is taking over.\n */\n const serves = (mount: PoApiMount, frameType: string, session: HeadlessHubSession): boolean => {\n if (!belongs(mount, session)) return false;\n const current = selectedChannel(session, frameType);\n return current === undefined || CHANNEL_PRIORITY[mount.scope] >= CHANNEL_PRIORITY[current.mount.scope];\n };\n\n const directEventKey = (frameType: string, sessionId: string): string => `${frameType}\\0${sessionId}`;\n const directEvents: PoDirectEventBus = {\n publish(frameType, sessionId, payload) {\n if (closed) return;\n const key = directEventKey(frameType, sessionId);\n directEventLatest.set(key, payload);\n while (directEventLatest.size > maxDirectEventLatest) {\n const oldest = directEventLatest.keys().next().value;\n if (oldest === undefined) break;\n directEventLatest.delete(oldest);\n }\n const listeners = directEventListeners.get(key);\n if (listeners === undefined) return;\n for (const listener of listeners) listener(payload);\n },\n subscribe(frameType, sessionId, listener, options) {\n if (closed) return () => undefined;\n const key = directEventKey(frameType, sessionId);\n const listeners = directEventListeners.get(key) ?? new Set<(payload: unknown) => void>();\n listeners.add(listener);\n directEventListeners.set(key, listeners);\n if (options?.replayLatest && directEventLatest.has(key)) listener(directEventLatest.get(key));\n let released = false;\n return () => {\n if (released) return;\n released = true;\n listeners.delete(listener);\n if (listeners.size === 0) directEventListeners.delete(key);\n };\n },\n clearSession(sessionId) {\n const suffix = `\\0${sessionId}`;\n for (const key of directEventLatest.keys()) if (key.endsWith(suffix)) directEventLatest.delete(key);\n },\n close() {\n directEventListeners.clear();\n directEventLatest.clear();\n },\n };\n\n const announceCommunicationReady = (sessionId: string): void => {\n const current = communicationEndpoints.get(sessionId);\n if (current?.ready !== true) return;\n for (const [peerSessionId, peer] of communicationEndpoints) {\n if (!peer.ready || !canCommunicate(sessionId, peerSessionId)) continue;\n for (const listener of current.readyListeners) listener(peerSessionId);\n for (const listener of peer.readyListeners) listener(sessionId);\n }\n };\n\n const bindCommunication = (sessionId: string): PoSessionCommunicationEndpoint => {\n const existing = communicationEndpoints.get(sessionId);\n if (existing !== undefined) return existing.endpoint;\n const listeners = new Map<string, Set<(sourceSessionId: string, payload: unknown) => void>>();\n const readyListeners = new Set<(peerSessionId: string) => void>();\n let endpoint!: PoSessionCommunicationEndpoint;\n const record = {\n listeners,\n readyListeners,\n ready: false,\n get endpoint() {\n return endpoint;\n },\n };\n endpoint = {\n sessionId,\n publish(targetSessionId, type, payload) {\n if (!canCommunicate(sessionId, targetSessionId)) return false;\n const target = communicationEndpoints.get(targetSessionId);\n if (target?.ready !== true) return false;\n for (const listener of target.listeners.get(type) ?? []) listener(sessionId, payload);\n return true;\n },\n subscribe(type, listener) {\n const current = listeners.get(type) ?? new Set<(sourceSessionId: string, payload: unknown) => void>();\n current.add(listener);\n listeners.set(type, current);\n return () => {\n current.delete(listener);\n if (current.size === 0) listeners.delete(type);\n };\n },\n onPeerReady(listener) {\n readyListeners.add(listener);\n if (!record.ready) {\n record.ready = true;\n announceCommunicationReady(sessionId);\n } else {\n for (const [peerSessionId, peer] of communicationEndpoints) {\n if (peer.ready && canCommunicate(sessionId, peerSessionId)) listener(peerSessionId);\n }\n }\n return () => readyListeners.delete(listener);\n },\n describePeer(peerSessionId) {\n if (!canCommunicate(sessionId, peerSessionId)) return undefined;\n const peer = sessions.get(peerSessionId);\n if (peer === undefined) return undefined;\n const own = sessions.get(sessionId)?.groups ?? [];\n const profile = peer.profile?.displayName ?? peer.profile?.name;\n return {\n sessionId: peerSessionId,\n name: peer.name,\n ...(profile === undefined ? {} : { profile }),\n sharedGroups: (peer.groups ?? []).filter((group) => own.includes(group)),\n };\n },\n close() {\n if (communicationEndpoints.get(sessionId)?.endpoint !== endpoint) return;\n communicationEndpoints.delete(sessionId);\n listeners.clear();\n readyListeners.clear();\n },\n };\n communicationEndpoints.set(sessionId, record);\n return endpoint;\n };\n\n const queuedEvents: HeadlessHubEvent[] = [];\n let publishing = false;\n const emit = (event: HeadlessHubEvent): void => {\n if (closed) return;\n queuedEvents.push(event.kind === 'upsert' ? { ...event, session: present(event.session) } : event);\n if (publishing) return;\n publishing = true;\n try {\n for (let index = 0; index < queuedEvents.length; index += 1)\n for (const listener of listeners) listener(queuedEvents[index]);\n } finally {\n queuedEvents.length = 0;\n publishing = false;\n }\n };\n const sessionScopes = (): readonly PoHubSessionScope[] => [...sessions.values()].map(scopeOf);\n const publish = (frameType: string, sessionId: string, payload: unknown, connectionId?: string): void => {\n if (!sessions.has(sessionId)) return;\n emit({ kind: 'channel', frameType, sessionId, payload, ...(connectionId === undefined ? {} : { connectionId }) });\n };\n\n /**\n * Hub-owned calls carry the hub credential, so a session API can tell them from a\n * browser call it must not trust. Browser traffic reaches a session API through\n * requestApi instead, and keeps the headers its caller sent.\n */\n const hubAuthenticated = (request: PoHubSessionApiRequest): PoHubSessionApiRequest => {\n const token = options.hubToken?.();\n if (token === undefined || token === '') return request;\n const headers = new Headers(request.headers);\n if (headers.has(AUTHORIZATION_HEADER)) return request;\n headers.set(AUTHORIZATION_HEADER, `Bearer ${token}`);\n return { ...request, headers };\n };\n\n const reservationsFor = (mount: PoApiMount): PoHubSessionReservations | undefined => {\n const reservations = options.sessionReservations;\n if (!reservations) return undefined;\n const check = (parentId: string): void => {\n const parent = sessions.get(parentId);\n if (!parent || !belongs(mount, parent)) throw new Error('Parent session is outside this mount.');\n };\n return {\n read: (id, parentId) => {\n check(parentId);\n return reservations.read(id, parentId);\n },\n prepare: (id, parentId, cwd) => {\n check(parentId);\n return reservations.prepare(id, parentId, cwd);\n },\n complete: (id, parentId) => {\n check(parentId);\n return reservations.complete(id, parentId);\n },\n };\n };\n const channelHost = (frameType: string, mount: PoApiMount): PoHubChannelHost => ({\n sessions: () =>\n sessionScopes().filter((scope) => {\n const session = sessions.get(scope.sessionId);\n return session !== undefined && serves(mount, frameType, session);\n }),\n sessionService: {\n reservations: reservationsFor(mount),\n create: async (request) => {\n // A workspace package may start a top-level session, placed in its own workspace.\n if (mount.scope === 'workspace' && request.parentSessionId === undefined) {\n if (request.reservationId !== undefined) throw new Error('A reserved session requires its owning parent.');\n if (options.createSession === undefined)\n throw new Error('The cockpit session service cannot create sessions in this host.');\n return options.createSession(request, { workspaceId: mount.workspaceId });\n }\n if (mount.scope !== 'global') {\n const parent = request.parentSessionId === undefined ? undefined : sessions.get(request.parentSessionId);\n if (!parent || !belongs(mount, parent)) throw new Error('Parent session is outside this mount.');\n }\n return sessionService.create(request);\n },\n close: async (id) => {\n const session = sessions.get(id);\n if (session === undefined) {\n const shutdown = sessionShutdowns.get(id);\n if (shutdown !== undefined) {\n if (!canClose(mount, shutdown.session)) throw new Error('Session is outside this mount.');\n await shutdown.promise;\n }\n return;\n }\n if (!canClose(mount, session)) throw new Error('Session is outside this mount.');\n await sessionService.close(id);\n },\n isLive: (id) => sessionService.isLive(id),\n registerReservedWorktreeProvisioner: (provisioner) => registerReservedWorktreeProvisioner(mount, provisioner),\n canCommunicate: (sourceId, targetId) => {\n const source = sessions.get(sourceId);\n return (\n source !== undefined && belongs(mount, source) && sessionService.canCommunicate?.(sourceId, targetId) === true\n );\n },\n },\n directEvents: {\n publish: (type, id, payload) => {\n const session = sessions.get(id);\n if (session && serves(mount, frameType, session)) directEvents.publish(type, id, payload);\n },\n subscribe: (type, id, listener, subscriptionOptions) => {\n const session = sessions.get(id);\n return session && serves(mount, frameType, session)\n ? directEvents.subscribe(type, id, listener, subscriptionOptions)\n : () => undefined;\n },\n close: () => undefined,\n },\n publish: (sessionId, payload) => {\n const session = sessions.get(sessionId);\n if (session && serves(mount, frameType, session)) publish(frameType, sessionId, payload);\n },\n publishToConnection: (connectionId, sessionId, payload) => {\n const session = sessions.get(sessionId);\n if (connectionId === '' || !session || !serves(mount, frameType, session)) return false;\n publish(frameType, sessionId, payload, connectionId);\n return true;\n },\n requestSessionApi: async (scope, request) => {\n const session = sessions.get(scope.sessionId);\n if (!session || !belongs(mount, session)) return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (options.requestSessionApi === undefined)\n return Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n return options.requestSessionApi(scope, hubAuthenticated(request));\n },\n ...(options.computerUse === undefined\n ? {}\n : {\n computerUse: {\n get available() {\n return options.computerUse!.available;\n },\n request(scope, request) {\n const session = sessions.get(scope.sessionId);\n if (!session || !belongs(mount, session)) throw new Error('Computer-use session is outside this mount.');\n return options.computerUse!.request(scopeOf(session), request);\n },\n },\n }),\n onNotice: (message) => options.onNotice?.(message),\n });\n\n const startChannel = (channel: PoHubChannel, mount: PoApiMount): StartedChannel | undefined => {\n const key = `${mountKey(mount)}:${channel.frameType}`;\n if (channels.has(key)) {\n options.onNotice?.(`hub channel '${channel.frameType}' is already registered`);\n return undefined;\n }\n try {\n const displaced = new Map<string, StartedChannel>();\n for (const session of sessions.values()) {\n if (!belongs(mount, session)) continue;\n const previous = selectedChannel(session, channel.frameType);\n if (previous !== undefined) displaced.set(session.id, previous);\n }\n const source = channel.start(channelHost(channel.frameType, mount));\n const started = { channel, source, mount };\n channels.set(key, started);\n for (const session of sessions.values()) {\n if (selectedChannel(session, channel.frameType) !== started) continue;\n displaced.get(session.id)?.source.sessionRemoved?.(session.id);\n source.sessionAdded?.(scopeOf(session));\n }\n return started;\n } catch (error) {\n options.onNotice?.(`hub channel '${channel.frameType}' failed (${String(error)})`);\n return undefined;\n }\n };\n\n const releaseChannel = (channel: PoHubChannel, started: StartedChannel): void => {\n const key = `${mountKey(started.mount)}:${channel.frameType}`;\n if (channels.get(key) !== started) return;\n const served = [...sessions.values()].filter((session) => selectedChannel(session, channel.frameType) === started);\n channels.delete(key);\n started.source.close();\n for (const session of served) selectedChannel(session, channel.frameType)?.source.sessionAdded?.(scopeOf(session));\n };\n\n const receiveMountedChannel = (\n mount: PoApiMount,\n sessionId: string,\n frameType: string,\n payload: unknown,\n connectionId: string,\n ): boolean => {\n if (!connectionId) return false;\n const session = sessions.get(sessionId);\n if (!session || !belongs(mount, session)) return false;\n const started = channels.get(`${mountKey(mount)}:${frameType}`);\n if (!started?.channel.receive) return false;\n started.channel.receive(scopeOf(session), payload, { connectionId });\n return true;\n };\n\n const unregisterSession = (sessionId: string, closeOptions?: HeadlessSessionCloseOptions): void => {\n const current = sessions.get(sessionId);\n if (current === undefined) return;\n const cleanup = sessionCleanups.get(sessionId);\n if (cleanup !== undefined) subscriptions.delete(cleanup);\n communicationEndpoints.get(sessionId)?.endpoint.close();\n // Let scoped sources dispatch their final stop while the live-session boundary still admits it.\n try {\n for (const { source } of selectedChannels(current)) source.sessionRemoved?.(sessionId);\n options.computerUse?.forgetSession?.(sessionId);\n } finally {\n // A failing external stop must not leave a closed host registered.\n sessions.delete(sessionId);\n activities.delete(sessionId);\n sessionCleanups.delete(sessionId);\n presentationCleanups.get(sessionId)?.();\n presentationCleanups.delete(sessionId);\n avatarIcons.delete(sessionId);\n directEvents.clearSession?.(sessionId);\n }\n emit({ kind: 'removed', sessionId, ...(closeOptions?.keepDormant === true ? { dormant: true as const } : {}) });\n };\n\n const startSessionShutdown = (\n session: HeadlessHubSession,\n closeOptions?: HeadlessSessionCloseOptions,\n ): Promise<void> => {\n const existing = sessionShutdowns.get(session.id);\n if (existing !== undefined) return existing.promise;\n const shutdown = { session, promise: Promise.resolve(), pending: true };\n const promise = Promise.resolve().then(() =>\n closeOptions === undefined\n ? options.manager.closeSession(session.id)\n : options.manager.closeSession(session.id, closeOptions),\n );\n shutdown.promise = promise;\n sessionShutdowns.set(session.id, shutdown);\n void promise.then(\n () => {\n shutdown.pending = false;\n if (sessionShutdowns.get(session.id) === shutdown) sessionShutdowns.delete(session.id);\n },\n () => {\n shutdown.pending = false;\n },\n );\n return promise;\n };\n\n const register = (session: HeadlessHubSession): void => {\n if (closed) throw new Error('The headless hub is closed.');\n if (sessions.has(session.id)) throw new Error(`Session '${session.id}' is already registered.`);\n if (sessionShutdowns.get(session.id)?.pending) throw new Error(`Session '${session.id}' is still shutting down.`);\n // A failed shutdown stays visible to scoped closers until the id is reused. Reopening\n // the session is that reuse, so it must not be blocked by the stale failure.\n sessionShutdowns.delete(session.id);\n let current: HeadlessHubSession = {\n ...session,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n };\n sessions.set(session.id, current);\n announceCommunicationReady(session.id);\n // Branch changes happen inside runs, so the status is read at start and after each settle.\n const refreshGit = (): void => {\n void readGitStatus(session.cwd).then(\n (git) => {\n if (closed || sessions.get(session.id)?.host !== session.host) return;\n if (git?.branch === current.git?.branch && git?.dirty === current.git?.dirty) return;\n const { git: _previous, ...rest } = current;\n current = git === undefined ? rest : { ...rest, git };\n sessions.set(session.id, current);\n emit({ kind: 'upsert', session: current });\n },\n (error: unknown) =>\n options.onNotice?.(\n `session ${session.id} git status failed (${error instanceof Error ? error.message : String(error)})`,\n ),\n );\n };\n const stopPresentation = session.host.onPresentationFrame((frame) => {\n if (sessions.get(session.id)?.host !== session.host) return;\n const type = typeof frame.type === 'string' ? frame.type : '';\n const entry = frame.entry as { customType?: unknown } | undefined;\n if (type === 'entry_appended' && entry?.customType === PO_NOTIFICATION_ENTRY_TYPE) {\n emit({ kind: 'frame', sessionId: session.id, frame });\n return;\n }\n // Streaming updates belong to the session presentation. Replicating the\n // hub's growing event list for every token makes model output quadratic.\n if (\n type !== 'agent_start' &&\n type !== 'agent_settled' &&\n type !== 'message_end' &&\n type !== 'session_info_changed' &&\n type !== SESSION_GROUPS_CHANGED_FRAME &&\n type !== 'extension_ui_request' &&\n type !== 'extension_ui_answered'\n )\n return;\n const now = new Date().toISOString();\n const phase = type === 'agent_start' ? 'turn' : type === 'agent_settled' ? 'idle' : current.phase;\n const phaseChanged = phase !== current.phase;\n const method = typeof frame.method === 'string' ? frame.method : '';\n const dialog = type === 'extension_ui_request' && ['select', 'confirm', 'input', 'editor'].includes(method);\n const awaitingInput = dialog\n ? true\n : type === 'extension_ui_answered' || type === 'agent_settled'\n ? false\n : current.awaitingInput;\n const groups =\n type === SESSION_GROUPS_CHANGED_FRAME && Array.isArray(frame.groups)\n ? frame.groups.filter((group): group is string => typeof group === 'string')\n : current.groups;\n current = {\n ...current,\n name: type === 'session_info_changed' && typeof frame.name === 'string' ? frame.name : current.name,\n ...(groups === undefined ? {} : { groups }),\n updatedAt: now,\n phase,\n phaseSince: phaseChanged ? now : current.phaseSince,\n everPrompted: current.everPrompted || type === 'agent_start',\n awaitingInput,\n ...(type === 'agent_settled' ? { lastSettledAt: now } : {}),\n };\n sessions.set(session.id, current);\n emit({ kind: 'upsert', session: current });\n // A new shared group makes new peers: tell both sides, as a fresh endpoint would be told.\n if (type === SESSION_GROUPS_CHANGED_FRAME) announceCommunicationReady(session.id);\n // Only the prompt text travels: options and defaults stay with the focused presentation.\n if (dialog) {\n const text = (key: string) => (typeof frame[key] === 'string' ? { [key]: frame[key] } : {});\n emit({\n kind: 'frame',\n sessionId: session.id,\n frame: { type, ...text('id'), method, ...text('title'), ...text('message') },\n });\n }\n if (type === 'agent_settled') refreshGit();\n });\n let registered = false;\n const root = (): string => (session.workspaceId && workspaces.get(session.workspaceId)?.root) || session.cwd;\n let compositionMode: string | undefined;\n const applyCompositions = (majorMode: string): boolean => {\n if (!options.publishSessionCompositions || majorMode === compositionMode) return false;\n compositionMode = majorMode;\n try {\n const { webComposition, nativeComposition } = options.publishSessionCompositions(session.id, root(), majorMode);\n current = { ...current, webComposition, nativeComposition };\n return true;\n } catch (error) {\n options.onNotice?.(\n `session ${session.id} plugins for major mode \"${majorMode}\" could not be published (${error instanceof Error ? error.message : String(error)})`,\n );\n return false;\n }\n };\n const applyProfile = (profileName: string | undefined): boolean => {\n let identity: HeadlessProfileIdentity | undefined;\n if (profileName) {\n try {\n identity = options.resolveProfileIdentity?.(root(), profileName);\n } catch (error) {\n options.onNotice?.(\n `session ${session.id} profile \"${profileName}\" could not be resolved (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n }\n const icon = identity?.icon;\n if (icon) avatarIcons.set(session.id, icon);\n else avatarIcons.delete(session.id);\n const profile: HeadlessSessionProfile | undefined = profileName\n ? {\n name: profileName,\n ...(identity?.displayName ? { displayName: identity.displayName } : {}),\n ...(icon\n ? { iconVersion: crypto.createHash('sha256').update(icon).digest('hex').slice(0, ICON_VERSION_LENGTH) }\n : {}),\n }\n : undefined;\n const previous = current.profile;\n if (\n previous?.name === profile?.name &&\n previous?.displayName === profile?.displayName &&\n previous?.iconVersion === profile?.iconVersion\n )\n return false;\n const { profile: _previous, ...rest } = current;\n current = profile === undefined ? rest : { ...rest, profile };\n return true;\n };\n const applySelection = (selection: PoHeadlessSelection): void => {\n if (closed || sessions.get(session.id)?.host !== session.host) return;\n const compositionsChanged = applyCompositions(selection.majorMode);\n const profileChanged = applyProfile(selection.profile);\n if (!compositionsChanged && !profileChanged) return;\n sessions.set(session.id, current);\n if (registered) emit({ kind: 'upsert', session: current });\n };\n const stopSelection = session.host.onSelection?.(applySelection);\n presentationCleanups.set(session.id, () => {\n stopPresentation();\n stopSelection?.();\n });\n for (const { source } of selectedChannels(current)) source.sessionAdded?.(scopeOf(session));\n const active = (): boolean => sessions.get(session.id)?.host === session.host && !closed;\n const cleanup = (): void => {\n subscriptions.delete(cleanup);\n sessionCleanups.delete(session.id);\n if (!active()) return;\n void closeSession(session.id).catch((error: unknown) =>\n options.onNotice?.(\n `session ${session.id} cleanup failed (${error instanceof Error ? error.message : String(error)})`,\n ),\n );\n };\n sessionCleanups.set(session.id, cleanup);\n void session.host.runtime.exited.then(cleanup, cleanup);\n subscriptions.add(cleanup);\n registered = true;\n emit({ kind: 'upsert', session: current });\n refreshGit();\n };\n\n const closeSession = async (sessionId: string, closeOptions?: HeadlessSessionCloseOptions): Promise<void> => {\n const pending = sessionShutdowns.get(sessionId);\n if (pending !== undefined) {\n await pending.promise;\n return;\n }\n const session = sessions.get(sessionId);\n if (session === undefined) return;\n unregisterSession(sessionId, closeOptions);\n await startSessionShutdown(session, closeOptions);\n };\n\n const promptTarget = (sessionId: string, parentSessionId: string | undefined): HeadlessHubSession => {\n const session = closed ? undefined : sessions.get(sessionId);\n if (session === undefined) throw new Error('The session is not live.');\n if (parentSessionId !== undefined && session.parentSessionId !== parentSessionId)\n throw new Error('Only the parent session can drive this session.');\n return session;\n };\n\n sessionService = {\n create: async (request) => {\n if (options.createSession === undefined)\n throw new Error('The cockpit session service cannot create sessions in this host.');\n return options.createSession(request);\n },\n close: closeSession,\n isLive: (sessionId) => !closed && sessions.has(sessionId),\n readExecutionState: async (sessionId, readOptions) => {\n const target = promptTarget(sessionId, readOptions?.parentSessionId);\n if (!target.host.readExecutionState) throw new Error('The session cannot report execution state.');\n return target.host.readExecutionState();\n },\n prompt: async (sessionId, text, promptOptions) => {\n promptOptions?.signal?.throwIfAborted();\n const { settled } = await promptTarget(sessionId, promptOptions?.parentSessionId).host.runtime.submitPrompt(text);\n return { settled };\n },\n abort: async (sessionId, abortOptions) => {\n await promptTarget(sessionId, abortOptions?.parentSessionId).host.runtime.abort();\n },\n steer: async (sessionId, message, steerOptions) => {\n await promptTarget(sessionId, steerOptions?.parentSessionId).host.runtime.steer(message);\n },\n release: async (sessionId, releaseOptions) => {\n promptTarget(sessionId, releaseOptions?.parentSessionId);\n await closeSession(sessionId, { keepDormant: true });\n },\n reservations: options.sessionReservations,\n provisionReservedWorktree: async (request) => {\n const parent = sessions.get(request.parentSessionId);\n const provisioner = parent === undefined ? undefined : worktreeProvisionerFor(parent);\n if (provisioner === undefined) throw new Error('Automatic conversation worktree provisioning is unavailable.');\n return provisioner(request);\n },\n registerReservedWorktreeProvisioner: (provisioner) =>\n registerReservedWorktreeProvisioner({ scope: 'global' }, provisioner),\n canCommunicate,\n bindCommunication,\n };\n\n const installMount = async (\n facets: readonly (PoServerFacet | LoadedServerFacet)[],\n suppliedContext: PoApiContext | undefined,\n announceWorkspace: boolean,\n ): Promise<void> => {\n if (closed) throw new Error('The headless hub is closed.');\n const context: PoApiContext = suppliedContext ?? {\n scope: 'global',\n ...(options.hubToken?.() === undefined ? {} : { hubToken: options.hubToken() }),\n sessionService,\n directEvents,\n onNotice: (message) => options.onNotice?.(message),\n };\n if (context.scope === 'session') throw new Error('Session facets belong to their session host.');\n if (context.scope === 'workspace' && (!context.workspaceId || !context.workspaceRoot))\n throw new Error('Workspace mounts require an admitted identity and root.');\n const mount: PoApiMount =\n context.scope === 'global' ? { scope: 'global' } : { scope: 'workspace', workspaceId: context.workspaceId! };\n const key = mountKey(mount);\n if (mounts.has(key)) throw new Error(`The '${key}' facets are already mounted.`);\n const host = createPoServerHost({\n scope: context.scope,\n context: {\n ...context,\n sessionService: channelHost('', mount).sessionService,\n directEvents: channelHost('', mount).directEvents,\n receiveChannel: (sessionId, frameType, payload, connectionId) =>\n receiveMountedChannel(mount, sessionId, frameType, payload, connectionId),\n },\n mountChannel: (channel) => {\n const started = startChannel(channel, mount);\n if (started === undefined) return { mounted: false, dispose: () => undefined };\n return { mounted: true, dispose: () => releaseChannel(channel, started) };\n },\n pluginRegistry,\n });\n try {\n const installed = await installServerFacets({\n host,\n facets,\n onNotice: options.onNotice,\n ...(options.platform === undefined ? {} : { platform: options.platform }),\n });\n if (closed) {\n await installed.dispose();\n throw new Error('The headless hub was closed while mounting facets.');\n }\n mounts.set(key, { host, installed, context, facets });\n if (announceWorkspace && mount.scope === 'workspace') {\n const workspace = { id: mount.workspaceId, root: context.workspaceRoot!, available: true };\n workspaces.set(mount.workspaceId, workspace);\n emit({ kind: 'workspace_upsert', workspace });\n }\n } catch (error) {\n host.dispose();\n throw error;\n }\n };\n const mountFacets = (\n facets: readonly (PoServerFacet | LoadedServerFacet)[],\n suppliedContext?: PoApiContext,\n ): Promise<void> => installMount(facets, suppliedContext, true);\n const replacements = new Map<string, Promise<void>>();\n const replaceFacets = (mount: PoApiMount, facets: readonly (PoServerFacet | LoadedServerFacet)[]): Promise<void> => {\n if (mount.scope === 'session') return Promise.reject(new Error('Session facets belong to their session host.'));\n const key = mountKey(mount);\n // One swap at a time per mount, so a second check never disposes a set mid-install.\n const run = (replacements.get(key) ?? Promise.resolve()).then(async () => {\n if (closed) throw new Error('The headless hub is closed.');\n const previous = mounts.get(key);\n if (previous === undefined) throw new Error(`The '${key}' facets are not mounted.`);\n mounts.delete(key);\n await disposeMount(previous);\n // A workspace removed while its old set unwound stays removed.\n if (closed || (mount.scope === 'workspace' && !workspaces.has(mount.workspaceId))) return;\n try {\n await installMount(facets, previous.context, false);\n } catch (error) {\n await installMount(previous.facets, previous.context, false).catch((rollbackError: unknown) =>\n options.onNotice?.(\n `The '${key}' facets could not be restored (${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)})`,\n ),\n );\n throw error;\n }\n });\n const settled = run.then(\n () => undefined,\n () => undefined,\n );\n replacements.set(key, settled);\n void settled.then(() => {\n if (replacements.get(key) === settled) replacements.delete(key);\n });\n return run;\n };\n\n return {\n sessionService,\n directEvents,\n ...(options.computerUse === undefined ? {} : { computerUse: options.computerUse }),\n async readHome(request, authorizeSession) {\n if (\n !request ||\n typeof request !== 'object' ||\n Array.isArray(request) ||\n (request.source !== undefined && (typeof request.source !== 'string' || request.source.length > 128)) ||\n (request.workspaceId !== undefined &&\n (typeof request.workspaceId !== 'string' || request.workspaceId.length > 256))\n )\n throw new Error('Invalid Home request.');\n const offset = Number.isSafeInteger(request?.offset) && request.offset! >= 0 ? request.offset! : 0;\n const limit =\n Number.isSafeInteger(request?.limit) && request.limit! > 0\n ? Math.min(request.limit!, HOME_PAGE_LIMIT)\n : HOME_PAGE_LIMIT;\n const counts: HomeSnapshot['counts'] = {\n decision: 0,\n failure: 0,\n blocked: 0,\n running: 0,\n queued: 0,\n paused: 0,\n completed: 0,\n };\n const statuses = new Map<string, HomeSourceStatus>();\n const entities = new Map<string, HomeItem>();\n let examined = 0;\n let projectors = 0;\n for (const session of sessions.values()) {\n if (\n closed ||\n !authorizeSession(session.id) ||\n (request.workspaceId !== undefined && request.workspaceId !== session.workspaceId)\n )\n continue;\n for (const { channel, source } of selectedChannels(session)) {\n if (!source.homeFor || (request.source !== undefined && request.source !== channel.frameType)) continue;\n const key = JSON.stringify([channel.frameType, session.workspaceId]);\n const status = statuses.get(key) ?? {\n source: channel.frameType,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n coverage: 'ready' as const,\n };\n statuses.set(key, status);\n if (examined >= HOME_ENTITY_LIMIT || projectors++ >= HOME_ENTITY_LIMIT) {\n status.coverage = 'partial';\n continue;\n }\n try {\n const projection = parseHomeProjection(source.homeFor(scopeOf(session)));\n if (!projection) {\n status.coverage = 'partial';\n continue;\n }\n if (projection.coverage === 'partial' || status.coverage === 'partial') status.coverage = 'partial';\n else if (projection.coverage === 'unavailable') status.coverage = 'unavailable';\n for (const entity of projection.entities) {\n examined += 1;\n if (examined > HOME_ENTITY_LIMIT) {\n status.coverage = 'partial';\n break;\n }\n const allowed = [entity.sessionId, ...(entity.relatedSessionIds ?? [])].every((id) => {\n const referenced = sessions.get(id);\n return (\n referenced !== undefined && referenced.workspaceId === session.workspaceId && authorizeSession(id)\n );\n });\n if (!allowed) {\n status.coverage = 'partial';\n continue;\n }\n const { relatedSessionIds: _related, ...publicEntity } = entity;\n const identity = JSON.stringify([channel.frameType, session.workspaceId, entity.id]);\n const previous = entities.get(identity);\n if (!previous || Date.parse(entity.updatedAt) > Date.parse(previous.updatedAt))\n entities.set(identity, {\n ...publicEntity,\n source: channel.frameType,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n });\n }\n } catch {\n // A package projector cannot fail the read or claim complete coverage.\n status.coverage = 'partial';\n }\n }\n }\n for (const status of statuses.values())\n status.counts = { decision: 0, failure: 0, blocked: 0, running: 0, queued: 0, paused: 0, completed: 0 };\n for (const entity of entities.values()) {\n const status = statuses.get(JSON.stringify([entity.source, entity.workspaceId]));\n if (status?.counts) status.counts[entity.kind] += 1;\n }\n const attention = [...entities.values()]\n .filter((entity) => {\n counts[entity.kind] += 1;\n return ['decision', 'failure', 'blocked', 'paused'].includes(entity.kind);\n })\n .sort(\n (a, b) =>\n ['decision', 'failure', 'blocked', 'paused'].indexOf(a.kind) -\n ['decision', 'failure', 'blocked', 'paused'].indexOf(b.kind) ||\n Date.parse(b.updatedAt) - Date.parse(a.updatedAt) ||\n a.id.localeCompare(b.id) ||\n a.source.localeCompare(b.source),\n );\n return {\n version: 1,\n observedAt: new Date().toISOString(),\n sources: [...statuses.values()],\n counts,\n items: attention.slice(offset, offset + limit),\n total: attention.length,\n ...(offset + limit < attention.length ? { nextOffset: offset + limit } : {}),\n };\n },\n snapshot: () => [...sessions.values()].map(present),\n session: (sessionId) => {\n const session = sessions.get(sessionId);\n return session === undefined ? undefined : present(session);\n },\n setPendingSessionSetups(sessionId, pending) {\n if (JSON.stringify(pendingSetups.get(sessionId) ?? []) === JSON.stringify(pending)) return;\n pendingSetups.set(sessionId, Object.freeze([...pending]));\n const session = sessions.get(sessionId);\n if (session) emit({ kind: 'upsert', session: present(session) });\n },\n setSessionActivity(sessionId, activity) {\n const session = sessions.get(sessionId);\n if (session === undefined) return;\n const next: PoSessionActivity | undefined =\n activity === undefined\n ? undefined\n : Object.freeze({\n label: activity.label.slice(0, MAX_ACTIVITY_LABEL),\n ...(activity.attention === true ? { attention: true } : {}),\n ...(activity.since === undefined ? {} : { since: activity.since }),\n });\n if (JSON.stringify(activities.get(sessionId)) === JSON.stringify(next)) return;\n if (next === undefined) activities.delete(sessionId);\n else activities.set(sessionId, next);\n emit({ kind: 'upsert', session: present(session) });\n },\n runtime: (sessionId) => sessions.get(sessionId)?.host.runtime,\n sessionAvatar(sessionId) {\n const match = ICON_DATA_URL.exec(avatarIcons.get(sessionId) ?? '');\n const mimeType = match?.[1];\n if (match === null || !(PROFILE_ICON_MIME_TYPES as readonly string[]).includes(mimeType ?? '')) return undefined;\n return { mimeType: mimeType!, bytes: Buffer.from(match[2]!, 'base64') };\n },\n onEvent(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n register,\n notifySessionRemoved(sessionId) {\n emit({ kind: 'removed', sessionId });\n },\n notifyDormantChanged(sessionId) {\n emit({ kind: 'dormant_changed', sessionId });\n },\n mountFacets,\n replaceFacets,\n workspaces: () => [...workspaces.values()],\n registerWorkspace(workspace) {\n workspaces.set(workspace.id, workspace);\n emit({ kind: 'workspace_upsert', workspace });\n },\n admitWorkspace: async (request) => {\n if (!options.admitWorkspace) throw new Error('Workspace admission is unavailable.');\n return options.admitWorkspace(request);\n },\n async removeWorkspace(id) {\n if ([...sessions.values()].some((session) => session.workspaceId === id))\n throw new Error('Workspace still has live sessions.');\n const key = mountKey({ scope: 'workspace', workspaceId: id });\n const mounted = mounts.get(key);\n if (!workspaces.has(id)) return;\n options.onWorkspaceRemoved?.(id);\n workspaces.delete(id);\n emit({ kind: 'workspace_removed', workspaceId: id });\n if (!mounted) return;\n mounts.delete(key);\n await disposeMount(mounted);\n },\n async requestApi(mount, basePath, request) {\n if (closed) return Response.json({ error: 'Server is closed.' }, { status: 503 });\n if (mount.scope === 'session') {\n const session = sessions.get(mount.sessionId);\n if (!session || !options.requestSessionApi)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n const url = new URL(request.url);\n return options.requestSessionApi(scopeOf(session), {\n basePath,\n path: `${url.pathname}${url.search}`,\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n body: request.body === null ? undefined : new Uint8Array(await request.arrayBuffer()),\n });\n }\n const handler = mounts.get(mountKey(mount))?.host.handlerFor(basePath);\n if (!handler)\n return Response.json({ error: `API '${basePath}' is not mounted in ${mountKey(mount)}.` }, { status: 404 });\n return handler.fetch(request);\n },\n pluginRegistry,\n editPresence,\n invokePlugin: (call, direction, caller) => pluginRegistry.invoke(call, direction, caller),\n async create(sessionOptions) {\n const id = sessionOptions.sessionId;\n if (closed) throw new Error('The headless hub is closed.');\n // Checked before building the host: once it exists, a refusal has to close it, and a\n // duplicate id would then close the live session that already owns the id.\n if (sessions.has(id)) throw new Error(`Session '${id}' is already registered.`);\n if (sessionShutdowns.get(id)?.pending) throw new Error(`Session '${id}' is still shutting down.`);\n const host = await options.manager.create(sessionOptions);\n const settledAt = await lastSettledAt(host);\n const groups = await storedGroups(host, options.onNotice);\n const session: HeadlessHubSession = {\n id: sessionOptions.sessionId,\n workspaceId: sessionOptions.workspaceId,\n webComposition: sessionOptions.webComposition,\n nativeComposition: sessionOptions.nativeComposition,\n name: sessionOptions.sessionName,\n cwd: sessionOptions.cwd,\n createdAt: new Date().toISOString(),\n ...(sessionOptions.parentSessionId === undefined ? {} : { parentSessionId: sessionOptions.parentSessionId }),\n ...(sessionOptions.sessionProvenance === undefined\n ? {}\n : { sessionProvenance: sessionOptions.sessionProvenance }),\n environment: sessionOptions.environment,\n ...(settledAt === undefined ? {} : { everPrompted: true, lastSettledAt: settledAt }),\n groups,\n host,\n };\n try {\n register(session);\n } catch (error) {\n // Registration can fail after publishing the host into the session map.\n // Roll back only our host, never a different session that owns this id.\n if (sessions.get(id)?.host === host) {\n try {\n unregisterSession(id);\n } catch (cleanupError) {\n options.onNotice?.(`Session '${id}' registration rollback failed: ${String(cleanupError)}`);\n }\n }\n // The hub closed, or a racing create took the id, while this host was starting.\n await Promise.resolve(options.manager.closeSession(id)).catch((closeError: unknown) =>\n options.onNotice?.(`Session '${id}' could not be closed after a failed registration: ${String(closeError)}`),\n );\n throw error;\n }\n return session;\n },\n closeSession,\n async requestSessionApi(scope, request) {\n if (closed || !sessions.has(scope.sessionId))\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (options.requestSessionApi === undefined)\n return Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n return options.requestSessionApi(scope, request);\n },\n registerChannel(channel, mount = { scope: 'global' }) {\n const started = startChannel(channel, mount);\n if (started === undefined) return () => undefined;\n return () => releaseChannel(channel, started);\n },\n channelTypes: () => [...new Set([...channels.values()].map(({ channel }) => channel.frameType))],\n channelFrames(sessionId) {\n const session = sessions.get(sessionId);\n if (session === undefined) return [];\n const scope = scopeOf(session);\n const frames: Array<{ type: string; sessionId: string; payload: unknown }> = [];\n for (const { channel, source } of selectedChannels(session)) {\n const type = channel.frameType;\n const payload = source.payloadFor(scope);\n if (payload !== undefined) frames.push({ type, sessionId, payload });\n }\n return frames;\n },\n threadJournal(sessionId, threadId) {\n const session = sessions.get(sessionId);\n if (session === undefined) return undefined;\n const scope = scopeOf(session);\n for (const { source } of selectedChannels(session)) {\n const journal = source.threadJournal?.(scope, threadId);\n if (journal !== undefined) return journal;\n }\n return undefined;\n },\n receiveChannel(\n sessionId,\n frameType,\n payload,\n connectionId,\n desktopAuthorized = false,\n computerUseAuthorized = false,\n ) {\n if (connectionId === '') return;\n const session = sessions.get(sessionId);\n const started = session && selectedChannels(session).find(({ channel }) => channel.frameType === frameType);\n if (session === undefined || started === undefined) return;\n started.channel.receive?.(scopeOf(session), payload, {\n connectionId,\n ...(desktopAuthorized ? { desktopAuthorized: true } : {}),\n ...(computerUseAuthorized ? { computerUseAuthorized: true } : {}),\n } satisfies PoHubChannelConnection);\n },\n disconnectChannels(connectionId) {\n if (connectionId === '') return;\n for (const { channel } of channels.values()) channel.disconnected?.({ connectionId });\n },\n async close() {\n if (closed) return;\n const ids = [...sessions.keys()];\n closed = true;\n directEvents.close();\n for (const unsubscribe of subscriptions) unsubscribe();\n subscriptions.clear();\n for (const cleanup of presentationCleanups.values()) cleanup();\n presentationCleanups.clear();\n const failures: unknown[] = [];\n for (const mounted of [...mounts.values()].reverse()) {\n try {\n await mounted.installed.dispose();\n } catch (error) {\n failures.push(error);\n }\n try {\n mounted.host.dispose();\n } catch (error) {\n failures.push(error);\n }\n }\n mounts.clear();\n pluginRegistry.dispose();\n editPresence.clear();\n workspaces.clear();\n for (const { source } of channels.values()) source.close();\n channels.clear();\n listeners.clear();\n const shutdowns: Promise<void>[] = [...sessionShutdowns.values()]\n .filter(({ pending }) => pending)\n .map(({ promise }) => promise);\n for (const id of ids) {\n const session = sessions.get(id);\n if (session !== undefined && !sessionShutdowns.has(id)) shutdowns.push(startSessionShutdown(session));\n }\n sessions.clear();\n const outcomes = await Promise.allSettled(shutdowns);\n for (const outcome of outcomes) if (outcome.status === 'rejected') failures.push(outcome.reason);\n if (failures.length) throw new AggregateError(failures, 'Mount shutdown failed');\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"headlessHub.cjs","names":["SessionMetadataDoc","BACKGROUND_CONTEXT","readSessionGitStatus","createNodePlatform","createPoPluginRegistry","crypto","createPoServerHost","installServerFacets","parseHomeProjection","PROFILE_ICON_MIME_TYPES"],"sources":["../src/server/headlessHub.ts"],"sourcesContent":["import crypto from 'node:crypto';\n\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\n\nimport { AGENT_SETTLED_ENTRY_TYPE } from '../constants/agentSettled';\nimport type { PoHeadlessSelection } from '../exports/headless';\nimport type {\n PoComputerUseHostBinding,\n PoDirectEventBus,\n PoHubChannel,\n PoHubChannelConnection,\n PoHubChannelHost,\n PoHubReservedWorktreeProvisioner,\n PoHubSessionApiRequest,\n PoHubSessionCreateRequest,\n PoHubSessionScope,\n PoHubSessionService,\n PoSessionCommunicationEndpoint,\n PoHubSessionReservations,\n PoPendingSessionSetup,\n PoSessionActivity,\n} from '../exports/hubChannel';\nimport { REMOTE_CONVERSATION_SESSION_PROVENANCE } from '../exports/hubChannel';\nimport type { PoNativeComposition, PoWebComposition } from '../exports/packageApi';\nimport type { PoApiContext, PoApiMount, PoEditPresenceLedger } from '../exports/packageApi';\nimport {\n createPoPluginRegistry,\n type PoPluginCaller,\n type PoPluginDirection,\n type PoPluginRegistry,\n} from '../exports/pluginProtocol';\nimport {\n createPoServerHost,\n installServerFacets,\n type PoServerFacet,\n type PoServerHost,\n type InstalledServerFacets,\n type LoadedServerFacet,\n} from '../exports/serverFacet';\nimport {\n HOME_ENTITY_LIMIT,\n HOME_PAGE_LIMIT,\n parseHomeProjection,\n type HomeRequest,\n type HomeSnapshot,\n type HomeItem,\n type HomeSourceStatus,\n} from '../schemas/home';\nimport { PO_NOTIFICATION_ENTRY_TYPE } from '../schemas/notification';\nimport type { PoPlatform } from '../schemas/platform';\nimport { PROFILE_ICON_MIME_TYPES } from '../schemas/profileIdentity';\nimport { SESSION_GROUPS_CHANGED_FRAME } from '../schemas/sessionProtocol';\nimport { createNodePlatform } from '../services/nodePlatform';\nimport { SessionMetadataDoc } from '../services/sessionDocs';\nimport { readSessionGitStatus } from '../services/sessionGitStatus';\nimport type { SessionGitStatus } from '../services/sessionGitStatus/type';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '../systems/main/types/headlessSessionHost';\nimport type { HeadlessSessionCloseOptions, HeadlessSessionManager } from '../systems/main/types/headlessSessionManager';\n\nconst AUTHORIZATION_HEADER = 'authorization';\nconst CHANNEL_PRIORITY = { global: 0, workspace: 1, session: 2 } as const;\nconst ICON_VERSION_LENGTH = 12;\nconst ICON_DATA_URL = /^data:([a-z/+.-]+);base64,([A-Za-z0-9+/=]+)$/u;\n/** A rail line, not a log: a longer label is cut to this. */\nconst MAX_ACTIVITY_LABEL = 80;\n\n/** The profile a session runs under, as shown on its rail card. The icon itself is served separately. */\nexport interface HeadlessSessionProfile {\n readonly name: string;\n readonly displayName?: string;\n /** Changes whenever the icon does, so a client can cache the avatar by it. */\n readonly iconVersion?: string;\n}\n\n/** A profile's persona presentation: display name and icon as a data: URL. */\nexport interface HeadlessProfileIdentity {\n readonly displayName?: string;\n readonly icon?: string;\n}\n\nexport interface HeadlessHubSession {\n readonly id: string;\n readonly workspaceId?: string;\n webComposition?: PoWebComposition;\n nativeComposition?: PoNativeComposition;\n readonly name: string;\n readonly cwd: string;\n readonly createdAt: string;\n readonly parentSessionId?: string;\n readonly sessionProvenance?: string;\n /** User-assigned groups; sessions sharing one may message each other. Empty when none. */\n readonly groups?: readonly string[];\n readonly updatedAt?: string;\n readonly phase?: 'idle' | 'turn' | 'compaction' | 'retry';\n readonly phaseSince?: string;\n readonly pendingMessageCount?: number;\n readonly everPrompted?: boolean;\n readonly awaitingInput?: boolean;\n readonly lastSettledAt?: string;\n /** Branch and dirty flag of the session cwd; absent outside a git work tree. */\n readonly git?: SessionGitStatus;\n /** Selected profile; absent when the session runs without one. */\n readonly profile?: HeadlessSessionProfile;\n readonly pendingSetups?: readonly PoPendingSessionSetup[];\n /** The line the session's extension last published about work it runs; absent when none. */\n readonly activity?: PoSessionActivity;\n /** Environment admitted for this session, when supplied by the host. */\n readonly environment?: Readonly<Record<string, string | undefined>>;\n readonly host: HeadlessSessionHost;\n}\n\nexport interface HeadlessWorkspace {\n readonly id: string;\n readonly root: string;\n readonly name?: string;\n readonly available?: boolean;\n}\n\n/** A workspace to admit: an existing folder, or a name alone for a new default folder. */\nexport interface HeadlessWorkspaceAdmission {\n readonly root?: string;\n readonly name?: string;\n}\n\nexport type HeadlessHubEvent =\n | { kind: 'upsert'; session: HeadlessHubSession }\n /** `dormant`: the session stopped running but keeps its record, so it lists as dormant. */\n | { kind: 'removed'; sessionId: string; dormant?: true }\n /** A dormant session's record changed; clients reread it from the dormant list. */\n | { kind: 'dormant_changed'; sessionId: string }\n | { kind: 'workspace_upsert'; workspace: HeadlessWorkspace }\n | { kind: 'workspace_removed'; workspaceId: string }\n | { kind: 'channel'; frameType: string; sessionId: string; payload: unknown; connectionId?: string }\n /** A live session frame every hub client needs: notification entries and agent dialogs. */\n | { kind: 'frame'; sessionId: string; frame: Record<string, unknown> };\n\nexport interface HeadlessHubOptions {\n manager: HeadlessSessionManager;\n /** Host capabilities for hub and workspace facet roots; defaults to the Node platform. */\n platform?: PoPlatform;\n /** Resolves the hub credential, because the server reads its token file after the hub exists. */\n hubToken?: () => string | undefined;\n /** Creates a session through the canonical cockpit lifecycle for hub channels. */\n createSession?: (\n request: PoHubSessionCreateRequest,\n /**\n * Set when a workspace-mounted package creates a session with no parent. The host must\n * refuse a cwd outside that workspace before admitting anything.\n */\n placement?: { workspaceId: string },\n ) => Promise<PoHubSessionScope>;\n onNotice?: (message: string) => void;\n sessionReservations?: PoHubSessionReservations;\n requestSessionApi?: (scope: PoHubSessionScope, request: PoHubSessionApiRequest) => Promise<Response>;\n computerUse?: PoComputerUseHostBinding;\n admitWorkspace?: (request: HeadlessWorkspaceAdmission) => Promise<HeadlessWorkspace>;\n onWorkspaceRemoved?: (workspaceId: string) => void;\n /** Reads a session cwd's git status; defaults to the git CLI. */\n readGitStatus?: (cwd: string) => Promise<SessionGitStatus | undefined>;\n /** Resolves a profile's persona presentation for a workspace root; sessions show no avatar without it. */\n resolveProfileIdentity?: (root: string, profile: string) => HeadlessProfileIdentity | undefined;\n /**\n * Publishes a session's web and native compositions for one major mode of a workspace root,\n * so the session mounts only that mode's plugins. Called when the session registers and\n * whenever its major mode changes; without it a session keeps its creation compositions.\n */\n publishSessionCompositions?: (\n sessionId: string,\n root: string,\n majorMode: string,\n ) => Pick<HeadlessHubSession, 'webComposition' | 'nativeComposition'>;\n}\n\nexport interface HeadlessHub {\n /** Canonical direct lifecycle shared by hub channels, APIs, and sessions. */\n readonly sessionService: PoHubSessionService;\n /** Lifecycle-owned event path shared by session facets and hub channels. */\n readonly directEvents: PoDirectEventBus;\n readonly computerUse?: PoComputerUseHostBinding;\n readHome?(request: HomeRequest, authorizeSession: (sessionId: string) => boolean): Promise<HomeSnapshot>;\n snapshot(): readonly HeadlessHubSession[];\n session(sessionId: string): HeadlessHubSession | undefined;\n runtime(sessionId: string): HeadlessSessionHost['runtime'] | undefined;\n /** The session's profile avatar image, when its profile has an icon. */\n sessionAvatar(sessionId: string): { mimeType: string; bytes: Uint8Array } | undefined;\n onEvent(listener: (event: HeadlessHubEvent) => void): () => void;\n register(session: HeadlessHubSession): void;\n create(options: HeadlessSessionHostOptions): Promise<HeadlessHubSession>;\n closeSession(sessionId: string, options?: HeadlessSessionCloseOptions): Promise<void>;\n /** Publishes removal of a persisted session that has no live host. */\n notifySessionRemoved(sessionId: string): void;\n /** Publishes a changed record of a persisted session that has no live host. */\n notifyDormantChanged(sessionId: string): void;\n /** Publishes setup-only children through the parent's normal session updates. */\n setPendingSessionSetups?(sessionId: string, pending: readonly PoPendingSessionSetup[]): void;\n /** Replaces the session's activity line; undefined clears it. Unknown sessions are ignored. */\n setSessionActivity?(sessionId: string, activity: PoSessionActivity | undefined): void;\n /** Dispatches an authenticated package API request inside the owning process. */\n requestSessionApi(scope: PoHubSessionScope, request: PoHubSessionApiRequest): Promise<Response>;\n /** Mounts the selected hub facets once, before the headless server accepts clients. */\n mountFacets(facets: readonly (PoServerFacet | LoadedServerFacet)[], context?: PoApiContext): Promise<void>;\n /**\n * Swaps a mounted global or workspace scope to a new facet set, with the context it was\n * mounted with. The old facets unwind through the same path `removeWorkspace` uses before\n * the new ones apply, so their API base paths and channels can be claimed again. When the\n * new set fails to install, the previous facets are reinstalled and the error is rethrown.\n */\n replaceFacets(mount: PoApiMount, facets: readonly (PoServerFacet | LoadedServerFacet)[]): Promise<void>;\n workspaces(): readonly HeadlessWorkspace[];\n registerWorkspace(workspace: HeadlessWorkspace): void;\n admitWorkspace(request: HeadlessWorkspaceAdmission): Promise<HeadlessWorkspace>;\n removeWorkspace(workspaceId: string): Promise<void>;\n requestApi(mount: PoApiMount, basePath: string, request: Request): Promise<Response>;\n /** The dispatch table hub facets mount into, shared with session hosts this hub serves. */\n readonly pluginRegistry: PoPluginRegistry;\n /** The edit presence ledger shared by every session host this hub serves. */\n readonly editPresence: PoEditPresenceLedger;\n invokePlugin(call: unknown, direction: PoPluginDirection, caller?: PoPluginCaller): Promise<unknown>;\n registerChannel(channel: PoHubChannel, mount?: PoApiMount): () => void;\n channelTypes(): readonly string[];\n channelFrames(sessionId: string): Array<{ type: string; sessionId: string; payload: unknown }>;\n /** Resolves a channel-owned child journal for the browser thread projection. */\n threadJournal(sessionId: string, threadId: string): string | undefined;\n receiveChannel(\n sessionId: string,\n frameType: string,\n payload: unknown,\n connectionId: string,\n desktopAuthorized?: boolean,\n computerUseAuthorized?: boolean,\n ): void;\n disconnectChannels(connectionId: string): void;\n close(): Promise<void>;\n}\n\ninterface StartedChannel {\n readonly channel: PoHubChannel;\n readonly source: ReturnType<PoHubChannel['start']>;\n readonly mount: PoApiMount;\n}\n\n/**\n * When a reopened session last settled, from the marker its runtime journals at every run end.\n * Without it a session with a whole history would read as fresh until its next turn.\n */\nasync function lastSettledAt(host: HeadlessSessionHost): Promise<string | undefined> {\n try {\n const entry = (await host.runtime.readEntries()).entries.findLast(\n (entry) => entry.type === 'custom' && entry.customType === AGENT_SETTLED_ENTRY_TYPE,\n );\n const data = entry?.type === 'custom' ? (entry.data as { timestamp?: unknown } | undefined) : undefined;\n return typeof data?.timestamp === 'number' && Number.isFinite(data.timestamp)\n ? new Date(data.timestamp).toISOString()\n : undefined;\n } catch {\n // A runtime without a readable journal has no history to report; the rail shows it as fresh.\n return undefined;\n }\n}\n\n/** The groups a resumed session was saved with. Sessions from before groups existed have none. */\nasync function storedGroups(host: HeadlessSessionHost, onNotice?: (message: string) => void): Promise<string[]> {\n try {\n const { groups } = (await host.runtime.session.snapshot(SessionMetadataDoc, BACKGROUND_CONTEXT)) as {\n groups?: unknown;\n };\n return Array.isArray(groups) ? groups.filter((group): group is string => typeof group === 'string') : [];\n } catch (error) {\n // The session still opens; it just starts outside its groups until they are set again.\n onNotice?.(`Session groups could not be read: ${String(error)}`);\n return [];\n }\n}\nfunction scopeOf(session: HeadlessHubSession): PoHubSessionScope {\n return {\n sessionId: session.id,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n cwd: session.cwd,\n ...(session.environment === undefined ? {} : { environment: session.environment }),\n ...(session.host.sessionContext === undefined ? {} : { sessionContext: session.host.sessionContext }),\n };\n}\n\n/** Owns direct, same-process session and channel state for presentation adapters. */\nexport function createHeadlessHub(options: HeadlessHubOptions): HeadlessHub {\n let gitPlatform = options.platform;\n const readGitStatus =\n options.readGitStatus ??\n ((cwd: string) => readSessionGitStatus((gitPlatform ??= createNodePlatform()).env(cwd), cwd));\n const sessions = new Map<string, HeadlessHubSession>();\n const pendingSetups = new Map<string, readonly PoPendingSessionSetup[]>();\n const activities = new Map<string, PoSessionActivity>();\n const present = (session: HeadlessHubSession): HeadlessHubSession => {\n const pending = pendingSetups.get(session.id);\n const activity = activities.get(session.id);\n if (pending === undefined && activity === undefined) return session;\n return {\n ...session,\n ...(pending === undefined ? {} : { pendingSetups: pending }),\n ...(activity === undefined ? {} : { activity }),\n };\n };\n const pluginRegistry = createPoPluginRegistry();\n const editPresence: PoEditPresenceLedger = new Map();\n const channels = new Map<string, StartedChannel>();\n const listeners = new Set<(event: HeadlessHubEvent) => void>();\n const subscriptions = new Set<() => void>();\n const sessionCleanups = new Map<string, () => void>();\n const presentationCleanups = new Map<string, () => void>();\n /** Profile icons by session, kept out of summaries because each can be hundreds of kilobytes. */\n const avatarIcons = new Map<string, string>();\n const sessionShutdowns = new Map<string, { session: HeadlessHubSession; promise: Promise<void>; pending: boolean }>();\n const directEventListeners = new Map<string, Set<(payload: unknown) => void>>();\n const directEventLatest = new Map<string, unknown>();\n const maxDirectEventLatest = 4096;\n const communicationEndpoints = new Map<\n string,\n {\n listeners: Map<string, Set<(sourceSessionId: string, payload: unknown) => void>>;\n readyListeners: Set<(peerSessionId: string) => void>;\n ready: boolean;\n endpoint: PoSessionCommunicationEndpoint;\n }\n >();\n let closed = false;\n interface FacetMount {\n host: PoServerHost;\n installed: InstalledServerFacets;\n /** Kept so `replaceFacets` remounts with the same context and can roll back. */\n context: PoApiContext;\n facets: readonly (PoServerFacet | LoadedServerFacet)[];\n }\n const mounts = new Map<string, FacetMount>();\n const disposeMount = async (mounted: FacetMount): Promise<void> => {\n try {\n await mounted.installed.dispose();\n } finally {\n mounted.host.dispose();\n }\n };\n const workspaces = new Map<string, HeadlessWorkspace>();\n const worktreeProvisioners = new Map<string, { mount: PoApiMount; provisioner: PoHubReservedWorktreeProvisioner }>();\n let sessionService: PoHubSessionService;\n\n const mountKey = (mount: PoApiMount): string =>\n mount.scope === 'global'\n ? 'global'\n : mount.scope === 'workspace'\n ? `workspace:${mount.workspaceId}`\n : `session:${mount.sessionId}`;\n const belongs = (mount: PoApiMount, session: HeadlessHubSession): boolean =>\n mount.scope === 'global' ||\n (mount.scope === 'workspace' ? session.workspaceId === mount.workspaceId : session.id === mount.sessionId);\n const canClose = (mount: PoApiMount, session: HeadlessHubSession): boolean =>\n belongs(mount, session) || (mount.scope === 'session' && session.parentSessionId === mount.sessionId);\n // Sessions executing in the same checkout share files, so they may message each other to resolve edits.\n // Sessions the user put in a shared group may message each other too.\n // Remote conversations are driven by an external client and keep the parent-child rule.\n const peers = (a: HeadlessHubSession, b: HeadlessHubSession): boolean => {\n if (\n a.sessionProvenance === REMOTE_CONVERSATION_SESSION_PROVENANCE ||\n b.sessionProvenance === REMOTE_CONVERSATION_SESSION_PROVENANCE\n )\n return false;\n const root = a.host.sessionContext?.checkoutRoot;\n if (root !== undefined && root === b.host.sessionContext?.checkoutRoot) return true;\n return (a.groups ?? []).some((group) => b.groups?.includes(group) === true);\n };\n const canCommunicate = (sourceId: string, targetId: string): boolean => {\n if (closed || sourceId === targetId) return false;\n const source = sessions.get(sourceId);\n const target = sessions.get(targetId);\n return (\n source !== undefined &&\n target !== undefined &&\n (source.parentSessionId === target.id || target.parentSessionId === source.id || peers(source, target))\n );\n };\n const registerReservedWorktreeProvisioner = (\n mount: PoApiMount,\n provisioner: PoHubReservedWorktreeProvisioner,\n ): (() => void) => {\n const key = mountKey(mount);\n if (worktreeProvisioners.has(key)) throw new Error('A worktree provisioner is already registered.');\n worktreeProvisioners.set(key, { mount, provisioner });\n return () => {\n if (worktreeProvisioners.get(key)?.provisioner === provisioner) worktreeProvisioners.delete(key);\n };\n };\n const worktreeProvisionerFor = (parent: HeadlessHubSession): PoHubReservedWorktreeProvisioner | undefined => {\n let provisioner: PoHubReservedWorktreeProvisioner | undefined;\n let priority = -1;\n for (const { mount, provisioner: candidate } of worktreeProvisioners.values()) {\n if (!belongs(mount, parent) || CHANNEL_PRIORITY[mount.scope] <= priority) continue;\n provisioner = candidate;\n priority = CHANNEL_PRIORITY[mount.scope];\n }\n return provisioner;\n };\n const selectedChannels = (session: HeadlessHubSession): StartedChannel[] => {\n const selected = new Map<string, StartedChannel>();\n for (const started of channels.values()) {\n if (!belongs(started.mount, session)) continue;\n const previous = selected.get(started.channel.frameType);\n if (!previous || CHANNEL_PRIORITY[started.mount.scope] > CHANNEL_PRIORITY[previous.mount.scope])\n selected.set(started.channel.frameType, started);\n }\n return [...selected.values()];\n };\n const selectedChannel = (session: HeadlessHubSession, frameType: string): StartedChannel | undefined =>\n selectedChannels(session).find((started) => started.channel.frameType === frameType);\n /**\n * One channel serves a session: the narrowest mount that reaches it. A package that\n * registers the same channel globally and per workspace would otherwise run two\n * sources against one session, and only the narrower one can publish or receive.\n *\n * Compared by mount scope rather than identity so a channel being started already\n * knows which sessions it is taking over.\n */\n const serves = (mount: PoApiMount, frameType: string, session: HeadlessHubSession): boolean => {\n if (!belongs(mount, session)) return false;\n const current = selectedChannel(session, frameType);\n return current === undefined || CHANNEL_PRIORITY[mount.scope] >= CHANNEL_PRIORITY[current.mount.scope];\n };\n\n const directEventKey = (frameType: string, sessionId: string): string => `${frameType}\\0${sessionId}`;\n const directEvents: PoDirectEventBus = {\n publish(frameType, sessionId, payload) {\n if (closed) return;\n const key = directEventKey(frameType, sessionId);\n directEventLatest.set(key, payload);\n while (directEventLatest.size > maxDirectEventLatest) {\n const oldest = directEventLatest.keys().next().value;\n if (oldest === undefined) break;\n directEventLatest.delete(oldest);\n }\n const listeners = directEventListeners.get(key);\n if (listeners === undefined) return;\n for (const listener of listeners) listener(payload);\n },\n subscribe(frameType, sessionId, listener, options) {\n if (closed) return () => undefined;\n const key = directEventKey(frameType, sessionId);\n const listeners = directEventListeners.get(key) ?? new Set<(payload: unknown) => void>();\n listeners.add(listener);\n directEventListeners.set(key, listeners);\n if (options?.replayLatest && directEventLatest.has(key)) listener(directEventLatest.get(key));\n let released = false;\n return () => {\n if (released) return;\n released = true;\n listeners.delete(listener);\n if (listeners.size === 0) directEventListeners.delete(key);\n };\n },\n clearSession(sessionId) {\n const suffix = `\\0${sessionId}`;\n for (const key of directEventLatest.keys()) if (key.endsWith(suffix)) directEventLatest.delete(key);\n },\n close() {\n directEventListeners.clear();\n directEventLatest.clear();\n },\n };\n\n const announceCommunicationReady = (sessionId: string): void => {\n const current = communicationEndpoints.get(sessionId);\n if (current?.ready !== true) return;\n for (const [peerSessionId, peer] of communicationEndpoints) {\n if (!peer.ready || !canCommunicate(sessionId, peerSessionId)) continue;\n for (const listener of current.readyListeners) listener(peerSessionId);\n for (const listener of peer.readyListeners) listener(sessionId);\n }\n };\n\n const bindCommunication = (sessionId: string): PoSessionCommunicationEndpoint => {\n const existing = communicationEndpoints.get(sessionId);\n if (existing !== undefined) return existing.endpoint;\n const listeners = new Map<string, Set<(sourceSessionId: string, payload: unknown) => void>>();\n const readyListeners = new Set<(peerSessionId: string) => void>();\n let endpoint!: PoSessionCommunicationEndpoint;\n const record = {\n listeners,\n readyListeners,\n ready: false,\n get endpoint() {\n return endpoint;\n },\n };\n endpoint = {\n sessionId,\n publish(targetSessionId, type, payload) {\n if (!canCommunicate(sessionId, targetSessionId)) return false;\n const target = communicationEndpoints.get(targetSessionId);\n if (target?.ready !== true) return false;\n for (const listener of target.listeners.get(type) ?? []) listener(sessionId, payload);\n return true;\n },\n subscribe(type, listener) {\n const current = listeners.get(type) ?? new Set<(sourceSessionId: string, payload: unknown) => void>();\n current.add(listener);\n listeners.set(type, current);\n return () => {\n current.delete(listener);\n if (current.size === 0) listeners.delete(type);\n };\n },\n onPeerReady(listener) {\n readyListeners.add(listener);\n if (!record.ready) {\n record.ready = true;\n announceCommunicationReady(sessionId);\n } else {\n for (const [peerSessionId, peer] of communicationEndpoints) {\n if (peer.ready && canCommunicate(sessionId, peerSessionId)) listener(peerSessionId);\n }\n }\n return () => readyListeners.delete(listener);\n },\n describePeer(peerSessionId) {\n if (!canCommunicate(sessionId, peerSessionId)) return undefined;\n const peer = sessions.get(peerSessionId);\n if (peer === undefined) return undefined;\n const source = sessions.get(sessionId)!;\n const own = source.groups ?? [];\n const sharedGroups = (peer.groups ?? []).filter((group) => own.includes(group));\n if (source.parentSessionId !== peer.id && peer.parentSessionId !== source.id && sharedGroups.length === 0)\n return undefined;\n const profile = peer.profile?.displayName ?? peer.profile?.name;\n return {\n sessionId: peerSessionId,\n name: peer.name,\n ...(profile === undefined ? {} : { profile }),\n sharedGroups,\n };\n },\n close() {\n if (communicationEndpoints.get(sessionId)?.endpoint !== endpoint) return;\n communicationEndpoints.delete(sessionId);\n listeners.clear();\n readyListeners.clear();\n },\n };\n communicationEndpoints.set(sessionId, record);\n return endpoint;\n };\n\n const queuedEvents: HeadlessHubEvent[] = [];\n let publishing = false;\n const emit = (event: HeadlessHubEvent): void => {\n if (closed) return;\n queuedEvents.push(event.kind === 'upsert' ? { ...event, session: present(event.session) } : event);\n if (publishing) return;\n publishing = true;\n try {\n for (let index = 0; index < queuedEvents.length; index += 1)\n for (const listener of listeners) listener(queuedEvents[index]);\n } finally {\n queuedEvents.length = 0;\n publishing = false;\n }\n };\n const sessionScopes = (): readonly PoHubSessionScope[] => [...sessions.values()].map(scopeOf);\n const publish = (frameType: string, sessionId: string, payload: unknown, connectionId?: string): void => {\n if (!sessions.has(sessionId)) return;\n emit({ kind: 'channel', frameType, sessionId, payload, ...(connectionId === undefined ? {} : { connectionId }) });\n };\n\n /**\n * Hub-owned calls carry the hub credential, so a session API can tell them from a\n * browser call it must not trust. Browser traffic reaches a session API through\n * requestApi instead, and keeps the headers its caller sent.\n */\n const hubAuthenticated = (request: PoHubSessionApiRequest): PoHubSessionApiRequest => {\n const token = options.hubToken?.();\n if (token === undefined || token === '') return request;\n const headers = new Headers(request.headers);\n if (headers.has(AUTHORIZATION_HEADER)) return request;\n headers.set(AUTHORIZATION_HEADER, `Bearer ${token}`);\n return { ...request, headers };\n };\n\n const reservationsFor = (mount: PoApiMount): PoHubSessionReservations | undefined => {\n const reservations = options.sessionReservations;\n if (!reservations) return undefined;\n const check = (parentId: string): void => {\n const parent = sessions.get(parentId);\n if (!parent || !belongs(mount, parent)) throw new Error('Parent session is outside this mount.');\n };\n return {\n read: (id, parentId) => {\n check(parentId);\n return reservations.read(id, parentId);\n },\n prepare: (id, parentId, cwd) => {\n check(parentId);\n return reservations.prepare(id, parentId, cwd);\n },\n complete: (id, parentId) => {\n check(parentId);\n return reservations.complete(id, parentId);\n },\n };\n };\n const channelHost = (frameType: string, mount: PoApiMount): PoHubChannelHost => ({\n sessions: () =>\n sessionScopes().filter((scope) => {\n const session = sessions.get(scope.sessionId);\n return session !== undefined && serves(mount, frameType, session);\n }),\n sessionService: {\n reservations: reservationsFor(mount),\n create: async (request) => {\n // A workspace package may start a top-level session, placed in its own workspace.\n if (mount.scope === 'workspace' && request.parentSessionId === undefined) {\n if (request.reservationId !== undefined) throw new Error('A reserved session requires its owning parent.');\n if (options.createSession === undefined)\n throw new Error('The cockpit session service cannot create sessions in this host.');\n return options.createSession(request, { workspaceId: mount.workspaceId });\n }\n if (mount.scope !== 'global') {\n const parent = request.parentSessionId === undefined ? undefined : sessions.get(request.parentSessionId);\n if (!parent || !belongs(mount, parent)) throw new Error('Parent session is outside this mount.');\n }\n return sessionService.create(request);\n },\n close: async (id) => {\n const session = sessions.get(id);\n if (session === undefined) {\n const shutdown = sessionShutdowns.get(id);\n if (shutdown !== undefined) {\n if (!canClose(mount, shutdown.session)) throw new Error('Session is outside this mount.');\n await shutdown.promise;\n }\n return;\n }\n if (!canClose(mount, session)) throw new Error('Session is outside this mount.');\n await sessionService.close(id);\n },\n isLive: (id) => sessionService.isLive(id),\n registerReservedWorktreeProvisioner: (provisioner) => registerReservedWorktreeProvisioner(mount, provisioner),\n canCommunicate: (sourceId, targetId) => {\n const source = sessions.get(sourceId);\n return (\n source !== undefined && belongs(mount, source) && sessionService.canCommunicate?.(sourceId, targetId) === true\n );\n },\n },\n directEvents: {\n publish: (type, id, payload) => {\n const session = sessions.get(id);\n if (session && serves(mount, frameType, session)) directEvents.publish(type, id, payload);\n },\n subscribe: (type, id, listener, subscriptionOptions) => {\n const session = sessions.get(id);\n return session && serves(mount, frameType, session)\n ? directEvents.subscribe(type, id, listener, subscriptionOptions)\n : () => undefined;\n },\n close: () => undefined,\n },\n publish: (sessionId, payload) => {\n const session = sessions.get(sessionId);\n if (session && serves(mount, frameType, session)) publish(frameType, sessionId, payload);\n },\n publishToConnection: (connectionId, sessionId, payload) => {\n const session = sessions.get(sessionId);\n if (connectionId === '' || !session || !serves(mount, frameType, session)) return false;\n publish(frameType, sessionId, payload, connectionId);\n return true;\n },\n requestSessionApi: async (scope, request) => {\n const session = sessions.get(scope.sessionId);\n if (!session || !belongs(mount, session)) return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (options.requestSessionApi === undefined)\n return Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n return options.requestSessionApi(scope, hubAuthenticated(request));\n },\n ...(options.computerUse === undefined\n ? {}\n : {\n computerUse: {\n get available() {\n return options.computerUse!.available;\n },\n request(scope, request) {\n const session = sessions.get(scope.sessionId);\n if (!session || !belongs(mount, session)) throw new Error('Computer-use session is outside this mount.');\n return options.computerUse!.request(scopeOf(session), request);\n },\n },\n }),\n onNotice: (message) => options.onNotice?.(message),\n });\n\n const startChannel = (channel: PoHubChannel, mount: PoApiMount): StartedChannel | undefined => {\n const key = `${mountKey(mount)}:${channel.frameType}`;\n if (channels.has(key)) {\n options.onNotice?.(`hub channel '${channel.frameType}' is already registered`);\n return undefined;\n }\n try {\n const displaced = new Map<string, StartedChannel>();\n for (const session of sessions.values()) {\n if (!belongs(mount, session)) continue;\n const previous = selectedChannel(session, channel.frameType);\n if (previous !== undefined) displaced.set(session.id, previous);\n }\n const source = channel.start(channelHost(channel.frameType, mount));\n const started = { channel, source, mount };\n channels.set(key, started);\n for (const session of sessions.values()) {\n if (selectedChannel(session, channel.frameType) !== started) continue;\n displaced.get(session.id)?.source.sessionRemoved?.(session.id);\n source.sessionAdded?.(scopeOf(session));\n }\n return started;\n } catch (error) {\n options.onNotice?.(`hub channel '${channel.frameType}' failed (${String(error)})`);\n return undefined;\n }\n };\n\n const releaseChannel = (channel: PoHubChannel, started: StartedChannel): void => {\n const key = `${mountKey(started.mount)}:${channel.frameType}`;\n if (channels.get(key) !== started) return;\n const served = [...sessions.values()].filter((session) => selectedChannel(session, channel.frameType) === started);\n channels.delete(key);\n started.source.close();\n for (const session of served) selectedChannel(session, channel.frameType)?.source.sessionAdded?.(scopeOf(session));\n };\n\n const receiveMountedChannel = (\n mount: PoApiMount,\n sessionId: string,\n frameType: string,\n payload: unknown,\n connectionId: string,\n ): boolean => {\n if (!connectionId) return false;\n const session = sessions.get(sessionId);\n if (!session || !belongs(mount, session)) return false;\n const started = channels.get(`${mountKey(mount)}:${frameType}`);\n if (!started?.channel.receive) return false;\n started.channel.receive(scopeOf(session), payload, { connectionId });\n return true;\n };\n\n const unregisterSession = (sessionId: string, closeOptions?: HeadlessSessionCloseOptions): void => {\n const current = sessions.get(sessionId);\n if (current === undefined) return;\n const cleanup = sessionCleanups.get(sessionId);\n if (cleanup !== undefined) subscriptions.delete(cleanup);\n communicationEndpoints.get(sessionId)?.endpoint.close();\n // Let scoped sources dispatch their final stop while the live-session boundary still admits it.\n try {\n for (const { source } of selectedChannels(current)) source.sessionRemoved?.(sessionId);\n options.computerUse?.forgetSession?.(sessionId);\n } finally {\n // A failing external stop must not leave a closed host registered.\n sessions.delete(sessionId);\n activities.delete(sessionId);\n sessionCleanups.delete(sessionId);\n presentationCleanups.get(sessionId)?.();\n presentationCleanups.delete(sessionId);\n avatarIcons.delete(sessionId);\n directEvents.clearSession?.(sessionId);\n }\n emit({ kind: 'removed', sessionId, ...(closeOptions?.keepDormant === true ? { dormant: true as const } : {}) });\n };\n\n const startSessionShutdown = (\n session: HeadlessHubSession,\n closeOptions?: HeadlessSessionCloseOptions,\n ): Promise<void> => {\n const existing = sessionShutdowns.get(session.id);\n if (existing !== undefined) return existing.promise;\n const shutdown = { session, promise: Promise.resolve(), pending: true };\n const promise = Promise.resolve().then(() =>\n closeOptions === undefined\n ? options.manager.closeSession(session.id)\n : options.manager.closeSession(session.id, closeOptions),\n );\n shutdown.promise = promise;\n sessionShutdowns.set(session.id, shutdown);\n void promise.then(\n () => {\n shutdown.pending = false;\n if (sessionShutdowns.get(session.id) === shutdown) sessionShutdowns.delete(session.id);\n },\n () => {\n shutdown.pending = false;\n },\n );\n return promise;\n };\n\n const register = (session: HeadlessHubSession): void => {\n if (closed) throw new Error('The headless hub is closed.');\n if (sessions.has(session.id)) throw new Error(`Session '${session.id}' is already registered.`);\n if (sessionShutdowns.get(session.id)?.pending) throw new Error(`Session '${session.id}' is still shutting down.`);\n // A failed shutdown stays visible to scoped closers until the id is reused. Reopening\n // the session is that reuse, so it must not be blocked by the stale failure.\n sessionShutdowns.delete(session.id);\n let current: HeadlessHubSession = {\n ...session,\n updatedAt: session.updatedAt ?? session.createdAt,\n phase: session.phase ?? 'idle',\n phaseSince: session.phaseSince ?? session.createdAt,\n pendingMessageCount: session.pendingMessageCount ?? 0,\n everPrompted: session.everPrompted ?? false,\n awaitingInput: session.awaitingInput ?? false,\n };\n sessions.set(session.id, current);\n announceCommunicationReady(session.id);\n // Branch changes happen inside runs, so the status is read at start and after each settle.\n const refreshGit = (): void => {\n void readGitStatus(session.cwd).then(\n (git) => {\n if (closed || sessions.get(session.id)?.host !== session.host) return;\n if (git?.branch === current.git?.branch && git?.dirty === current.git?.dirty) return;\n const { git: _previous, ...rest } = current;\n current = git === undefined ? rest : { ...rest, git };\n sessions.set(session.id, current);\n emit({ kind: 'upsert', session: current });\n },\n (error: unknown) =>\n options.onNotice?.(\n `session ${session.id} git status failed (${error instanceof Error ? error.message : String(error)})`,\n ),\n );\n };\n const stopPresentation = session.host.onPresentationFrame((frame) => {\n if (sessions.get(session.id)?.host !== session.host) return;\n const type = typeof frame.type === 'string' ? frame.type : '';\n const entry = frame.entry as { customType?: unknown } | undefined;\n if (type === 'entry_appended' && entry?.customType === PO_NOTIFICATION_ENTRY_TYPE) {\n emit({ kind: 'frame', sessionId: session.id, frame });\n return;\n }\n // Streaming updates belong to the session presentation. Replicating the\n // hub's growing event list for every token makes model output quadratic.\n if (\n type !== 'agent_start' &&\n type !== 'agent_settled' &&\n type !== 'message_end' &&\n type !== 'session_info_changed' &&\n type !== SESSION_GROUPS_CHANGED_FRAME &&\n type !== 'extension_ui_request' &&\n type !== 'extension_ui_answered'\n )\n return;\n const now = new Date().toISOString();\n const phase = type === 'agent_start' ? 'turn' : type === 'agent_settled' ? 'idle' : current.phase;\n const phaseChanged = phase !== current.phase;\n const method = typeof frame.method === 'string' ? frame.method : '';\n const dialog = type === 'extension_ui_request' && ['select', 'confirm', 'input', 'editor'].includes(method);\n const awaitingInput = dialog\n ? true\n : type === 'extension_ui_answered' || type === 'agent_settled'\n ? false\n : current.awaitingInput;\n const groups =\n type === SESSION_GROUPS_CHANGED_FRAME && Array.isArray(frame.groups)\n ? frame.groups.filter((group): group is string => typeof group === 'string')\n : current.groups;\n current = {\n ...current,\n name: type === 'session_info_changed' && typeof frame.name === 'string' ? frame.name : current.name,\n ...(groups === undefined ? {} : { groups }),\n updatedAt: now,\n phase,\n phaseSince: phaseChanged ? now : current.phaseSince,\n everPrompted: current.everPrompted || type === 'agent_start',\n awaitingInput,\n ...(type === 'agent_settled' ? { lastSettledAt: now } : {}),\n };\n sessions.set(session.id, current);\n emit({ kind: 'upsert', session: current });\n // A new shared group makes new peers: tell both sides, as a fresh endpoint would be told.\n if (type === SESSION_GROUPS_CHANGED_FRAME) announceCommunicationReady(session.id);\n // Only the prompt text travels: options and defaults stay with the focused presentation.\n if (dialog) {\n const text = (key: string) => (typeof frame[key] === 'string' ? { [key]: frame[key] } : {});\n emit({\n kind: 'frame',\n sessionId: session.id,\n frame: { type, ...text('id'), method, ...text('title'), ...text('message') },\n });\n }\n if (type === 'agent_settled') refreshGit();\n });\n let registered = false;\n const root = (): string => (session.workspaceId && workspaces.get(session.workspaceId)?.root) || session.cwd;\n let compositionMode: string | undefined;\n const applyCompositions = (majorMode: string): boolean => {\n if (!options.publishSessionCompositions || majorMode === compositionMode) return false;\n compositionMode = majorMode;\n try {\n const { webComposition, nativeComposition } = options.publishSessionCompositions(session.id, root(), majorMode);\n current = { ...current, webComposition, nativeComposition };\n return true;\n } catch (error) {\n options.onNotice?.(\n `session ${session.id} plugins for major mode \"${majorMode}\" could not be published (${error instanceof Error ? error.message : String(error)})`,\n );\n return false;\n }\n };\n const applyProfile = (profileName: string | undefined): boolean => {\n let identity: HeadlessProfileIdentity | undefined;\n if (profileName) {\n try {\n identity = options.resolveProfileIdentity?.(root(), profileName);\n } catch (error) {\n options.onNotice?.(\n `session ${session.id} profile \"${profileName}\" could not be resolved (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n }\n const icon = identity?.icon;\n if (icon) avatarIcons.set(session.id, icon);\n else avatarIcons.delete(session.id);\n const profile: HeadlessSessionProfile | undefined = profileName\n ? {\n name: profileName,\n ...(identity?.displayName ? { displayName: identity.displayName } : {}),\n ...(icon\n ? { iconVersion: crypto.createHash('sha256').update(icon).digest('hex').slice(0, ICON_VERSION_LENGTH) }\n : {}),\n }\n : undefined;\n const previous = current.profile;\n if (\n previous?.name === profile?.name &&\n previous?.displayName === profile?.displayName &&\n previous?.iconVersion === profile?.iconVersion\n )\n return false;\n const { profile: _previous, ...rest } = current;\n current = profile === undefined ? rest : { ...rest, profile };\n return true;\n };\n const applySelection = (selection: PoHeadlessSelection): void => {\n if (closed || sessions.get(session.id)?.host !== session.host) return;\n const compositionsChanged = applyCompositions(selection.majorMode);\n const profileChanged = applyProfile(selection.profile);\n if (!compositionsChanged && !profileChanged) return;\n sessions.set(session.id, current);\n if (registered) emit({ kind: 'upsert', session: current });\n };\n const stopSelection = session.host.onSelection?.(applySelection);\n presentationCleanups.set(session.id, () => {\n stopPresentation();\n stopSelection?.();\n });\n for (const { source } of selectedChannels(current)) source.sessionAdded?.(scopeOf(session));\n const active = (): boolean => sessions.get(session.id)?.host === session.host && !closed;\n const cleanup = (): void => {\n subscriptions.delete(cleanup);\n sessionCleanups.delete(session.id);\n if (!active()) return;\n void closeSession(session.id).catch((error: unknown) =>\n options.onNotice?.(\n `session ${session.id} cleanup failed (${error instanceof Error ? error.message : String(error)})`,\n ),\n );\n };\n sessionCleanups.set(session.id, cleanup);\n void session.host.runtime.exited.then(cleanup, cleanup);\n subscriptions.add(cleanup);\n registered = true;\n emit({ kind: 'upsert', session: current });\n refreshGit();\n };\n\n const closeSession = async (sessionId: string, closeOptions?: HeadlessSessionCloseOptions): Promise<void> => {\n const pending = sessionShutdowns.get(sessionId);\n if (pending !== undefined) {\n await pending.promise;\n return;\n }\n const session = sessions.get(sessionId);\n if (session === undefined) return;\n unregisterSession(sessionId, closeOptions);\n await startSessionShutdown(session, closeOptions);\n };\n\n const promptTarget = (sessionId: string, parentSessionId: string | undefined): HeadlessHubSession => {\n const session = closed ? undefined : sessions.get(sessionId);\n if (session === undefined) throw new Error('The session is not live.');\n if (parentSessionId !== undefined && session.parentSessionId !== parentSessionId)\n throw new Error('Only the parent session can drive this session.');\n return session;\n };\n\n sessionService = {\n create: async (request) => {\n if (options.createSession === undefined)\n throw new Error('The cockpit session service cannot create sessions in this host.');\n return options.createSession(request);\n },\n close: closeSession,\n isLive: (sessionId) => !closed && sessions.has(sessionId),\n readExecutionState: async (sessionId, readOptions) => {\n const target = promptTarget(sessionId, readOptions?.parentSessionId);\n if (!target.host.readExecutionState) throw new Error('The session cannot report execution state.');\n return target.host.readExecutionState();\n },\n prompt: async (sessionId, text, promptOptions) => {\n promptOptions?.signal?.throwIfAborted();\n const { settled } = await promptTarget(sessionId, promptOptions?.parentSessionId).host.runtime.submitPrompt(text);\n return { settled };\n },\n abort: async (sessionId, abortOptions) => {\n await promptTarget(sessionId, abortOptions?.parentSessionId).host.runtime.abort();\n },\n steer: async (sessionId, message, steerOptions) => {\n await promptTarget(sessionId, steerOptions?.parentSessionId).host.runtime.steer(message);\n },\n release: async (sessionId, releaseOptions) => {\n promptTarget(sessionId, releaseOptions?.parentSessionId);\n await closeSession(sessionId, { keepDormant: true });\n },\n reservations: options.sessionReservations,\n provisionReservedWorktree: async (request) => {\n const parent = sessions.get(request.parentSessionId);\n const provisioner = parent === undefined ? undefined : worktreeProvisionerFor(parent);\n if (provisioner === undefined) throw new Error('Automatic conversation worktree provisioning is unavailable.');\n return provisioner(request);\n },\n registerReservedWorktreeProvisioner: (provisioner) =>\n registerReservedWorktreeProvisioner({ scope: 'global' }, provisioner),\n canCommunicate,\n bindCommunication,\n };\n\n const installMount = async (\n facets: readonly (PoServerFacet | LoadedServerFacet)[],\n suppliedContext: PoApiContext | undefined,\n announceWorkspace: boolean,\n ): Promise<void> => {\n if (closed) throw new Error('The headless hub is closed.');\n const context: PoApiContext = suppliedContext ?? {\n scope: 'global',\n ...(options.hubToken?.() === undefined ? {} : { hubToken: options.hubToken() }),\n sessionService,\n directEvents,\n onNotice: (message) => options.onNotice?.(message),\n };\n if (context.scope === 'session') throw new Error('Session facets belong to their session host.');\n if (context.scope === 'workspace' && (!context.workspaceId || !context.workspaceRoot))\n throw new Error('Workspace mounts require an admitted identity and root.');\n const mount: PoApiMount =\n context.scope === 'global' ? { scope: 'global' } : { scope: 'workspace', workspaceId: context.workspaceId! };\n const key = mountKey(mount);\n if (mounts.has(key)) throw new Error(`The '${key}' facets are already mounted.`);\n const host = createPoServerHost({\n scope: context.scope,\n context: {\n ...context,\n sessionService: channelHost('', mount).sessionService,\n directEvents: channelHost('', mount).directEvents,\n receiveChannel: (sessionId, frameType, payload, connectionId) =>\n receiveMountedChannel(mount, sessionId, frameType, payload, connectionId),\n },\n mountChannel: (channel) => {\n const started = startChannel(channel, mount);\n if (started === undefined) return { mounted: false, dispose: () => undefined };\n return { mounted: true, dispose: () => releaseChannel(channel, started) };\n },\n pluginRegistry,\n });\n try {\n const installed = await installServerFacets({\n host,\n facets,\n onNotice: options.onNotice,\n ...(options.platform === undefined ? {} : { platform: options.platform }),\n });\n if (closed) {\n await installed.dispose();\n throw new Error('The headless hub was closed while mounting facets.');\n }\n mounts.set(key, { host, installed, context, facets });\n if (announceWorkspace && mount.scope === 'workspace') {\n const workspace = { id: mount.workspaceId, root: context.workspaceRoot!, available: true };\n workspaces.set(mount.workspaceId, workspace);\n emit({ kind: 'workspace_upsert', workspace });\n }\n } catch (error) {\n host.dispose();\n throw error;\n }\n };\n const mountFacets = (\n facets: readonly (PoServerFacet | LoadedServerFacet)[],\n suppliedContext?: PoApiContext,\n ): Promise<void> => installMount(facets, suppliedContext, true);\n const replacements = new Map<string, Promise<void>>();\n const replaceFacets = (mount: PoApiMount, facets: readonly (PoServerFacet | LoadedServerFacet)[]): Promise<void> => {\n if (mount.scope === 'session') return Promise.reject(new Error('Session facets belong to their session host.'));\n const key = mountKey(mount);\n // One swap at a time per mount, so a second check never disposes a set mid-install.\n const run = (replacements.get(key) ?? Promise.resolve()).then(async () => {\n if (closed) throw new Error('The headless hub is closed.');\n const previous = mounts.get(key);\n if (previous === undefined) throw new Error(`The '${key}' facets are not mounted.`);\n mounts.delete(key);\n await disposeMount(previous);\n // A workspace removed while its old set unwound stays removed.\n if (closed || (mount.scope === 'workspace' && !workspaces.has(mount.workspaceId))) return;\n try {\n await installMount(facets, previous.context, false);\n } catch (error) {\n await installMount(previous.facets, previous.context, false).catch((rollbackError: unknown) =>\n options.onNotice?.(\n `The '${key}' facets could not be restored (${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)})`,\n ),\n );\n throw error;\n }\n });\n const settled = run.then(\n () => undefined,\n () => undefined,\n );\n replacements.set(key, settled);\n void settled.then(() => {\n if (replacements.get(key) === settled) replacements.delete(key);\n });\n return run;\n };\n\n return {\n sessionService,\n directEvents,\n ...(options.computerUse === undefined ? {} : { computerUse: options.computerUse }),\n async readHome(request, authorizeSession) {\n if (\n !request ||\n typeof request !== 'object' ||\n Array.isArray(request) ||\n (request.source !== undefined && (typeof request.source !== 'string' || request.source.length > 128)) ||\n (request.workspaceId !== undefined &&\n (typeof request.workspaceId !== 'string' || request.workspaceId.length > 256))\n )\n throw new Error('Invalid Home request.');\n const offset = Number.isSafeInteger(request?.offset) && request.offset! >= 0 ? request.offset! : 0;\n const limit =\n Number.isSafeInteger(request?.limit) && request.limit! > 0\n ? Math.min(request.limit!, HOME_PAGE_LIMIT)\n : HOME_PAGE_LIMIT;\n const counts: HomeSnapshot['counts'] = {\n decision: 0,\n failure: 0,\n blocked: 0,\n running: 0,\n queued: 0,\n paused: 0,\n completed: 0,\n };\n const statuses = new Map<string, HomeSourceStatus>();\n const entities = new Map<string, HomeItem>();\n let examined = 0;\n let projectors = 0;\n for (const session of sessions.values()) {\n if (\n closed ||\n !authorizeSession(session.id) ||\n (request.workspaceId !== undefined && request.workspaceId !== session.workspaceId)\n )\n continue;\n for (const { channel, source } of selectedChannels(session)) {\n if (!source.homeFor || (request.source !== undefined && request.source !== channel.frameType)) continue;\n const key = JSON.stringify([channel.frameType, session.workspaceId]);\n const status = statuses.get(key) ?? {\n source: channel.frameType,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n coverage: 'ready' as const,\n };\n statuses.set(key, status);\n if (examined >= HOME_ENTITY_LIMIT || projectors++ >= HOME_ENTITY_LIMIT) {\n status.coverage = 'partial';\n continue;\n }\n try {\n const projection = parseHomeProjection(source.homeFor(scopeOf(session)));\n if (!projection) {\n status.coverage = 'partial';\n continue;\n }\n if (projection.coverage === 'partial' || status.coverage === 'partial') status.coverage = 'partial';\n else if (projection.coverage === 'unavailable') status.coverage = 'unavailable';\n for (const entity of projection.entities) {\n examined += 1;\n if (examined > HOME_ENTITY_LIMIT) {\n status.coverage = 'partial';\n break;\n }\n const allowed = [entity.sessionId, ...(entity.relatedSessionIds ?? [])].every((id) => {\n const referenced = sessions.get(id);\n return (\n referenced !== undefined && referenced.workspaceId === session.workspaceId && authorizeSession(id)\n );\n });\n if (!allowed) {\n status.coverage = 'partial';\n continue;\n }\n const { relatedSessionIds: _related, ...publicEntity } = entity;\n const identity = JSON.stringify([channel.frameType, session.workspaceId, entity.id]);\n const previous = entities.get(identity);\n if (!previous || Date.parse(entity.updatedAt) > Date.parse(previous.updatedAt))\n entities.set(identity, {\n ...publicEntity,\n source: channel.frameType,\n ...(session.workspaceId === undefined ? {} : { workspaceId: session.workspaceId }),\n });\n }\n } catch {\n // A package projector cannot fail the read or claim complete coverage.\n status.coverage = 'partial';\n }\n }\n }\n for (const status of statuses.values())\n status.counts = { decision: 0, failure: 0, blocked: 0, running: 0, queued: 0, paused: 0, completed: 0 };\n for (const entity of entities.values()) {\n const status = statuses.get(JSON.stringify([entity.source, entity.workspaceId]));\n if (status?.counts) status.counts[entity.kind] += 1;\n }\n const attention = [...entities.values()]\n .filter((entity) => {\n counts[entity.kind] += 1;\n return ['decision', 'failure', 'blocked', 'paused'].includes(entity.kind);\n })\n .sort(\n (a, b) =>\n ['decision', 'failure', 'blocked', 'paused'].indexOf(a.kind) -\n ['decision', 'failure', 'blocked', 'paused'].indexOf(b.kind) ||\n Date.parse(b.updatedAt) - Date.parse(a.updatedAt) ||\n a.id.localeCompare(b.id) ||\n a.source.localeCompare(b.source),\n );\n return {\n version: 1,\n observedAt: new Date().toISOString(),\n sources: [...statuses.values()],\n counts,\n items: attention.slice(offset, offset + limit),\n total: attention.length,\n ...(offset + limit < attention.length ? { nextOffset: offset + limit } : {}),\n };\n },\n snapshot: () => [...sessions.values()].map(present),\n session: (sessionId) => {\n const session = sessions.get(sessionId);\n return session === undefined ? undefined : present(session);\n },\n setPendingSessionSetups(sessionId, pending) {\n if (JSON.stringify(pendingSetups.get(sessionId) ?? []) === JSON.stringify(pending)) return;\n pendingSetups.set(sessionId, Object.freeze([...pending]));\n const session = sessions.get(sessionId);\n if (session) emit({ kind: 'upsert', session: present(session) });\n },\n setSessionActivity(sessionId, activity) {\n const session = sessions.get(sessionId);\n if (session === undefined) return;\n const next: PoSessionActivity | undefined =\n activity === undefined\n ? undefined\n : Object.freeze({\n label: activity.label.slice(0, MAX_ACTIVITY_LABEL),\n ...(activity.attention === true ? { attention: true } : {}),\n ...(activity.since === undefined ? {} : { since: activity.since }),\n });\n if (JSON.stringify(activities.get(sessionId)) === JSON.stringify(next)) return;\n if (next === undefined) activities.delete(sessionId);\n else activities.set(sessionId, next);\n emit({ kind: 'upsert', session: present(session) });\n },\n runtime: (sessionId) => sessions.get(sessionId)?.host.runtime,\n sessionAvatar(sessionId) {\n const match = ICON_DATA_URL.exec(avatarIcons.get(sessionId) ?? '');\n const mimeType = match?.[1];\n if (match === null || !(PROFILE_ICON_MIME_TYPES as readonly string[]).includes(mimeType ?? '')) return undefined;\n return { mimeType: mimeType!, bytes: Buffer.from(match[2]!, 'base64') };\n },\n onEvent(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n register,\n notifySessionRemoved(sessionId) {\n emit({ kind: 'removed', sessionId });\n },\n notifyDormantChanged(sessionId) {\n emit({ kind: 'dormant_changed', sessionId });\n },\n mountFacets,\n replaceFacets,\n workspaces: () => [...workspaces.values()],\n registerWorkspace(workspace) {\n workspaces.set(workspace.id, workspace);\n emit({ kind: 'workspace_upsert', workspace });\n },\n admitWorkspace: async (request) => {\n if (!options.admitWorkspace) throw new Error('Workspace admission is unavailable.');\n return options.admitWorkspace(request);\n },\n async removeWorkspace(id) {\n if ([...sessions.values()].some((session) => session.workspaceId === id))\n throw new Error('Workspace still has live sessions.');\n const key = mountKey({ scope: 'workspace', workspaceId: id });\n const mounted = mounts.get(key);\n if (!workspaces.has(id)) return;\n options.onWorkspaceRemoved?.(id);\n workspaces.delete(id);\n emit({ kind: 'workspace_removed', workspaceId: id });\n if (!mounted) return;\n mounts.delete(key);\n await disposeMount(mounted);\n },\n async requestApi(mount, basePath, request) {\n if (closed) return Response.json({ error: 'Server is closed.' }, { status: 503 });\n if (mount.scope === 'session') {\n const session = sessions.get(mount.sessionId);\n if (!session || !options.requestSessionApi)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n const url = new URL(request.url);\n return options.requestSessionApi(scopeOf(session), {\n basePath,\n path: `${url.pathname}${url.search}`,\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n body: request.body === null ? undefined : new Uint8Array(await request.arrayBuffer()),\n });\n }\n const handler = mounts.get(mountKey(mount))?.host.handlerFor(basePath);\n if (!handler)\n return Response.json({ error: `API '${basePath}' is not mounted in ${mountKey(mount)}.` }, { status: 404 });\n return handler.fetch(request);\n },\n pluginRegistry,\n editPresence,\n invokePlugin: (call, direction, caller) => pluginRegistry.invoke(call, direction, caller),\n async create(sessionOptions) {\n const id = sessionOptions.sessionId;\n if (closed) throw new Error('The headless hub is closed.');\n // Checked before building the host: once it exists, a refusal has to close it, and a\n // duplicate id would then close the live session that already owns the id.\n if (sessions.has(id)) throw new Error(`Session '${id}' is already registered.`);\n if (sessionShutdowns.get(id)?.pending) throw new Error(`Session '${id}' is still shutting down.`);\n const host = await options.manager.create(sessionOptions);\n const settledAt = await lastSettledAt(host);\n const groups = await storedGroups(host, options.onNotice);\n const session: HeadlessHubSession = {\n id: sessionOptions.sessionId,\n workspaceId: sessionOptions.workspaceId,\n webComposition: sessionOptions.webComposition,\n nativeComposition: sessionOptions.nativeComposition,\n name: sessionOptions.sessionName,\n cwd: sessionOptions.cwd,\n createdAt: new Date().toISOString(),\n ...(sessionOptions.parentSessionId === undefined ? {} : { parentSessionId: sessionOptions.parentSessionId }),\n ...(sessionOptions.sessionProvenance === undefined\n ? {}\n : { sessionProvenance: sessionOptions.sessionProvenance }),\n environment: sessionOptions.environment,\n ...(settledAt === undefined ? {} : { everPrompted: true, lastSettledAt: settledAt }),\n groups,\n host,\n };\n try {\n register(session);\n } catch (error) {\n // Registration can fail after publishing the host into the session map.\n // Roll back only our host, never a different session that owns this id.\n if (sessions.get(id)?.host === host) {\n try {\n unregisterSession(id);\n } catch (cleanupError) {\n options.onNotice?.(`Session '${id}' registration rollback failed: ${String(cleanupError)}`);\n }\n }\n // The hub closed, or a racing create took the id, while this host was starting.\n await Promise.resolve(options.manager.closeSession(id)).catch((closeError: unknown) =>\n options.onNotice?.(`Session '${id}' could not be closed after a failed registration: ${String(closeError)}`),\n );\n throw error;\n }\n return session;\n },\n closeSession,\n async requestSessionApi(scope, request) {\n if (closed || !sessions.has(scope.sessionId))\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (options.requestSessionApi === undefined)\n return Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n return options.requestSessionApi(scope, request);\n },\n registerChannel(channel, mount = { scope: 'global' }) {\n const started = startChannel(channel, mount);\n if (started === undefined) return () => undefined;\n return () => releaseChannel(channel, started);\n },\n channelTypes: () => [...new Set([...channels.values()].map(({ channel }) => channel.frameType))],\n channelFrames(sessionId) {\n const session = sessions.get(sessionId);\n if (session === undefined) return [];\n const scope = scopeOf(session);\n const frames: Array<{ type: string; sessionId: string; payload: unknown }> = [];\n for (const { channel, source } of selectedChannels(session)) {\n const type = channel.frameType;\n const payload = source.payloadFor(scope);\n if (payload !== undefined) frames.push({ type, sessionId, payload });\n }\n return frames;\n },\n threadJournal(sessionId, threadId) {\n const session = sessions.get(sessionId);\n if (session === undefined) return undefined;\n const scope = scopeOf(session);\n for (const { source } of selectedChannels(session)) {\n const journal = source.threadJournal?.(scope, threadId);\n if (journal !== undefined) return journal;\n }\n return undefined;\n },\n receiveChannel(\n sessionId,\n frameType,\n payload,\n connectionId,\n desktopAuthorized = false,\n computerUseAuthorized = false,\n ) {\n if (connectionId === '') return;\n const session = sessions.get(sessionId);\n const started = session && selectedChannels(session).find(({ channel }) => channel.frameType === frameType);\n if (session === undefined || started === undefined) return;\n started.channel.receive?.(scopeOf(session), payload, {\n connectionId,\n ...(desktopAuthorized ? { desktopAuthorized: true } : {}),\n ...(computerUseAuthorized ? { computerUseAuthorized: true } : {}),\n } satisfies PoHubChannelConnection);\n },\n disconnectChannels(connectionId) {\n if (connectionId === '') return;\n for (const { channel } of channels.values()) channel.disconnected?.({ connectionId });\n },\n async close() {\n if (closed) return;\n const ids = [...sessions.keys()];\n closed = true;\n directEvents.close();\n for (const unsubscribe of subscriptions) unsubscribe();\n subscriptions.clear();\n for (const cleanup of presentationCleanups.values()) cleanup();\n presentationCleanups.clear();\n const failures: unknown[] = [];\n for (const mounted of [...mounts.values()].reverse()) {\n try {\n await mounted.installed.dispose();\n } catch (error) {\n failures.push(error);\n }\n try {\n mounted.host.dispose();\n } catch (error) {\n failures.push(error);\n }\n }\n mounts.clear();\n pluginRegistry.dispose();\n editPresence.clear();\n workspaces.clear();\n for (const { source } of channels.values()) source.close();\n channels.clear();\n listeners.clear();\n const shutdowns: Promise<void>[] = [...sessionShutdowns.values()]\n .filter(({ pending }) => pending)\n .map(({ promise }) => promise);\n for (const id of ids) {\n const session = sessions.get(id);\n if (session !== undefined && !sessionShutdowns.has(id)) shutdowns.push(startSessionShutdown(session));\n }\n sessions.clear();\n const outcomes = await Promise.allSettled(shutdowns);\n for (const outcome of outcomes) if (outcome.status === 'rejected') failures.push(outcome.reason);\n if (failures.length) throw new AggregateError(failures, 'Mount shutdown failed');\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/headlessHub.mjs
CHANGED
|
@@ -251,13 +251,16 @@ function createHeadlessHub(options) {
|
|
|
251
251
|
if (!canCommunicate(sessionId, peerSessionId)) return void 0;
|
|
252
252
|
const peer = sessions.get(peerSessionId);
|
|
253
253
|
if (peer === void 0) return void 0;
|
|
254
|
-
const
|
|
254
|
+
const source = sessions.get(sessionId);
|
|
255
|
+
const own = source.groups ?? [];
|
|
256
|
+
const sharedGroups = (peer.groups ?? []).filter((group) => own.includes(group));
|
|
257
|
+
if (source.parentSessionId !== peer.id && peer.parentSessionId !== source.id && sharedGroups.length === 0) return void 0;
|
|
255
258
|
const profile = peer.profile?.displayName ?? peer.profile?.name;
|
|
256
259
|
return {
|
|
257
260
|
sessionId: peerSessionId,
|
|
258
261
|
name: peer.name,
|
|
259
262
|
...profile === void 0 ? {} : { profile },
|
|
260
|
-
sharedGroups
|
|
263
|
+
sharedGroups
|
|
261
264
|
};
|
|
262
265
|
},
|
|
263
266
|
close() {
|