@adhdev/daemon-standalone 1.0.28-rc.18 → 1.0.28-rc.19
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/index.js +4480 -1703
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-BaD_sbu-.js → index-CWWODSEE.js} +1 -1
- package/public/index.html +1 -1
- package/vendor/mcp-server/index.js +82 -8
- package/vendor/mcp-server/index.js.map +1 -1
- package/vendor/session-host-daemon/index.d.mts +2 -0
- package/vendor/session-host-daemon/index.d.ts +2 -0
- package/vendor/session-host-daemon/index.js +38 -24
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +26 -10
- package/vendor/session-host-daemon/index.mjs.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/runtime.ts","../src/storage.ts","../src/session-diagnostics.ts","../src/session-lifecycle.ts","../src/session-protocol.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { randomUUID } from 'crypto';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport {\n SessionHostClient,\n formatRuntimeOwner,\n getDefaultSessionHostEndpoint,\n resolveAttachableRuntimeRecord,\n resolveRuntimeRecord,\n type SessionHostEvent,\n type SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport { SessionHostServer } from './server.js';\n\nexport { SessionHostServer } from './server.js';\nexport type { SessionHostServerOptions } from './server.js';\n\nconst SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';\n\nfunction getSessionHostPidFile(appName: string): string {\n const dir = path.join(os.homedir(), '.adhdev');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `${appName}-session-host.pid`);\n}\n\nfunction writeSessionHostPid(appName: string): void {\n fs.writeFileSync(getSessionHostPidFile(appName), String(process.pid), 'utf8');\n}\n\nfunction removeSessionHostPid(appName: string): void {\n try {\n fs.unlinkSync(getSessionHostPidFile(appName));\n } catch {\n // noop\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const [command, ...rest] = argv;\n const readOnly = rest.includes('--read-only');\n const takeover = rest.includes('--takeover');\n const showAll = rest.includes('--all');\n const positional = rest.filter((arg) => arg !== '--read-only' && arg !== '--takeover' && arg !== '--all');\n return {\n command: command || 'serve',\n positional,\n readOnly,\n takeover,\n showAll,\n };\n}\n\nasync function runServer(): Promise<void> {\n const server = new SessionHostServer({ appName: SESSION_HOST_APP_NAME });\n writeSessionHostPid(SESSION_HOST_APP_NAME);\n await server.start();\n\n process.on('SIGINT', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n process.on('SIGTERM', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n // Fallback: flush persistence on any exit (covers Windows where SIGTERM is unsupported)\n process.on('exit', () => {\n server.flushAllPersistence();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n });\n\n // Keep the host alive; IPC transport wiring comes next.\n await new Promise<void>(() => {});\n}\n\nasync function listRuntimes(showAll = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const response = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!response.success) {\n throw new Error(response.error || 'Failed to list runtimes');\n }\n const runtimes = (response.result || []).filter((runtime: SessionHostRecord) => showAll || runtime.lifecycle !== 'stopped');\n if (runtimes.length === 0) {\n console.log('No runtimes.');\n return;\n }\n console.log('runtimeKey\\tlifecycle\\towner\\tworkspace\\tid\\tdisplayName');\n for (const runtime of runtimes) {\n console.log([\n runtime.runtimeKey,\n runtime.lifecycle,\n formatRuntimeOwner(runtime),\n runtime.workspaceLabel,\n runtime.sessionId,\n runtime.displayName,\n ].join('\\t'));\n }\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nasync function attachRuntime(target: string, readOnly = false, takeover = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n const clientId = `local-terminal-${process.pid}-${randomUUID().slice(0, 8)}`;\n let lastSeq = 0;\n let restoredRawMode = false;\n let runtimeId = '';\n let localReadOnly = readOnly;\n\n const cleanup = async () => {\n process.stdout.off('resize', handleResize);\n process.stdin.off('data', handleInput);\n process.stdin.pause();\n if (process.stdin.isTTY && restoredRawMode) {\n process.stdin.setRawMode(false);\n }\n await client.request({\n type: 'release_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.request({\n type: 'detach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.close().catch(() => {});\n };\n\n const handleResize = () => {\n void client.request({\n type: 'resize_session',\n payload: {\n sessionId: runtimeId,\n cols: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n },\n }).catch(() => ({ success: false }));\n };\n\n const sendInputWithTakeover = async (data: string) => {\n let response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (!response.success && response.error?.startsWith('Write owned by ')) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: true,\n },\n });\n if (ownerResponse.success && ownerResponse.result) {\n response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (response.success) {\n process.stderr.write(`Took control of ${ownerResponse.result.runtimeKey}.\\n`);\n }\n }\n }\n return response;\n };\n\n const handleInput = (chunk: Buffer) => {\n if (!localReadOnly && chunk.length === 1 && chunk[0] === 0x1d) {\n void cleanup().finally(() => process.exit(0));\n return;\n }\n if (localReadOnly) return;\n void sendInputWithTakeover(chunk.toString('utf8')).catch(() => ({ success: false }));\n };\n\n try {\n if (readOnly && takeover) {\n throw new Error('Use either --read-only or --takeover, not both');\n }\n\n const listResponse = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n let runtimeRecord = resolveAttachableRuntimeRecord(listResponse.result, target);\n runtimeId = runtimeRecord.sessionId;\n\n if (runtimeRecord.lifecycle === 'interrupted' && !readOnly) {\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeId,\n },\n });\n if (resumeResponse.success && resumeResponse.result) {\n runtimeRecord = resumeResponse.result;\n } else {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} could not be resumed automatically: ${resumeResponse.error || 'unknown error'}\\n`,\n );\n }\n }\n\n let effectiveReadOnly = readOnly;\n if (!effectiveReadOnly && runtimeRecord.writeOwner && runtimeRecord.writeOwner.clientId !== clientId && !takeover) {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} is currently owned by ${runtimeRecord.writeOwner.clientId}; first input will take control here.\\n`,\n );\n }\n localReadOnly = effectiveReadOnly;\n\n const attachResponse = await client.request<SessionHostRecord>({\n type: 'attach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n clientType: 'local-terminal',\n readOnly: effectiveReadOnly,\n },\n });\n if (!attachResponse.success) {\n throw new Error(attachResponse.error || `Failed to attach runtime ${runtimeId}`);\n }\n const attachedRecord = attachResponse.result || null;\n\n if (!effectiveReadOnly && takeover) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: takeover,\n },\n });\n if (!ownerResponse.success) {\n throw new Error(ownerResponse.error || `Failed to acquire write owner for runtime ${runtimeId}`);\n }\n }\n\n const snapshotResponse = await client.request<{ seq: number; text: string; truncated: boolean; cols?: number; rows?: number }>({\n type: 'get_snapshot',\n payload: { sessionId: runtimeId },\n });\n if (!snapshotResponse.success) {\n throw new Error(snapshotResponse.error || `Failed to read runtime snapshot ${runtimeId}`);\n }\n lastSeq = snapshotResponse.result?.seq || 0;\n if (snapshotResponse.result?.text) {\n process.stdout.write(snapshotResponse.result.text);\n }\n if (attachedRecord?.lifecycle === 'stopped' || attachedRecord?.lifecycle === 'failed' || attachedRecord?.lifecycle === 'interrupted') {\n process.stderr.write(`Runtime ${attachedRecord.runtimeKey} is already ${attachedRecord.lifecycle}. Detached after snapshot.\\n`);\n await cleanup();\n return;\n }\n\n const stopSignals = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n const signalHandlers = stopSignals.map((signal) => {\n const handler = () => {\n void cleanup().finally(() => process.exit(0));\n };\n process.on(signal, handler);\n return { signal, handler };\n });\n\n const unsubscribe = client.onEvent((event: SessionHostEvent) => {\n if (!('sessionId' in event)) return;\n if (event.sessionId !== runtimeId) return;\n if (event.type === 'session_output') {\n if (event.seq <= lastSeq) return;\n lastSeq = event.seq;\n process.stdout.write(event.data);\n return;\n }\n if (event.type === 'session_exit') {\n void cleanup().finally(() => {\n for (const { signal, handler } of signalHandlers) {\n process.off(signal, handler);\n }\n unsubscribe();\n process.exit(event.exitCode ?? 0);\n });\n }\n });\n\n process.stdout.on('resize', handleResize);\n process.stdin.on('data', handleInput);\n process.stdin.resume();\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n restoredRawMode = true;\n }\n handleResize();\n if (!effectiveReadOnly) {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId}. Press Ctrl+] to detach.\\n`);\n } else {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId} (read-only).\\n`);\n }\n await new Promise<void>(() => {});\n } catch (error) {\n await cleanup().catch(() => {});\n throw error;\n }\n}\n\nasync function main(): Promise<void> {\n const { command, positional, readOnly, takeover, showAll } = parseArgs(process.argv.slice(2));\n if (command === 'serve') {\n await runServer();\n return;\n }\n if (command === 'list') {\n await listRuntimes(showAll);\n return;\n }\n if (command === 'attach') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond attach <runtimeId|runtimeKey>');\n }\n await attachRuntime(target, readOnly, takeover);\n return;\n }\n if (command === 'resume') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>');\n }\n const client = new SessionHostClient({ endpoint: getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME) });\n try {\n const listResponse = await client.request<SessionHostRecord[]>({ type: 'list_sessions', payload: {} });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n const runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeRecord.sessionId,\n },\n });\n if (!resumeResponse.success || !resumeResponse.result) {\n throw new Error(resumeResponse.error || `Failed to resume runtime ${runtimeRecord.runtimeKey}`);\n }\n console.log(`Resumed ${resumeResponse.result.runtimeKey} (${resumeResponse.result.sessionId})`);\n } finally {\n await client.close().catch(() => {});\n }\n return;\n }\n throw new Error(`Unknown command: ${command}`);\n}\n\nif (require.main === module) {\n // Prevent native crashes (e.g. node-pty on Windows) from silently killing the server process\n process.on('uncaughtException', (err) => {\n console.error(`[session-host] Uncaught exception: ${err?.message}\\n${err?.stack || ''}`);\n // Do not exit — keep the server alive for existing sessions\n });\n process.on('unhandledRejection', (reason: any) => {\n console.error(`[session-host] Unhandled rejection: ${reason?.message || reason}`);\n });\n\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n });\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport {\n SessionHostRegistry,\n classifyTermination,\n createLineParser,\n createResponseEnvelope,\n getDefaultSessionHostEndpoint,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionAttachedClient,\n SessionHostDiagnostics,\n SessionHostEndpoint,\n SessionHostEvent,\n SessionHostLogEntry,\n SessionHostPruneDuplicatesResult,\n SessionHostRecord,\n SessionHostRequestEnvelope,\n SessionHostRequestTrace,\n SessionHostRequest,\n SessionHostRuntimeTransition,\n SessionHostResponse,\n SessionTermination,\n} from '@adhdev/session-host-core';\nimport { PtySessionRuntime } from './runtime.js';\nimport { SessionHostStorage } from './storage.js';\nimport {\n buildHostDiagnostics,\n pushRecent,\n} from './session-diagnostics.js';\nimport {\n buildPayloadFromRecord,\n buildRecoveredRecord,\n planDuplicatePrune,\n} from './session-lifecycle.js';\nimport {\n getRequestClientId,\n getRequestSessionId,\n mergeRuntimeSnapshot,\n} from './session-protocol.js';\n\nexport interface SessionHostServerOptions {\n endpoint?: SessionHostEndpoint;\n appName?: string;\n}\n\nexport class SessionHostServer extends EventEmitter {\n readonly endpoint: SessionHostEndpoint;\n readonly registry = new SessionHostRegistry();\n private runtimes = new Map<string, PtySessionRuntime>();\n private readonly storage: SessionHostStorage;\n private ipcServer: net.Server | null = null;\n private sockets = new Set<net.Socket>();\n // Tracks which sessionIds each socket has subscribed to (via create/attach).\n // Used to avoid broadcasting session-specific events to uninterested sockets.\n private socketSessions = new Map<net.Socket, Set<string>>();\n private persistTimers = new Map<string, NodeJS.Timeout>();\n private readonly startedAt = Date.now();\n private recentLogs: SessionHostLogEntry[] = [];\n private recentRequests: SessionHostRequestTrace[] = [];\n private recentTransitions: SessionHostRuntimeTransition[] = [];\n private exitWaiters = new Map<string, Array<(exitCode: number | null) => void>>();\n private lastNoOutputInputWarnAt = new Map<string, number>();\n // Records the most recent explicit stop/delete/restart/prune request per\n // session so the termination diagnostic can attribute the exit to it.\n private stopRequests = new Map<string, SessionTermination['requestedStop']>();\n\n constructor(options: SessionHostServerOptions = {}) {\n super();\n this.endpoint = options.endpoint || getDefaultSessionHostEndpoint(options.appName || 'adhdev');\n this.storage = new SessionHostStorage({ appName: options.appName || 'adhdev' });\n }\n\n async start(): Promise<void> {\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n\n this.ipcServer = net.createServer((socket) => {\n this.sockets.add(socket);\n const removeSocket = () => {\n this.sockets.delete(socket);\n this.socketSessions.delete(socket);\n };\n socket.on('close', removeSocket);\n socket.on('end', removeSocket);\n socket.on('error', () => {\n removeSocket();\n try {\n socket.destroy();\n } catch {\n // noop\n }\n });\n socket.on('data', createLineParser((envelope) => {\n if (envelope.kind !== 'request') return;\n void this.handleIncomingRequest(socket, envelope);\n }));\n });\n\n await new Promise<void>((resolve, reject) => {\n this.ipcServer?.once('listening', () => resolve());\n this.ipcServer?.once('error', reject);\n this.ipcServer?.listen(this.endpoint.path);\n });\n\n this.recordHostLog('info', `session host endpoint ready: ${this.endpoint.path}`);\n // Do not block readiness on restoring/resuming persisted runtimes.\n // Startup callers only need the IPC endpoint to accept connections.\n setTimeout(() => {\n try {\n this.restorePersistedRuntimes();\n } catch (error: any) {\n this.recordHostLog('error', `session host restore failed: ${error?.message || String(error)}`);\n }\n }, 0);\n }\n\n async stop(): Promise<void> {\n this.flushAllPersistence();\n for (const runtime of this.runtimes.values()) {\n try {\n runtime.stop();\n } catch {\n // noop\n }\n }\n this.runtimes.clear();\n for (const timer of this.persistTimers.values()) {\n clearTimeout(timer);\n }\n this.persistTimers.clear();\n for (const socket of this.sockets) {\n socket.destroy();\n }\n this.sockets.clear();\n this.socketSessions.clear();\n if (this.ipcServer) {\n const server = this.ipcServer;\n this.ipcServer = null;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n this.removeAllListeners();\n }\n\n async handleRequest(request: SessionHostRequest): Promise<SessionHostResponse> {\n try {\n switch (request.type) {\n case 'create_session': {\n const record = this.registry.createSession(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_created', sessionId: record.sessionId, record });\n this.recordRuntimeTransition(record.sessionId, 'create_session', 'starting', `provider=${record.providerType}`, true);\n try {\n const startedRecord = this.startRuntime(record, request.payload, 'session_started');\n return { success: true, result: startedRecord };\n } catch (error: any) {\n this.registry.markStopped(record.sessionId, 'failed');\n this.persistNow(record.sessionId);\n this.recordRuntimeTransition(record.sessionId, 'create_session_failed', 'failed', undefined, false, error?.message || String(error));\n return { success: false, error: error?.message || String(error) };\n }\n }\n case 'list_sessions':\n return { success: true, result: this.registry.listSessions() };\n case 'attach_session': {\n const record = this.registry.attachClient(request.payload);\n this.schedulePersist(record.sessionId);\n const client = record.attachedClients.find(item => item.clientId === request.payload.clientId);\n if (client) {\n this.emitEvent({ type: 'client_attached', sessionId: record.sessionId, client });\n }\n this.recordRuntimeTransition(record.sessionId, 'attach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'detach_session': {\n const record = this.registry.detachClient(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n this.recordRuntimeTransition(record.sessionId, 'detach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'acquire_write': {\n const record = this.registry.acquireWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n this.recordRuntimeTransition(record.sessionId, 'acquire_write', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'release_write': {\n const record = this.registry.releaseWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n this.recordRuntimeTransition(record.sessionId, 'release_write', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'get_snapshot':\n return { success: true, result: this.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };\n case 'get_terminal_snapshot':\n return { success: true, result: this.requireRuntime(request.payload.sessionId).getTerminalSnapshot() };\n case 'get_host_diagnostics':\n return { success: true, result: this.getHostDiagnostics(request.payload) };\n case 'clear_session_buffer': {\n const record = this.registry.clearBuffer(request.payload.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_cleared', sessionId: record.sessionId });\n this.recordRuntimeTransition(record.sessionId, 'clear_buffer', record.lifecycle, undefined, true);\n return { success: true, result: record };\n }\n case 'update_session_meta': {\n const record = this.registry.updateSessionMeta(\n request.payload.sessionId,\n request.payload.meta || {},\n request.payload.replace === true,\n );\n this.persistNow(record.sessionId);\n this.recordRuntimeTransition(record.sessionId, 'update_meta', record.lifecycle, undefined, true);\n return { success: true, result: record };\n }\n case 'send_input': {\n const client = this.getAttachedClient(request.payload.sessionId, request.payload.clientId);\n if (client?.readOnly) {\n return { success: false, error: `Client ${request.payload.clientId} is read-only` };\n }\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner && session.writeOwner.clientId !== request.payload.clientId) {\n return { success: false, error: `Write owned by ${session.writeOwner.clientId}` };\n }\n const runtime = this.requireRuntime(request.payload.sessionId);\n const beforeSnapshotSeq = this.registry.getSnapshot(request.payload.sessionId)?.seq ?? 0;\n runtime.write(request.payload.data);\n this.scheduleNoOutputInputDiagnostic({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n input: request.payload.data,\n beforeSnapshotSeq,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resize_session': {\n this.requireRuntime(request.payload.sessionId).resize(request.payload.cols, request.payload.rows);\n const record = this.registry.getSession(request.payload.sessionId);\n if (record) {\n this.registry.restoreSession(\n {\n ...record,\n meta: {\n ...(record.meta || {}),\n sessionHostCols: request.payload.cols,\n sessionHostRows: request.payload.rows,\n },\n },\n this.registry.getSnapshot(request.payload.sessionId),\n );\n }\n this.schedulePersist(request.payload.sessionId);\n this.emitEvent({\n type: 'session_resized',\n sessionId: request.payload.sessionId,\n cols: request.payload.cols,\n rows: request.payload.rows,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'stop_session': {\n this.stopRequests.set(request.payload.sessionId, 'stop');\n this.registry.setLifecycle(request.payload.sessionId, 'stopping');\n this.persistNow(request.payload.sessionId);\n this.requireRuntime(request.payload.sessionId).stop();\n this.emitEvent({ type: 'session_stopped', sessionId: request.payload.sessionId });\n this.recordRuntimeTransition(request.payload.sessionId, 'stop_session', 'stopping', undefined, true);\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'delete_session': {\n const record = this.registry.getSession(request.payload.sessionId);\n if (!record) return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n if (this.runtimes.has(record.sessionId)) {\n if (!request.payload.force) {\n return { success: false, error: `Session ${record.sessionId} is still running; pass force to stop and delete it` };\n }\n this.stopRequests.set(record.sessionId, 'delete');\n this.registry.setLifecycle(record.sessionId, 'stopping');\n this.persistNow(record.sessionId);\n this.requireRuntime(record.sessionId).stop();\n await this.waitForRuntimeExit(record.sessionId).catch((error: any) => {\n this.recordRuntimeTransition(record.sessionId, 'delete_session_timeout', 'stopping', undefined, false, error?.message || String(error));\n });\n }\n this.registry.deleteSession(record.sessionId);\n this.storage.remove(record.sessionId);\n this.storage.removeTombstone(record.sessionId);\n this.stopRequests.delete(record.sessionId);\n this.emitEvent({ type: 'session_deleted', sessionId: record.sessionId });\n this.recordRuntimeTransition(record.sessionId, 'delete_session', record.lifecycle, undefined, true);\n return { success: true, result: { sessionId: record.sessionId, deleted: true } };\n }\n case 'resume_session': {\n const existing = this.registry.getSession(request.payload.sessionId);\n if (!existing) {\n return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n }\n if (this.runtimes.has(request.payload.sessionId)) {\n return { success: true, result: existing };\n }\n const resumed = this.startRuntime(existing, buildPayloadFromRecord(existing), 'session_resumed');\n this.recordRuntimeTransition(request.payload.sessionId, 'resume_session', resumed.lifecycle, undefined, true);\n return { success: true, result: resumed };\n }\n case 'restart_session': {\n const restarted = await this.restartRuntime(request.payload.sessionId);\n return { success: true, result: restarted };\n }\n case 'prune_duplicate_sessions': {\n const result = await this.pruneDuplicateSessions(request.payload);\n return { success: true, result };\n }\n case 'send_signal': {\n const runtime = this.requireRuntime(request.payload.sessionId);\n runtime.sendSignal(request.payload.signal);\n const record = this.registry.getSession(request.payload.sessionId);\n this.recordRuntimeTransition(request.payload.sessionId, 'send_signal', record?.lifecycle, request.payload.signal, true);\n return { success: true, result: record };\n }\n case 'force_detach_client': {\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner?.clientId === request.payload.clientId) {\n const released = this.registry.releaseWrite({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n });\n this.emitEvent({ type: 'write_owner_changed', sessionId: released.sessionId, owner: released.writeOwner });\n }\n const record = this.registry.detachClient({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n });\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n this.recordRuntimeTransition(record.sessionId, 'force_detach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n default:\n return { success: false, error: `Unsupported session host request: ${(request as { type?: string })?.type || 'unknown'}` };\n }\n } catch (error: any) {\n return { success: false, error: error?.message || String(error) };\n }\n }\n\n private requireRuntime(sessionId: string): PtySessionRuntime {\n const runtime = this.runtimes.get(sessionId);\n if (!runtime) throw new Error(`Runtime not found for session: ${sessionId}`);\n return runtime;\n }\n\n private getAttachedClient(sessionId: string, clientId: string): SessionAttachedClient | null {\n const session = this.registry.getSession(sessionId);\n return session?.attachedClients.find((client) => client.clientId === clientId) || null;\n }\n\n private emitEvent(event: SessionHostEvent): void {\n // Diagnostic-only events are stored locally (recentLogs/Requests/Transitions)\n // and accessible via get_host_diagnostics. Broadcasting them to every socket\n // creates O(N²) traffic when many CLI sessions are active.\n const diagnosticOnly = event.type === 'request_trace'\n || event.type === 'runtime_transition'\n || event.type === 'host_log';\n if (!diagnosticOnly) {\n const targetSessionId = 'sessionId' in event ? (event as { sessionId: string }).sessionId : null;\n for (const socket of [...this.sockets]) {\n // If the event is session-specific, only send to sockets subscribed to that session.\n if (targetSessionId && event.type === 'session_output') {\n const sessions = this.socketSessions.get(socket);\n if (!sessions?.has(targetSessionId)) continue;\n } else if (targetSessionId && this.socketSessions.size > 0) {\n const sessions = this.socketSessions.get(socket);\n if (sessions && !sessions.has(targetSessionId)) continue;\n }\n this.writeEnvelopeSafely(socket, {\n kind: 'event',\n event,\n });\n }\n }\n this.emit('event', event);\n }\n\n private subscribeSocketToSession(socket: net.Socket, sessionId: string): void {\n let sessions = this.socketSessions.get(socket);\n if (!sessions) {\n sessions = new Set();\n this.socketSessions.set(socket, sessions);\n }\n sessions.add(sessionId);\n }\n\n private async handleIncomingRequest(socket: net.Socket, envelope: SessionHostRequestEnvelope): Promise<void> {\n const sessionId = getRequestSessionId(envelope.request);\n if (sessionId && (envelope.request.type === 'create_session' || envelope.request.type === 'attach_session')) {\n this.subscribeSocketToSession(socket, sessionId);\n }\n const startedAt = Date.now();\n const response = await this.handleRequest(envelope.request);\n if (sessionId && envelope.request.type === 'create_session' && response.success) {\n // sessionId may have been auto-generated — subscribe to whatever was actually created\n const createdId = (response.result as { sessionId?: string } | undefined)?.sessionId;\n if (createdId && createdId !== sessionId) this.subscribeSocketToSession(socket, createdId);\n }\n this.recordRequestTrace({\n timestamp: startedAt,\n requestId: envelope.requestId,\n type: envelope.request.type,\n sessionId: getRequestSessionId(envelope.request),\n clientId: getRequestClientId(envelope.request),\n success: response.success,\n durationMs: Math.max(0, Date.now() - startedAt),\n error: response.success ? undefined : response.error,\n });\n this.writeEnvelopeSafely(socket, createResponseEnvelope(envelope.requestId, response));\n }\n\n private writeEnvelopeSafely(socket: net.Socket, envelope: SessionHostRequestEnvelope | ReturnType<typeof createResponseEnvelope> | { kind: 'event'; event: SessionHostEvent }): void {\n if (socket.destroyed || !socket.writable || socket.writableEnded) {\n this.sockets.delete(socket);\n return;\n }\n const payload = `${JSON.stringify(envelope)}\\n`;\n try {\n socket.write(payload, (error?: Error | null) => {\n if (!error) return;\n this.sockets.delete(socket);\n try {\n socket.destroy();\n } catch {\n // noop\n }\n });\n } catch {\n this.sockets.delete(socket);\n try {\n socket.destroy();\n } catch {\n // noop\n }\n }\n }\n\n private schedulePersist(sessionId: string): void {\n const existing = this.persistTimers.get(sessionId);\n if (existing) clearTimeout(existing);\n this.persistTimers.set(sessionId, setTimeout(() => {\n this.persistTimers.delete(sessionId);\n this.persistNow(sessionId);\n }, 200));\n }\n\n private persistNow(sessionId: string): void {\n const record = this.registry.getSession(sessionId);\n if (!record) return;\n const snapshot = this.getSnapshot(sessionId);\n try {\n this.storage.save(record, snapshot);\n } catch (error: any) {\n const code = typeof error?.code === 'string' ? error.code : 'persist_failed';\n console.error(`[session-host] Persist failed for ${sessionId}: ${code}: ${error?.message || error}`);\n }\n }\n\n private getHostDiagnostics(payload?: { includeSessions?: boolean; limit?: number }): SessionHostDiagnostics {\n return buildHostDiagnostics({\n payload,\n hostStartedAt: this.startedAt,\n endpointPath: this.endpoint.path,\n runtimeCount: this.runtimes.size,\n sessions: this.registry.listSessions(),\n recentLogs: this.recentLogs,\n recentRequests: this.recentRequests,\n recentTransitions: this.recentTransitions,\n });\n }\n\n private recordHostLog(\n level: SessionHostLogEntry['level'],\n message: string,\n sessionId?: string,\n data?: Record<string, unknown>,\n ): void {\n const entry: SessionHostLogEntry = {\n timestamp: Date.now(),\n level,\n message,\n sessionId,\n data,\n };\n pushRecent(this.recentLogs, entry);\n this.emitEvent({ type: 'host_log', entry });\n this.emit('log', `[${level}] ${message}`);\n }\n\n private recordRequestTrace(trace: SessionHostRequestTrace): void {\n pushRecent(this.recentRequests, trace);\n this.emitEvent({ type: 'request_trace', trace });\n if (!trace.success) {\n this.recordHostLog(\n 'warn',\n `request ${trace.type} failed after ${trace.durationMs}ms${trace.error ? `: ${trace.error}` : ''}`,\n trace.sessionId,\n { requestId: trace.requestId, clientId: trace.clientId },\n );\n }\n }\n\n private scheduleNoOutputInputDiagnostic(params: {\n sessionId: string;\n clientId: string;\n input: string;\n beforeSnapshotSeq: number;\n }): void {\n if (!params.input || /^\\x1b/.test(params.input)) {\n return;\n }\n\n const hasPotentialEcho = /[^\\x00-\\x1F\\x7F]/.test(params.input);\n if (!hasPotentialEcho && params.input !== '\\r' && params.input !== '\\n') {\n return;\n }\n\n setTimeout(() => {\n let afterSnapshotSeq = params.beforeSnapshotSeq;\n try {\n afterSnapshotSeq = this.registry.getSnapshot(params.sessionId)?.seq ?? params.beforeSnapshotSeq;\n } catch {\n return;\n }\n if (afterSnapshotSeq > params.beforeSnapshotSeq) {\n return;\n }\n\n const now = Date.now();\n const lastWarnAt = this.lastNoOutputInputWarnAt.get(params.sessionId) || 0;\n if (now - lastWarnAt < 10_000) {\n return;\n }\n this.lastNoOutputInputWarnAt.set(params.sessionId, now);\n const record = this.registry.getSession(params.sessionId);\n this.recordHostLog(\n 'warn',\n 'send_input produced no terminal output after PTY write; runtime may be ignoring stdin or stuck in a hidden input reader',\n params.sessionId,\n {\n clientId: params.clientId,\n inputLength: params.input.length,\n beforeSnapshotSeq: params.beforeSnapshotSeq,\n afterSnapshotSeq,\n lifecycle: record?.lifecycle,\n osPid: record?.osPid,\n providerType: record?.providerType,\n },\n );\n this.recordRuntimeTransition(\n params.sessionId,\n 'send_input_no_output_after_write',\n record?.lifecycle,\n `clientId=${params.clientId} inputLength=${params.input.length} seq=${params.beforeSnapshotSeq}`,\n false,\n 'no terminal output after PTY write',\n );\n }, 250);\n }\n\n private recordRuntimeTransition(\n sessionId: string,\n action: string,\n lifecycle?: SessionHostRuntimeTransition['lifecycle'],\n detail?: string,\n success = true,\n error?: string,\n ): void {\n const transition: SessionHostRuntimeTransition = {\n timestamp: Date.now(),\n sessionId,\n action,\n lifecycle,\n detail,\n success,\n error,\n };\n pushRecent(this.recentTransitions, transition);\n this.emitEvent({ type: 'runtime_transition', transition });\n }\n\n private waitForRuntimeExit(sessionId: string, timeoutMs = 5_000): Promise<number | null> {\n if (!this.runtimes.has(sessionId)) {\n return Promise.resolve(this.registry.getSession(sessionId)?.lifecycle === 'failed' ? 1 : 0);\n }\n return new Promise<number | null>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const waiters = this.exitWaiters.get(sessionId) || [];\n this.exitWaiters.set(sessionId, waiters.filter((waiter) => waiter !== onExit));\n reject(new Error(`Timed out waiting for runtime ${sessionId} to exit`));\n }, timeoutMs);\n const onExit = (exitCode: number | null) => {\n clearTimeout(timeout);\n resolve(exitCode);\n };\n const waiters = this.exitWaiters.get(sessionId) || [];\n waiters.push(onExit);\n this.exitWaiters.set(sessionId, waiters);\n });\n }\n\n private resolveExitWaiters(sessionId: string, exitCode: number | null): void {\n const waiters = this.exitWaiters.get(sessionId);\n if (!waiters?.length) return;\n this.exitWaiters.delete(sessionId);\n for (const waiter of waiters) {\n try {\n waiter(exitCode);\n } catch {\n // noop\n }\n }\n }\n\n private getSnapshot(sessionId: string, sinceSeq?: number) {\n const snapshot = this.registry.getSnapshot(sessionId, sinceSeq);\n const record = this.registry.getSession(sessionId);\n const runtimeText = typeof sinceSeq === 'number'\n ? ''\n : (this.runtimes.get(sessionId)?.getSnapshotText?.() || '');\n return mergeRuntimeSnapshot(snapshot, record, { sinceSeq, runtimeText });\n }\n\n flushAllPersistence(): void {\n for (const sessionId of this.runtimes.keys()) {\n this.persistNow(sessionId);\n }\n for (const record of this.registry.listSessions()) {\n this.persistNow(record.sessionId);\n }\n }\n\n private async restartRuntime(sessionId: string): Promise<SessionHostRecord> {\n const existing = this.registry.getSession(sessionId);\n if (!existing) {\n throw new Error(`Unknown session: ${sessionId}`);\n }\n\n if (this.runtimes.has(sessionId)) {\n this.stopRequests.set(sessionId, 'restart');\n this.registry.setLifecycle(sessionId, 'stopping');\n this.persistNow(sessionId);\n this.recordRuntimeTransition(sessionId, 'restart_requested', 'stopping', undefined, true);\n this.requireRuntime(sessionId).stop();\n await this.waitForRuntimeExit(sessionId);\n }\n\n const latest = this.registry.getSession(sessionId) || existing;\n const restarted = this.startRuntime(latest, buildPayloadFromRecord(latest), 'session_resumed');\n this.recordRuntimeTransition(sessionId, 'restart_completed', restarted.lifecycle, undefined, true);\n return restarted;\n }\n\n private async pruneDuplicateSessions(payload?: {\n providerType?: string;\n workspace?: string;\n dryRun?: boolean;\n }): Promise<SessionHostPruneDuplicatesResult> {\n const providerFilter = typeof payload?.providerType === 'string' ? payload.providerType.trim() : '';\n const workspaceFilter = typeof payload?.workspace === 'string' ? payload.workspace.trim() : '';\n const dryRun = payload?.dryRun === true;\n\n const { duplicateGroups, keptSessionIds, duplicateRecords } = planDuplicatePrune(\n this.registry.listSessions(),\n { providerFilter, workspaceFilter },\n );\n\n const prunedSessionIds: string[] = [];\n if (!dryRun) {\n for (const duplicate of duplicateRecords) {\n await this.pruneDuplicateRuntime(duplicate);\n prunedSessionIds.push(duplicate.sessionId);\n }\n }\n\n this.recordHostLog(\n dryRun ? 'info' : 'warn',\n `${dryRun ? 'session host dry-run found' : 'session host pruned'} ${duplicateGroups.length} duplicate group(s)`,\n undefined,\n {\n providerType: providerFilter || undefined,\n workspace: workspaceFilter || undefined,\n dryRun,\n prunedSessionIds,\n keptSessionIds,\n },\n );\n\n return {\n duplicateGroupCount: duplicateGroups.length,\n keptSessionIds,\n prunedSessionIds,\n groups: duplicateGroups,\n };\n }\n\n private restorePersistedRuntimes(): void {\n const states = this.storage.loadAll();\n let skippedAutoResumeSessions = 0;\n for (const persisted of states) {\n const { recoveredRecord, wasLiveRuntime, hadRecoveryInterest } = buildRecoveredRecord(persisted);\n this.registry.restoreSession(recoveredRecord, persisted.snapshot);\n this.storage.save(recoveredRecord, persisted.snapshot);\n if (wasLiveRuntime && hadRecoveryInterest) {\n skippedAutoResumeSessions += 1;\n }\n }\n\n if (skippedAutoResumeSessions > 0) {\n this.recordHostLog('warn', `session host restored ${skippedAutoResumeSessions} live runtime snapshot(s) without auto-resume`);\n }\n }\n\n private async pruneDuplicateRuntime(record: SessionHostRecord): Promise<void> {\n const providerSessionId = typeof record.meta?.providerSessionId === 'string'\n ? String(record.meta.providerSessionId)\n : undefined;\n this.recordRuntimeTransition(\n record.sessionId,\n 'prune_duplicate_session',\n record.lifecycle,\n providerSessionId ? `providerSessionId=${providerSessionId}` : undefined,\n true,\n );\n\n if (this.runtimes.has(record.sessionId)) {\n this.stopRequests.set(record.sessionId, 'prune');\n this.registry.setLifecycle(record.sessionId, 'stopping');\n this.persistNow(record.sessionId);\n this.requireRuntime(record.sessionId).stop();\n await this.waitForRuntimeExit(record.sessionId).catch((error: any) => {\n this.recordRuntimeTransition(record.sessionId, 'prune_duplicate_timeout', 'stopping', undefined, false, error?.message || String(error));\n });\n }\n\n this.registry.deleteSession(record.sessionId);\n this.storage.remove(record.sessionId);\n this.storage.removeTombstone(record.sessionId);\n this.stopRequests.delete(record.sessionId);\n }\n\n private startRuntime(\n record: SessionHostRecord,\n payload: CreateSessionPayload,\n startEventType: 'session_started' | 'session_resumed',\n ): SessionHostRecord {\n const runtime = new PtySessionRuntime({\n sessionId: record.sessionId,\n payload,\n onData: (data) => {\n const { seq } = this.registry.appendOutput(record.sessionId, data);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_output', sessionId: record.sessionId, seq, data });\n },\n onExit: (exitCode, signal) => this.handleRuntimeExit(record, exitCode, signal),\n });\n\n this.registry.setLifecycle(record.sessionId, 'starting');\n const pid = runtime.start();\n this.runtimes.set(record.sessionId, runtime);\n const startedRecord = this.registry.markStarted(record.sessionId, pid);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: startEventType, sessionId: record.sessionId, pid });\n this.recordRuntimeTransition(record.sessionId, startEventType, startedRecord.lifecycle, `pid=${pid}`, true);\n return startedRecord;\n }\n\n /**\n * Handle a PTY termination: classify the (exitCode, signal) pair, stamp the\n * record + tombstone, emit exactly one structured diagnostic, and schedule\n * cleanup of the live persistence file (the tombstone is retained).\n */\n private handleRuntimeExit(record: SessionHostRecord, exitCode: number | null, signal: number | null): SessionTermination {\n // Capture pre-termination context BEFORE mutating the record.\n const priorRecord = this.registry.getSession(record.sessionId);\n const termination = classifyTermination({\n exitCode,\n signal,\n osPid: priorRecord?.osPid,\n previousLifecycle: priorRecord?.lifecycle,\n lastOutputAt: priorRecord?.lastActivityAt,\n requestedStop: this.stopRequests.get(record.sessionId),\n terminatedAt: Date.now(),\n });\n this.stopRequests.delete(record.sessionId);\n\n this.registry.markStopped(record.sessionId, termination.lifecycle, termination);\n this.runtimes.delete(record.sessionId);\n this.resolveExitWaiters(record.sessionId, exitCode);\n this.persistNow(record.sessionId);\n // Persist a tombstone that survives live-record cleanup so the termination\n // stays inspectable after the 5s removal below.\n this.storage.saveTombstone(record.sessionId, termination);\n this.emitEvent({ type: 'session_exit', sessionId: record.sessionId, exitCode, signal, termination });\n const summary = `reason=${termination.reason} exitCode=${termination.exitCode === null ? 'unknown' : termination.exitCode} signal=${termination.signal ?? 'none'}`;\n // Exactly one structured, secret-free termination diagnostic.\n this.recordHostLog(\n termination.lifecycle === 'stopped' ? 'info' : 'warn',\n `session terminated: ${summary}`,\n record.sessionId,\n {\n runtimeKey: record.runtimeKey,\n providerType: record.providerType,\n osPid: termination.osPid,\n exitCode: termination.exitCode,\n signal: termination.signal,\n reason: termination.reason,\n previousLifecycle: termination.previousLifecycle,\n lifecycle: termination.lifecycle,\n lastOutputAt: termination.lastOutputAt,\n requestedStop: termination.requestedStop,\n },\n );\n this.recordRuntimeTransition(\n record.sessionId,\n 'session_exit',\n termination.lifecycle,\n summary,\n termination.lifecycle === 'stopped',\n termination.lifecycle === 'stopped' ? undefined : summary,\n );\n // Clean up the live persistence file after a brief delay (allow post-mortem\n // reads). The tombstone written above is retained.\n setTimeout(() => this.storage.remove(record.sessionId), 5_000).unref?.();\n return termination;\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as pty from 'node-pty';\nimport type { IPty } from 'node-pty';\nimport type { CreateSessionPayload, SessionTerminalSnapshot } from '@adhdev/session-host-core';\nimport {\n sanitizeSpawnEnv,\n ensureNodePtySpawnHelperPermissions,\n resolveSessionHostCols,\n resolveSessionHostRows,\n} from '@adhdev/session-host-core';\n\ntype TerminalMirrorHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n formatPlainText(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyTerminalHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n formatPlainText(options?: { trim?: boolean }): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyBinding = {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle;\n};\n\ntype XtermBufferLine = {\n translateToString(trimRight?: boolean): string;\n};\n\ntype XtermBuffer = {\n length: number;\n viewportY: number;\n cursorX?: number;\n cursorY?: number;\n getLine(index: number): XtermBufferLine | undefined;\n};\n\ntype XtermTerminal = {\n buffer: { active: XtermBuffer };\n loadAddon(addon: { activate(terminal: XtermTerminal): void }): void;\n write(data: string, callback?: () => void): void;\n resize(cols: number, rows: number): void;\n dispose(): void;\n};\n\ntype XtermCtor = new (options: { cols: number; rows: number; scrollback: number }) => XtermTerminal;\n\ntype XtermSerializeAddon = {\n serialize(options?: { range?: { start: number; end: number }; scrollback?: number; excludeModes?: boolean }): string;\n dispose(): void;\n};\n\nlet terminalMirrorFactory:\n | ((options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle)\n | null\n | undefined;\nlet terminalMirrorWarning: string | null = null;\nlet terminalMirrorBackendLogged = false;\n\nensureNodePtySpawnHelperPermissions((msg: string) => console.log(`[session-host] ${msg}`));\n\nfunction logTerminalMirrorBackend(message: string, level: 'info' | 'warn' = 'info'): void {\n if (terminalMirrorBackendLogged) return;\n terminalMirrorBackendLogged = true;\n const prefix = '[session-host]';\n if (level === 'warn') console.warn(`${prefix} ${message}`);\n else console.log(`${prefix} ${message}`);\n}\n\nexport interface PtyRuntimeOptions {\n sessionId: string;\n payload: CreateSessionPayload;\n onData: (data: string) => void;\n onExit: (exitCode: number | null, signal: number | null) => void;\n}\n\n// Use shared spawn env sanitizer — alias for backward compat within this file\nconst buildRuntimeEnv = sanitizeSpawnEnv;\n\nfunction computeTerminalQueryTail(buffer: string): string {\n const prefixes = ['\\x1b[6n', '\\x1b[?6n'];\n const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;\n const start = Math.max(0, buffer.length - maxLength);\n for (let i = start; i < buffer.length; i++) {\n const suffix = buffer.slice(i);\n if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {\n return suffix;\n }\n }\n return '';\n}\n\nfunction formatXtermViewportPlain(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(buffer.length || 0, start + Math.max(1, rows | 0)));\n const lines: string[] = [];\n\n for (let i = start; i < end; i++) {\n const line = buffer.getLine(i);\n const raw = line ? line.translateToString(false) : '';\n lines.push(raw.replace(/\\s+$/, ''));\n }\n\n let first = 0;\n let last = lines.length;\n while (first < last && !lines[first]?.trim()) first++;\n while (last > first && !lines[last - 1]?.trim()) last--;\n // Use CRLF row boundaries for unambiguous terminal replay regardless of the\n // browser xterm convertEol setting. CRLF is always explicit; bare LF depends\n // on convertEol being true to reset the cursor column, which is not guaranteed\n // for all xterm consumer configurations.\n return lines.slice(first, last).join('\\r\\n');\n}\n\nfunction createXtermSerializeAddon(terminal: XtermTerminal): XtermSerializeAddon | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/addon-serialize');\n const SerializeAddon = mod.SerializeAddon || mod.default?.SerializeAddon || mod.default;\n if (!SerializeAddon) return null;\n const addon = new SerializeAddon() as XtermSerializeAddon & { activate(terminal: XtermTerminal): void };\n terminal.loadAddon(addon);\n return addon;\n } catch {\n return null;\n }\n}\n\nfunction formatCursorRestore(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const row = Math.max(0, Math.min(Math.max(0, rows | 0) - 1, buffer.cursorY || 0));\n const col = Math.max(0, buffer.cursorX || 0);\n return `\\x1b[${row + 1};${col + 1}H`;\n}\n\nfunction serializeXtermViewport(terminal: XtermTerminal, serializer: XtermSerializeAddon, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(Math.max(0, buffer.length || 0) - 1, start + Math.max(1, rows | 0) - 1));\n if (end < start) return '';\n const viewport = serializer.serialize({\n range: { start, end },\n excludeModes: true,\n });\n // Range serialization reproduces the visible cells, but leaves the replay cursor\n // at the end of the serialized viewport. CLIs like Claude frequently update the\n // current status line with relative cursor movement; if the dashboard seeds a\n // snapshot and then receives an incremental update, that update must continue\n // from the live cursor row, not from the next line after the viewport replay.\n return `${viewport}${formatCursorRestore(terminal, rows)}`;\n}\n\nfunction createXtermMirror(options: { cols: number; rows: number; scrollback: number }): TerminalMirrorHandle {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/xterm');\n const Terminal = (mod.Terminal || mod.default?.Terminal || mod.default) as XtermCtor | undefined;\n if (!Terminal) {\n throw new Error('@xterm/xterm Terminal export not found');\n }\n\n let currentRows = Math.max(1, options.rows | 0);\n const terminal = new Terminal({\n cols: Math.max(1, options.cols | 0),\n rows: currentRows,\n scrollback: Math.max(0, options.scrollback | 0),\n });\n const serializer = createXtermSerializeAddon(terminal);\n\n return {\n write(data: string | Uint8Array): void {\n if (!data) return;\n terminal.write(typeof data === 'string' ? data : Buffer.from(data).toString('utf8'));\n },\n resize(cols: number, rows: number): void {\n currentRows = Math.max(1, rows | 0);\n terminal.resize(Math.max(1, cols | 0), currentRows);\n },\n formatVT(): string {\n if (serializer) return serializeXtermViewport(terminal, serializer, currentRows);\n return formatXtermViewportPlain(terminal, currentRows);\n },\n formatPlainText(): string {\n return formatXtermViewportPlain(terminal, currentRows).replace(/\\r\\n/g, '\\n');\n },\n getCursorPosition(): { col: number; row: number } {\n const buffer = terminal.buffer.active;\n return {\n col: Math.max(0, buffer.cursorX || 0),\n row: Math.max(0, buffer.cursorY || 0),\n };\n },\n dispose(): void {\n serializer?.dispose();\n terminal.dispose();\n },\n };\n}\n\nfunction normalizeGhosttyBinding(mod: any): GhosttyBinding | null {\n const raw = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;\n if (!raw) return null;\n\n // Keep Ghostty as the authoritative emulator for terminal query responses, but use\n // xterm's serialized active viewport for UI seeding. Ghostty's formatter serializes\n // scrollback before the active viewport; after full-screen Claude Code redraws (for\n // example `/status` -> Esc), replaying that as a fresh terminal seed makes stale\n // splash-screen rows visible as duplicated logos. xterm's serialize addon gives us\n // the viewport-only seed without dropping SGR color/style or CRLF row movement.\n return {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle {\n const handle = raw.createTerminal(options) as any;\n const viewportSnapshot = createXtermMirror(options);\n return {\n write(data: string | Uint8Array): void {\n handle.write(data);\n viewportSnapshot.write(data);\n },\n resize(cols: number, rows: number): void {\n handle.resize(cols, rows);\n viewportSnapshot.resize(cols, rows);\n },\n formatVT(): string {\n return viewportSnapshot.formatVT();\n },\n formatPlainText(): string {\n return viewportSnapshot.formatPlainText();\n },\n getCursorPosition(): { col: number; row: number } {\n if (typeof handle.getCursorPosition === 'function') return handle.getCursorPosition() as { col: number; row: number };\n return viewportSnapshot.getCursorPosition();\n },\n dispose(): void {\n handle.dispose();\n viewportSnapshot.dispose();\n },\n };\n },\n };\n}\n\nexport const __testing = {\n createXtermMirror,\n formatXtermViewportPlain,\n serializeXtermViewport,\n};\n\nfunction getTerminalMirrorFactory(): (options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle {\n if (terminalMirrorFactory) return terminalMirrorFactory;\n if (terminalMirrorFactory === null) {\n throw new Error(terminalMirrorWarning || 'No terminal mirror backend available');\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const ghosttyMod = require('@adhdev/ghostty-vt-node');\n const binding = normalizeGhosttyBinding(ghosttyMod);\n if (!binding) {\n throw new Error('@adhdev/ghostty-vt-node does not export createTerminal()');\n }\n terminalMirrorFactory = (options) => binding.createTerminal(options);\n logTerminalMirrorBackend('terminal mirror backend=ghostty-vt');\n return terminalMirrorFactory;\n } catch (ghosttyError: any) {\n try {\n terminalMirrorFactory = createXtermMirror;\n terminalMirrorWarning = `Ghostty VT unavailable; falling back to xterm mirror (${ghosttyError?.message || String(ghosttyError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n return terminalMirrorFactory;\n } catch (xtermError: any) {\n terminalMirrorFactory = null;\n terminalMirrorWarning = `No terminal mirror backend available (ghostty: ${ghosttyError?.message || String(ghosttyError)}; xterm: ${xtermError?.message || String(xtermError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n throw new Error(terminalMirrorWarning);\n }\n }\n}\n\nexport class PtySessionRuntime {\n readonly sessionId: string;\n readonly payload: CreateSessionPayload;\n private cols: number;\n private rows: number;\n\n private ptyProcess: IPty | null = null;\n private screenMirror: TerminalMirrorHandle | null = null;\n private pendingQueryScanTail = '';\n private terminalModeScanTail = '';\n private altScreen = false;\n private pasteMode = false;\n private scrollRegion: { top: number; bot: number };\n private onDataCallback: (data: string) => void;\n private onExitCallback: (exitCode: number | null, signal: number | null) => void;\n\n constructor(options: PtyRuntimeOptions) {\n this.sessionId = options.sessionId;\n this.payload = options.payload;\n this.cols = resolveSessionHostCols(options.payload.cols);\n this.rows = resolveSessionHostRows(options.payload.rows);\n this.scrollRegion = { top: 0, bot: this.rows - 1 };\n this.onDataCallback = options.onData;\n this.onExitCallback = options.onExit;\n }\n\n start(): number {\n if (this.ptyProcess) return this.ptyProcess.pid;\n\n const command = this.payload.launchCommand.command;\n const args = this.payload.launchCommand.args || [];\n const env = buildRuntimeEnv(process.env, this.payload.launchCommand.env);\n\n // Validate workspace directory — an invalid cwd causes a native crash on Windows\n // (node-pty error code 267: ERROR_DIRECTORY) that bypasses JS try/catch\n let cwd = this.payload.workspace || process.cwd();\n if (cwd) {\n try {\n const stat = fs.statSync(cwd);\n if (!stat.isDirectory()) cwd = os.homedir();\n } catch {\n cwd = os.homedir();\n }\n }\n\n this.ptyProcess = pty.spawn(command, args, {\n name: 'xterm-256color',\n cols: this.cols,\n rows: this.rows,\n cwd,\n env,\n });\n this.screenMirror = getTerminalMirrorFactory()({\n cols: this.cols,\n rows: this.rows,\n scrollback: 32768,\n });\n\n this.ptyProcess.onData((data: string) => {\n this.screenMirror?.write(data);\n this.trackTerminalModes(data);\n this.respondToTerminalQueries(data);\n this.onDataCallback(data);\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this.ptyProcess = null;\n this.screenMirror?.dispose();\n this.screenMirror = null;\n this.pendingQueryScanTail = '';\n this.terminalModeScanTail = '';\n // Preserve the nullable/unknown exitCode and signal exactly as node-pty\n // reports them: a signal-terminated process arrives as exitCode=null and\n // must stay distinguishable from a clean exit 0.\n this.onExitCallback(\n typeof exitCode === 'number' ? exitCode : null,\n typeof signal === 'number' ? signal : null,\n );\n });\n\n return this.ptyProcess.pid;\n }\n\n write(data: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.write(data);\n }\n\n resize(cols: number, rows: number): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.resize(cols, rows);\n this.cols = Math.max(1, cols | 0);\n this.rows = Math.max(1, rows | 0);\n this.scrollRegion = {\n top: Math.min(this.scrollRegion.top, this.rows - 1),\n bot: Math.min(Math.max(this.scrollRegion.top, this.scrollRegion.bot), this.rows - 1),\n };\n this.screenMirror?.resize(cols, rows);\n }\n\n stop(): void {\n if (!this.ptyProcess) return;\n this.ptyProcess.kill();\n }\n\n sendSignal(signal: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n const normalized = String(signal || '').trim().toUpperCase();\n if (!normalized) throw new Error('signal is required');\n\n try {\n process.kill(this.ptyProcess.pid, normalized as NodeJS.Signals);\n } catch {\n if (normalized === 'SIGTERM' || normalized === 'SIGKILL') {\n this.ptyProcess.kill();\n return;\n }\n throw new Error(`Unsupported signal for runtime ${this.sessionId}: ${normalized}`);\n }\n }\n\n getSnapshotText(): string {\n return this.screenMirror?.formatVT() || '';\n }\n\n getTerminalSnapshot(): SessionTerminalSnapshot {\n if (!this.ptyProcess || !this.screenMirror) {\n throw new Error(`Session not running: ${this.sessionId}`);\n }\n const cursor = this.screenMirror.getCursorPosition();\n return {\n text: this.screenMirror.formatPlainText(),\n state: {\n cursor: {\n row: Math.max(0, cursor.row | 0),\n col: Math.max(0, cursor.col | 0),\n },\n altScreen: this.altScreen,\n pasteMode: this.pasteMode,\n rawMode: true,\n scrollRegion: { ...this.scrollRegion },\n cols: this.cols,\n rows: this.rows,\n },\n };\n }\n\n private trackTerminalModes(data: string): void {\n if (!data) return;\n const combined = this.terminalModeScanTail + data;\n const privateMode = /\\x1b\\[\\?([0-9;]*)([hl])/g;\n let privateMatch: RegExpExecArray | null;\n while ((privateMatch = privateMode.exec(combined)) !== null) {\n const enabled = privateMatch[2] === 'h';\n for (const mode of privateMatch[1].split(';')) {\n if (mode === '47' || mode === '1047' || mode === '1049') this.altScreen = enabled;\n if (mode === '2004') this.pasteMode = enabled;\n }\n }\n\n const scrollRegion = /\\x1b\\[(\\d*)(?:;(\\d*))?r/g;\n let scrollMatch: RegExpExecArray | null;\n while ((scrollMatch = scrollRegion.exec(combined)) !== null) {\n const top = scrollMatch[1] ? Number.parseInt(scrollMatch[1], 10) - 1 : 0;\n const bot = scrollMatch[2] ? Number.parseInt(scrollMatch[2], 10) - 1 : this.rows - 1;\n this.scrollRegion = {\n top: Math.max(0, Math.min(this.rows - 1, top)),\n bot: Math.max(0, Math.min(this.rows - 1, bot)),\n };\n if (this.scrollRegion.bot < this.scrollRegion.top) {\n this.scrollRegion = { top: 0, bot: this.rows - 1 };\n }\n }\n\n const lastEscape = combined.lastIndexOf('\\x1b');\n this.terminalModeScanTail = lastEscape >= 0 && combined.length - lastEscape < 64\n ? combined.slice(lastEscape)\n : '';\n }\n\n private respondToTerminalQueries(data: string): void {\n if (!this.ptyProcess || !this.screenMirror || !data) return;\n\n const combined = this.pendingQueryScanTail + data;\n const regex = /\\x1b\\[(\\?)?6n/g;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(combined)) !== null) {\n const cursor = this.screenMirror.getCursorPosition();\n const row = Math.max(1, (cursor.row | 0) + 1);\n const col = Math.max(1, (cursor.col | 0) + 1);\n const response = match[1]\n ? `\\x1b[?${row};${col}R`\n : `\\x1b[${row};${col}R`;\n this.ptyProcess.write(response);\n }\n\n this.pendingQueryScanTail = computeTerminalQueryTail(combined);\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { SessionBufferSnapshot, SessionHostRecord, SessionTermination } from '@adhdev/session-host-core';\n\nexport interface PersistedRuntimeState {\n record: SessionHostRecord;\n snapshot: SessionBufferSnapshot;\n updatedAt: number;\n}\n\nexport interface PersistedTombstone {\n sessionId: string;\n termination: SessionTermination;\n updatedAt: number;\n}\n\ninterface SessionHostStorageOptions {\n appName?: string;\n}\n\nexport class SessionHostStorage {\n private readonly rootDir: string;\n private readonly runtimesDir: string;\n private readonly tombstonesDir: string;\n\n constructor(options: SessionHostStorageOptions = {}) {\n const appName = options.appName || 'adhdev';\n this.rootDir = path.join(os.homedir(), '.adhdev', 'session-host', appName);\n this.runtimesDir = path.join(this.rootDir, 'runtimes');\n this.tombstonesDir = path.join(this.rootDir, 'tombstones');\n }\n\n loadAll(): PersistedRuntimeState[] {\n if (!fs.existsSync(this.runtimesDir)) return [];\n const entries = fs.readdirSync(this.runtimesDir, { withFileTypes: true });\n const states: PersistedRuntimeState[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.runtimesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedRuntimeState;\n if (parsed?.record?.sessionId) {\n states.push(parsed);\n }\n } catch {\n // Ignore malformed snapshots; host should still boot.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n save(record: SessionHostRecord, snapshot: SessionBufferSnapshot): void {\n fs.mkdirSync(this.runtimesDir, { recursive: true });\n const filePath = path.join(this.runtimesDir, `${record.sessionId}.json`);\n const payload: PersistedRuntimeState = {\n record,\n snapshot,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n remove(sessionId: string): void {\n const filePath = path.join(this.runtimesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n\n /**\n * Persist a compact termination tombstone. Kept in a separate directory from\n * live runtimes so it survives the post-exit cleanup of the runtime file and\n * remains inspectable for post-mortem diagnostics.\n */\n saveTombstone(sessionId: string, termination: SessionTermination): void {\n fs.mkdirSync(this.tombstonesDir, { recursive: true });\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n const payload: PersistedTombstone = {\n sessionId,\n termination,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n loadTombstone(sessionId: string): PersistedTombstone | null {\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n try {\n const parsed = JSON.parse(fs.readFileSync(filePath, 'utf8')) as PersistedTombstone;\n return parsed?.sessionId ? parsed : null;\n } catch {\n return null;\n }\n }\n\n loadAllTombstones(): PersistedTombstone[] {\n if (!fs.existsSync(this.tombstonesDir)) return [];\n const entries = fs.readdirSync(this.tombstonesDir, { withFileTypes: true });\n const states: PersistedTombstone[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.tombstonesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedTombstone;\n if (parsed?.sessionId) states.push(parsed);\n } catch {\n // Ignore malformed tombstones.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n removeTombstone(sessionId: string): void {\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n}\n","import {\n SESSION_HOST_SUPPORTED_REQUEST_TYPES,\n} from '@adhdev/session-host-core';\nimport type {\n SessionHostDiagnostics,\n SessionHostLogEntry,\n SessionHostRecord,\n SessionHostRequestTrace,\n SessionHostRuntimeTransition,\n} from '@adhdev/session-host-core';\n\nexport const MAX_RECENT_DIAGNOSTICS = 200;\n\nexport function pushRecent<T>(bucket: T[], entry: T, max = MAX_RECENT_DIAGNOSTICS): void {\n bucket.push(entry);\n if (bucket.length > max) {\n bucket.splice(0, bucket.length - max);\n }\n}\n\nexport function getSessionHostRecoveryLabel(record: SessionHostRecord): string | null {\n const recoveryState = typeof record.meta?.runtimeRecoveryState === 'string'\n ? String(record.meta.runtimeRecoveryState).trim()\n : '';\n if (!recoveryState) return null;\n if (recoveryState === 'auto_resumed') return 'restored after restart';\n if (recoveryState === 'resume_failed') return 'restore failed';\n if (recoveryState === 'host_restart_interrupted') return 'host restart interrupted';\n if (recoveryState === 'orphan_snapshot') return 'snapshot recovered';\n return recoveryState.replace(/_/g, ' ');\n}\n\nexport function getSessionSurfaceKind(\n record: SessionHostRecord,\n): 'live_runtime' | 'recovery_snapshot' | 'inactive_record' {\n if (['starting', 'running', 'stopping', 'interrupted'].includes(record.lifecycle)) {\n return 'live_runtime';\n }\n if ((record.lifecycle === 'stopped' || record.lifecycle === 'failed') && (record.meta?.restoredFromStorage === true || getSessionHostRecoveryLabel(record))) {\n return 'recovery_snapshot';\n }\n return 'inactive_record';\n}\n\nexport function annotateSessionSurface(record: SessionHostRecord): SessionHostRecord {\n return {\n ...record,\n surfaceKind: getSessionSurfaceKind(record),\n };\n}\n\nexport function sanitizeDiagnosticsRecord(record: SessionHostRecord): SessionHostRecord {\n return {\n ...record,\n launchCommand: {\n command: record.launchCommand.command,\n args: Array.isArray(record.launchCommand.args) ? [...record.launchCommand.args] : [],\n },\n };\n}\n\nexport interface BuildHostDiagnosticsParams {\n payload?: { includeSessions?: boolean; limit?: number };\n hostStartedAt: number;\n endpointPath: string;\n runtimeCount: number;\n sessions: SessionHostRecord[];\n recentLogs: SessionHostLogEntry[];\n recentRequests: SessionHostRequestTrace[];\n recentTransitions: SessionHostRuntimeTransition[];\n}\n\nexport function buildHostDiagnostics(params: BuildHostDiagnosticsParams): SessionHostDiagnostics {\n const limit = Math.max(1, Math.min(200, Number(params.payload?.limit) || 50));\n const allSessions = params.payload?.includeSessions === false\n ? undefined\n : params.sessions\n .map((record) => annotateSessionSurface(record))\n .map((record) => sanitizeDiagnosticsRecord(record));\n const liveRuntimes = allSessions?.filter((record) => record.surfaceKind === 'live_runtime');\n const recoverySnapshots = allSessions?.filter((record) => record.surfaceKind === 'recovery_snapshot').slice(0, limit);\n const inactiveRecords = allSessions?.filter((record) => record.surfaceKind === 'inactive_record').slice(0, limit);\n const sessions = allSessions\n ? [\n ...(liveRuntimes || []),\n ...(recoverySnapshots || []),\n ...(inactiveRecords || []),\n ]\n : undefined;\n return {\n hostStartedAt: params.hostStartedAt,\n endpoint: params.endpointPath,\n runtimeCount: params.runtimeCount,\n supportedRequestTypes: [...SESSION_HOST_SUPPORTED_REQUEST_TYPES],\n sessions,\n liveRuntimes,\n recoverySnapshots,\n inactiveRecords,\n recentLogs: params.recentLogs.slice(-limit),\n recentRequests: params.recentRequests.slice(-limit),\n recentTransitions: params.recentTransitions.slice(-limit),\n };\n}\n","import {\n resolveSessionHostCols,\n resolveSessionHostRows,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionHostDuplicateSessionGroup,\n SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport type { PersistedRuntimeState } from './storage.js';\n\nexport function compareDuplicateCandidates(a: SessionHostRecord, b: SessionHostRecord): number {\n const score = (record: SessionHostRecord) => {\n const lifecycleScore = record.lifecycle === 'running'\n ? 4\n : record.lifecycle === 'starting'\n ? 3\n : record.lifecycle === 'stopping'\n ? 2\n : record.lifecycle === 'interrupted'\n ? 1\n : 0;\n return [\n lifecycleScore,\n record.writeOwner ? 1 : 0,\n Array.isArray(record.attachedClients) ? record.attachedClients.length : 0,\n record.lastActivityAt || 0,\n record.startedAt || 0,\n record.createdAt || 0,\n ];\n };\n\n const aScore = score(a);\n const bScore = score(b);\n for (let i = 0; i < aScore.length; i += 1) {\n if (aScore[i] === bScore[i]) continue;\n return bScore[i] - aScore[i];\n }\n return 0;\n}\n\nexport interface DuplicatePrunePlan {\n duplicateGroups: SessionHostDuplicateSessionGroup[];\n keptSessionIds: string[];\n // Records to prune, in group order. Only populated for non-dry-run callers.\n duplicateRecords: SessionHostRecord[];\n}\n\nexport function planDuplicatePrune(\n sessions: SessionHostRecord[],\n filters: { providerFilter: string; workspaceFilter: string },\n): DuplicatePrunePlan {\n const candidates = sessions\n .filter((record) => ['starting', 'running', 'stopping', 'interrupted'].includes(record.lifecycle))\n .filter((record) => !filters.providerFilter || record.providerType === filters.providerFilter)\n .filter((record) => !filters.workspaceFilter || record.workspace === filters.workspaceFilter);\n\n const groups = new Map<string, SessionHostRecord[]>();\n for (const record of candidates) {\n const providerSessionId = typeof record.meta?.providerSessionId === 'string'\n ? String(record.meta.providerSessionId).trim()\n : '';\n if (!providerSessionId) continue;\n const bindingKey = `${record.providerType}::${record.workspace}::${providerSessionId}`;\n const bucket = groups.get(bindingKey) || [];\n bucket.push(record);\n groups.set(bindingKey, bucket);\n }\n\n const duplicateGroups: SessionHostDuplicateSessionGroup[] = [];\n const keptSessionIds: string[] = [];\n const duplicateRecords: SessionHostRecord[] = [];\n\n for (const [bindingKey, records] of groups.entries()) {\n if (records.length < 2) continue;\n const sorted = [...records].sort((a, b) => compareDuplicateCandidates(a, b));\n const kept = sorted[0];\n const duplicates = sorted.slice(1);\n const providerSessionId = typeof kept.meta?.providerSessionId === 'string'\n ? String(kept.meta.providerSessionId)\n : '';\n duplicateGroups.push({\n bindingKey,\n providerType: kept.providerType,\n workspace: kept.workspace,\n providerSessionId,\n keptSessionId: kept.sessionId,\n prunedSessionIds: duplicates.map((record) => record.sessionId),\n });\n keptSessionIds.push(kept.sessionId);\n for (const duplicate of duplicates) {\n duplicateRecords.push(duplicate);\n }\n }\n\n return { duplicateGroups, keptSessionIds, duplicateRecords };\n}\n\nexport function buildPayloadFromRecord(record: SessionHostRecord): CreateSessionPayload {\n return {\n sessionId: record.sessionId,\n runtimeKey: record.runtimeKey,\n displayName: record.displayName,\n providerType: record.providerType,\n category: record.category,\n workspace: record.workspace,\n launchCommand: record.launchCommand,\n cols: resolveSessionHostCols(typeof record.meta?.sessionHostCols === 'number' ? record.meta.sessionHostCols as number : undefined),\n rows: resolveSessionHostRows(typeof record.meta?.sessionHostRows === 'number' ? record.meta.sessionHostRows as number : undefined),\n meta: record.meta,\n };\n}\n\nexport interface RecoveredRuntimeState {\n recoveredRecord: SessionHostRecord;\n wasLiveRuntime: boolean;\n hadRecoveryInterest: boolean;\n}\n\nexport function buildRecoveredRecord(persisted: PersistedRuntimeState): RecoveredRuntimeState {\n const wasLiveRuntime = !['stopped', 'failed'].includes(persisted.record.lifecycle);\n const hadAttachedClients = Array.isArray(persisted.record.attachedClients) && persisted.record.attachedClients.length > 0;\n const hadWriteOwner = !!persisted.record.writeOwner;\n const hadRecoveryInterest = hadAttachedClients || hadWriteOwner;\n const recoveredRecord: SessionHostRecord = {\n ...persisted.record,\n attachedClients: [],\n writeOwner: null,\n lifecycle: wasLiveRuntime ? 'stopped' : persisted.record.lifecycle,\n lastActivityAt: Date.now(),\n meta: {\n ...(persisted.record.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: wasLiveRuntime ? 'orphan_snapshot' : 'snapshot',\n runtimeHadAttachedClientsAtCrash: hadAttachedClients,\n runtimeHadWriteOwnerAtCrash: hadWriteOwner,\n runtimeAutoResumeSkipped: wasLiveRuntime && hadRecoveryInterest,\n },\n };\n return { recoveredRecord, wasLiveRuntime, hadRecoveryInterest };\n}\n","import type {\n SessionBufferSnapshot,\n SessionHostRecord,\n SessionHostRequest,\n} from '@adhdev/session-host-core';\n\nexport function getRequestSessionId(request: SessionHostRequest): string | undefined {\n const payload = (request as { payload?: Record<string, unknown> }).payload;\n return typeof payload?.sessionId === 'string' ? payload.sessionId : undefined;\n}\n\nexport function getRequestClientId(request: SessionHostRequest): string | undefined {\n const payload = (request as { payload?: Record<string, unknown> }).payload;\n return typeof payload?.clientId === 'string' ? payload.clientId : undefined;\n}\n\n// Merges the registry buffer snapshot with the live runtime's rendered viewport\n// text. For incremental reads (sinceSeq provided) the buffer snapshot is\n// authoritative and the runtime viewport is not overlaid.\nexport function mergeRuntimeSnapshot(\n base: SessionBufferSnapshot,\n record: SessionHostRecord | null | undefined,\n opts: { sinceSeq?: number; runtimeText: string },\n): SessionBufferSnapshot {\n const cols = typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80;\n const rows = typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24;\n if (typeof opts.sinceSeq === 'number' || !opts.runtimeText) {\n return {\n ...base,\n cols,\n rows,\n };\n }\n return {\n ...base,\n text: opts.runtimeText,\n truncated: false,\n cols,\n rows,\n };\n}\n"],"mappings":"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","names":["fs","os","path","import_session_host_core","fs","import_session_host_core","fs","os","import_session_host_core","import_session_host_core","waiters"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/runtime.ts","../src/storage.ts","../src/session-diagnostics.ts","../src/session-lifecycle.ts","../src/session-protocol.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { randomUUID } from 'crypto';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport {\n SessionHostClient,\n formatRuntimeOwner,\n getDefaultSessionHostEndpoint,\n resolveAttachableRuntimeRecord,\n resolveInstanceConfigDir,\n resolveRuntimeRecord,\n resolveSessionHostIpcKey,\n type SessionHostEvent,\n type SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport { SessionHostServer } from './server.js';\n\nexport { SessionHostServer } from './server.js';\nexport type { SessionHostServerOptions } from './server.js';\n\nconst SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || 'adhdev';\n\n// Instance identity comes from the parent daemon's pinned env\n// (ADHDEV_CONFIG_DIR — see managed-host buildEnv). The endpoint, pid file, and\n// storage root all derive from that ONE resolution so the host process lives\n// entirely inside its own instance's namespace: two simultaneous instances\n// (stable/preview/standalone/custom) can never attach to, kill, or persist\n// over each other's session host. The default instance yields the legacy\n// un-suffixed socket and `<home>/.adhdev` paths, byte-identical to before.\nconst INSTANCE_CONFIG_DIR = resolveInstanceConfigDir(process.env);\nconst INSTANCE_IPC_KEY = resolveSessionHostIpcKey(INSTANCE_CONFIG_DIR);\n\nfunction getSessionHostEndpoint() {\n return getDefaultSessionHostEndpoint(SESSION_HOST_APP_NAME, { ipcKey: INSTANCE_IPC_KEY });\n}\n\nfunction getSessionHostStorageRoot(): string {\n return path.join(INSTANCE_CONFIG_DIR, 'session-host', SESSION_HOST_APP_NAME);\n}\n\nfunction getSessionHostPidFile(appName: string): string {\n const dir = INSTANCE_CONFIG_DIR;\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return path.join(dir, `${appName}-session-host.pid`);\n}\n\nfunction writeSessionHostPid(appName: string): void {\n fs.writeFileSync(getSessionHostPidFile(appName), String(process.pid), 'utf8');\n}\n\nfunction removeSessionHostPid(appName: string): void {\n try {\n fs.unlinkSync(getSessionHostPidFile(appName));\n } catch {\n // noop\n }\n}\n\nfunction parseArgs(argv: string[]) {\n const [command, ...rest] = argv;\n const readOnly = rest.includes('--read-only');\n const takeover = rest.includes('--takeover');\n const showAll = rest.includes('--all');\n const positional = rest.filter((arg) => arg !== '--read-only' && arg !== '--takeover' && arg !== '--all');\n return {\n command: command || 'serve',\n positional,\n readOnly,\n takeover,\n showAll,\n };\n}\n\nasync function runServer(): Promise<void> {\n const server = new SessionHostServer({\n appName: SESSION_HOST_APP_NAME,\n endpoint: getSessionHostEndpoint(),\n storageRootDir: getSessionHostStorageRoot(),\n });\n writeSessionHostPid(SESSION_HOST_APP_NAME);\n await server.start();\n\n process.on('SIGINT', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n process.on('SIGTERM', async () => {\n await server.stop();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n process.exit(0);\n });\n\n // Fallback: flush persistence on any exit (covers Windows where SIGTERM is unsupported)\n process.on('exit', () => {\n server.flushAllPersistence();\n removeSessionHostPid(SESSION_HOST_APP_NAME);\n });\n\n // Keep the host alive; IPC transport wiring comes next.\n await new Promise<void>(() => {});\n}\n\nasync function listRuntimes(showAll = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getSessionHostEndpoint() });\n try {\n const response = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!response.success) {\n throw new Error(response.error || 'Failed to list runtimes');\n }\n const runtimes = (response.result || []).filter((runtime: SessionHostRecord) => showAll || runtime.lifecycle !== 'stopped');\n if (runtimes.length === 0) {\n console.log('No runtimes.');\n return;\n }\n console.log('runtimeKey\\tlifecycle\\towner\\tworkspace\\tid\\tdisplayName');\n for (const runtime of runtimes) {\n console.log([\n runtime.runtimeKey,\n runtime.lifecycle,\n formatRuntimeOwner(runtime),\n runtime.workspaceLabel,\n runtime.sessionId,\n runtime.displayName,\n ].join('\\t'));\n }\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nasync function attachRuntime(target: string, readOnly = false, takeover = false): Promise<void> {\n const client = new SessionHostClient({ endpoint: getSessionHostEndpoint() });\n const clientId = `local-terminal-${process.pid}-${randomUUID().slice(0, 8)}`;\n let lastSeq = 0;\n let restoredRawMode = false;\n let runtimeId = '';\n let localReadOnly = readOnly;\n\n const cleanup = async () => {\n process.stdout.off('resize', handleResize);\n process.stdin.off('data', handleInput);\n process.stdin.pause();\n if (process.stdin.isTTY && restoredRawMode) {\n process.stdin.setRawMode(false);\n }\n await client.request({\n type: 'release_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.request({\n type: 'detach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n },\n }).catch(() => ({ success: false }));\n await client.close().catch(() => {});\n };\n\n const handleResize = () => {\n void client.request({\n type: 'resize_session',\n payload: {\n sessionId: runtimeId,\n cols: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n },\n }).catch(() => ({ success: false }));\n };\n\n const sendInputWithTakeover = async (data: string) => {\n let response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (!response.success && response.error?.startsWith('Write owned by ')) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: true,\n },\n });\n if (ownerResponse.success && ownerResponse.result) {\n response = await client.request({\n type: 'send_input',\n payload: {\n sessionId: runtimeId,\n clientId,\n data,\n },\n });\n if (response.success) {\n process.stderr.write(`Took control of ${ownerResponse.result.runtimeKey}.\\n`);\n }\n }\n }\n return response;\n };\n\n const handleInput = (chunk: Buffer) => {\n if (!localReadOnly && chunk.length === 1 && chunk[0] === 0x1d) {\n void cleanup().finally(() => process.exit(0));\n return;\n }\n if (localReadOnly) return;\n void sendInputWithTakeover(chunk.toString('utf8')).catch(() => ({ success: false }));\n };\n\n try {\n if (readOnly && takeover) {\n throw new Error('Use either --read-only or --takeover, not both');\n }\n\n const listResponse = await client.request<SessionHostRecord[]>({\n type: 'list_sessions',\n payload: {},\n });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n let runtimeRecord = resolveAttachableRuntimeRecord(listResponse.result, target);\n runtimeId = runtimeRecord.sessionId;\n\n if (runtimeRecord.lifecycle === 'interrupted' && !readOnly) {\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeId,\n },\n });\n if (resumeResponse.success && resumeResponse.result) {\n runtimeRecord = resumeResponse.result;\n } else {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} could not be resumed automatically: ${resumeResponse.error || 'unknown error'}\\n`,\n );\n }\n }\n\n let effectiveReadOnly = readOnly;\n if (!effectiveReadOnly && runtimeRecord.writeOwner && runtimeRecord.writeOwner.clientId !== clientId && !takeover) {\n process.stderr.write(\n `Runtime ${runtimeRecord.runtimeKey} is currently owned by ${runtimeRecord.writeOwner.clientId}; first input will take control here.\\n`,\n );\n }\n localReadOnly = effectiveReadOnly;\n\n const attachResponse = await client.request<SessionHostRecord>({\n type: 'attach_session',\n payload: {\n sessionId: runtimeId,\n clientId,\n clientType: 'local-terminal',\n readOnly: effectiveReadOnly,\n },\n });\n if (!attachResponse.success) {\n throw new Error(attachResponse.error || `Failed to attach runtime ${runtimeId}`);\n }\n const attachedRecord = attachResponse.result || null;\n\n if (!effectiveReadOnly && takeover) {\n const ownerResponse = await client.request<SessionHostRecord>({\n type: 'acquire_write',\n payload: {\n sessionId: runtimeId,\n clientId,\n ownerType: 'user',\n force: takeover,\n },\n });\n if (!ownerResponse.success) {\n throw new Error(ownerResponse.error || `Failed to acquire write owner for runtime ${runtimeId}`);\n }\n }\n\n const snapshotResponse = await client.request<{ seq: number; text: string; truncated: boolean; cols?: number; rows?: number }>({\n type: 'get_snapshot',\n payload: { sessionId: runtimeId },\n });\n if (!snapshotResponse.success) {\n throw new Error(snapshotResponse.error || `Failed to read runtime snapshot ${runtimeId}`);\n }\n lastSeq = snapshotResponse.result?.seq || 0;\n if (snapshotResponse.result?.text) {\n process.stdout.write(snapshotResponse.result.text);\n }\n if (attachedRecord?.lifecycle === 'stopped' || attachedRecord?.lifecycle === 'failed' || attachedRecord?.lifecycle === 'interrupted') {\n process.stderr.write(`Runtime ${attachedRecord.runtimeKey} is already ${attachedRecord.lifecycle}. Detached after snapshot.\\n`);\n await cleanup();\n return;\n }\n\n const stopSignals = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n const signalHandlers = stopSignals.map((signal) => {\n const handler = () => {\n void cleanup().finally(() => process.exit(0));\n };\n process.on(signal, handler);\n return { signal, handler };\n });\n\n const unsubscribe = client.onEvent((event: SessionHostEvent) => {\n if (!('sessionId' in event)) return;\n if (event.sessionId !== runtimeId) return;\n if (event.type === 'session_output') {\n if (event.seq <= lastSeq) return;\n lastSeq = event.seq;\n process.stdout.write(event.data);\n return;\n }\n if (event.type === 'session_exit') {\n void cleanup().finally(() => {\n for (const { signal, handler } of signalHandlers) {\n process.off(signal, handler);\n }\n unsubscribe();\n process.exit(event.exitCode ?? 0);\n });\n }\n });\n\n process.stdout.on('resize', handleResize);\n process.stdin.on('data', handleInput);\n process.stdin.resume();\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n restoredRawMode = true;\n }\n handleResize();\n if (!effectiveReadOnly) {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId}. Press Ctrl+] to detach.\\n`);\n } else {\n process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId} (read-only).\\n`);\n }\n await new Promise<void>(() => {});\n } catch (error) {\n await cleanup().catch(() => {});\n throw error;\n }\n}\n\nasync function main(): Promise<void> {\n const { command, positional, readOnly, takeover, showAll } = parseArgs(process.argv.slice(2));\n if (command === 'serve') {\n await runServer();\n return;\n }\n if (command === 'list') {\n await listRuntimes(showAll);\n return;\n }\n if (command === 'attach') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond attach <runtimeId|runtimeKey>');\n }\n await attachRuntime(target, readOnly, takeover);\n return;\n }\n if (command === 'resume') {\n const target = positional[0];\n if (!target) {\n throw new Error('runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>');\n }\n const client = new SessionHostClient({ endpoint: getSessionHostEndpoint() });\n try {\n const listResponse = await client.request<SessionHostRecord[]>({ type: 'list_sessions', payload: {} });\n if (!listResponse.success || !listResponse.result) {\n throw new Error(listResponse.error || 'Failed to list runtimes');\n }\n const runtimeRecord = resolveRuntimeRecord(listResponse.result, target);\n const resumeResponse = await client.request<SessionHostRecord>({\n type: 'resume_session',\n payload: {\n sessionId: runtimeRecord.sessionId,\n },\n });\n if (!resumeResponse.success || !resumeResponse.result) {\n throw new Error(resumeResponse.error || `Failed to resume runtime ${runtimeRecord.runtimeKey}`);\n }\n console.log(`Resumed ${resumeResponse.result.runtimeKey} (${resumeResponse.result.sessionId})`);\n } finally {\n await client.close().catch(() => {});\n }\n return;\n }\n throw new Error(`Unknown command: ${command}`);\n}\n\nif (require.main === module) {\n // Prevent native crashes (e.g. node-pty on Windows) from silently killing the server process\n process.on('uncaughtException', (err) => {\n console.error(`[session-host] Uncaught exception: ${err?.message}\\n${err?.stack || ''}`);\n // Do not exit — keep the server alive for existing sessions\n });\n process.on('unhandledRejection', (reason: any) => {\n console.error(`[session-host] Unhandled rejection: ${reason?.message || reason}`);\n });\n\n void main().catch((error) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n });\n}\n","import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as net from 'net';\nimport {\n SessionHostRegistry,\n classifyTermination,\n createLineParser,\n createResponseEnvelope,\n getDefaultSessionHostEndpoint,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionAttachedClient,\n SessionHostDiagnostics,\n SessionHostEndpoint,\n SessionHostEvent,\n SessionHostLogEntry,\n SessionHostPruneDuplicatesResult,\n SessionHostRecord,\n SessionHostRequestEnvelope,\n SessionHostRequestTrace,\n SessionHostRequest,\n SessionHostRuntimeTransition,\n SessionHostResponse,\n SessionTermination,\n} from '@adhdev/session-host-core';\nimport { PtySessionRuntime } from './runtime.js';\nimport { SessionHostStorage } from './storage.js';\nimport {\n buildHostDiagnostics,\n pushRecent,\n} from './session-diagnostics.js';\nimport {\n buildPayloadFromRecord,\n buildRecoveredRecord,\n planDuplicatePrune,\n} from './session-lifecycle.js';\nimport {\n getRequestClientId,\n getRequestSessionId,\n mergeRuntimeSnapshot,\n} from './session-protocol.js';\n\nexport interface SessionHostServerOptions {\n endpoint?: SessionHostEndpoint;\n appName?: string;\n /** Explicit session-host state root (runtime records + tombstones). */\n storageRootDir?: string;\n}\n\nexport class SessionHostServer extends EventEmitter {\n readonly endpoint: SessionHostEndpoint;\n readonly registry = new SessionHostRegistry();\n private runtimes = new Map<string, PtySessionRuntime>();\n private readonly storage: SessionHostStorage;\n private ipcServer: net.Server | null = null;\n private sockets = new Set<net.Socket>();\n // Tracks which sessionIds each socket has subscribed to (via create/attach).\n // Used to avoid broadcasting session-specific events to uninterested sockets.\n private socketSessions = new Map<net.Socket, Set<string>>();\n private persistTimers = new Map<string, NodeJS.Timeout>();\n private readonly startedAt = Date.now();\n private recentLogs: SessionHostLogEntry[] = [];\n private recentRequests: SessionHostRequestTrace[] = [];\n private recentTransitions: SessionHostRuntimeTransition[] = [];\n private exitWaiters = new Map<string, Array<(exitCode: number | null) => void>>();\n private lastNoOutputInputWarnAt = new Map<string, number>();\n // Records the most recent explicit stop/delete/restart/prune request per\n // session so the termination diagnostic can attribute the exit to it.\n private stopRequests = new Map<string, SessionTermination['requestedStop']>();\n\n constructor(options: SessionHostServerOptions = {}) {\n super();\n this.endpoint = options.endpoint || getDefaultSessionHostEndpoint(options.appName || 'adhdev');\n this.storage = new SessionHostStorage({\n appName: options.appName || 'adhdev',\n rootDir: options.storageRootDir,\n });\n }\n\n async start(): Promise<void> {\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n\n this.ipcServer = net.createServer((socket) => {\n this.sockets.add(socket);\n const removeSocket = () => {\n this.sockets.delete(socket);\n this.socketSessions.delete(socket);\n };\n socket.on('close', removeSocket);\n socket.on('end', removeSocket);\n socket.on('error', () => {\n removeSocket();\n try {\n socket.destroy();\n } catch {\n // noop\n }\n });\n socket.on('data', createLineParser((envelope) => {\n if (envelope.kind !== 'request') return;\n void this.handleIncomingRequest(socket, envelope);\n }));\n });\n\n await new Promise<void>((resolve, reject) => {\n this.ipcServer?.once('listening', () => resolve());\n this.ipcServer?.once('error', reject);\n this.ipcServer?.listen(this.endpoint.path);\n });\n\n this.recordHostLog('info', `session host endpoint ready: ${this.endpoint.path}`);\n // Do not block readiness on restoring/resuming persisted runtimes.\n // Startup callers only need the IPC endpoint to accept connections.\n setTimeout(() => {\n try {\n this.restorePersistedRuntimes();\n } catch (error: any) {\n this.recordHostLog('error', `session host restore failed: ${error?.message || String(error)}`);\n }\n }, 0);\n }\n\n async stop(): Promise<void> {\n this.flushAllPersistence();\n for (const runtime of this.runtimes.values()) {\n try {\n runtime.stop();\n } catch {\n // noop\n }\n }\n this.runtimes.clear();\n for (const timer of this.persistTimers.values()) {\n clearTimeout(timer);\n }\n this.persistTimers.clear();\n for (const socket of this.sockets) {\n socket.destroy();\n }\n this.sockets.clear();\n this.socketSessions.clear();\n if (this.ipcServer) {\n const server = this.ipcServer;\n this.ipcServer = null;\n await new Promise<void>((resolve) => server.close(() => resolve()));\n }\n if (this.endpoint.kind === 'unix') {\n try {\n fs.unlinkSync(this.endpoint.path);\n } catch {\n // noop\n }\n }\n this.removeAllListeners();\n }\n\n async handleRequest(request: SessionHostRequest): Promise<SessionHostResponse> {\n try {\n switch (request.type) {\n case 'create_session': {\n const record = this.registry.createSession(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_created', sessionId: record.sessionId, record });\n this.recordRuntimeTransition(record.sessionId, 'create_session', 'starting', `provider=${record.providerType}`, true);\n try {\n const startedRecord = this.startRuntime(record, request.payload, 'session_started');\n return { success: true, result: startedRecord };\n } catch (error: any) {\n this.registry.markStopped(record.sessionId, 'failed');\n this.persistNow(record.sessionId);\n this.recordRuntimeTransition(record.sessionId, 'create_session_failed', 'failed', undefined, false, error?.message || String(error));\n return { success: false, error: error?.message || String(error) };\n }\n }\n case 'list_sessions':\n return { success: true, result: this.registry.listSessions() };\n case 'attach_session': {\n const record = this.registry.attachClient(request.payload);\n this.schedulePersist(record.sessionId);\n const client = record.attachedClients.find(item => item.clientId === request.payload.clientId);\n if (client) {\n this.emitEvent({ type: 'client_attached', sessionId: record.sessionId, client });\n }\n this.recordRuntimeTransition(record.sessionId, 'attach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'detach_session': {\n const record = this.registry.detachClient(request.payload);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n this.recordRuntimeTransition(record.sessionId, 'detach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'acquire_write': {\n const record = this.registry.acquireWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n this.recordRuntimeTransition(record.sessionId, 'acquire_write', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'release_write': {\n const record = this.registry.releaseWrite(request.payload);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'write_owner_changed', sessionId: record.sessionId, owner: record.writeOwner });\n this.recordRuntimeTransition(record.sessionId, 'release_write', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n case 'get_snapshot':\n return { success: true, result: this.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };\n case 'get_terminal_snapshot':\n return { success: true, result: this.requireRuntime(request.payload.sessionId).getTerminalSnapshot() };\n case 'get_host_diagnostics':\n return { success: true, result: this.getHostDiagnostics(request.payload) };\n case 'clear_session_buffer': {\n const record = this.registry.clearBuffer(request.payload.sessionId);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: 'session_cleared', sessionId: record.sessionId });\n this.recordRuntimeTransition(record.sessionId, 'clear_buffer', record.lifecycle, undefined, true);\n return { success: true, result: record };\n }\n case 'update_session_meta': {\n const record = this.registry.updateSessionMeta(\n request.payload.sessionId,\n request.payload.meta || {},\n request.payload.replace === true,\n );\n this.persistNow(record.sessionId);\n this.recordRuntimeTransition(record.sessionId, 'update_meta', record.lifecycle, undefined, true);\n return { success: true, result: record };\n }\n case 'send_input': {\n const client = this.getAttachedClient(request.payload.sessionId, request.payload.clientId);\n if (client?.readOnly) {\n return { success: false, error: `Client ${request.payload.clientId} is read-only` };\n }\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner && session.writeOwner.clientId !== request.payload.clientId) {\n return { success: false, error: `Write owned by ${session.writeOwner.clientId}` };\n }\n const runtime = this.requireRuntime(request.payload.sessionId);\n const beforeSnapshotSeq = this.registry.getSnapshot(request.payload.sessionId)?.seq ?? 0;\n runtime.write(request.payload.data);\n this.scheduleNoOutputInputDiagnostic({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n input: request.payload.data,\n beforeSnapshotSeq,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'resize_session': {\n this.requireRuntime(request.payload.sessionId).resize(request.payload.cols, request.payload.rows);\n const record = this.registry.getSession(request.payload.sessionId);\n if (record) {\n this.registry.restoreSession(\n {\n ...record,\n meta: {\n ...(record.meta || {}),\n sessionHostCols: request.payload.cols,\n sessionHostRows: request.payload.rows,\n },\n },\n this.registry.getSnapshot(request.payload.sessionId),\n );\n }\n this.schedulePersist(request.payload.sessionId);\n this.emitEvent({\n type: 'session_resized',\n sessionId: request.payload.sessionId,\n cols: request.payload.cols,\n rows: request.payload.rows,\n });\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'stop_session': {\n this.stopRequests.set(request.payload.sessionId, 'stop');\n this.registry.setLifecycle(request.payload.sessionId, 'stopping');\n this.persistNow(request.payload.sessionId);\n this.requireRuntime(request.payload.sessionId).stop();\n this.emitEvent({ type: 'session_stopped', sessionId: request.payload.sessionId });\n this.recordRuntimeTransition(request.payload.sessionId, 'stop_session', 'stopping', undefined, true);\n return { success: true, result: this.registry.getSession(request.payload.sessionId) };\n }\n case 'delete_session': {\n const record = this.registry.getSession(request.payload.sessionId);\n if (!record) return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n if (this.runtimes.has(record.sessionId)) {\n if (!request.payload.force) {\n return { success: false, error: `Session ${record.sessionId} is still running; pass force to stop and delete it` };\n }\n this.stopRequests.set(record.sessionId, 'delete');\n this.registry.setLifecycle(record.sessionId, 'stopping');\n this.persistNow(record.sessionId);\n this.requireRuntime(record.sessionId).stop();\n await this.waitForRuntimeExit(record.sessionId).catch((error: any) => {\n this.recordRuntimeTransition(record.sessionId, 'delete_session_timeout', 'stopping', undefined, false, error?.message || String(error));\n });\n }\n this.registry.deleteSession(record.sessionId);\n this.storage.remove(record.sessionId);\n this.storage.removeTombstone(record.sessionId);\n this.stopRequests.delete(record.sessionId);\n this.emitEvent({ type: 'session_deleted', sessionId: record.sessionId });\n this.recordRuntimeTransition(record.sessionId, 'delete_session', record.lifecycle, undefined, true);\n return { success: true, result: { sessionId: record.sessionId, deleted: true } };\n }\n case 'resume_session': {\n const existing = this.registry.getSession(request.payload.sessionId);\n if (!existing) {\n return { success: false, error: `Unknown session: ${request.payload.sessionId}` };\n }\n if (this.runtimes.has(request.payload.sessionId)) {\n return { success: true, result: existing };\n }\n const resumed = this.startRuntime(existing, buildPayloadFromRecord(existing), 'session_resumed');\n this.recordRuntimeTransition(request.payload.sessionId, 'resume_session', resumed.lifecycle, undefined, true);\n return { success: true, result: resumed };\n }\n case 'restart_session': {\n const restarted = await this.restartRuntime(request.payload.sessionId);\n return { success: true, result: restarted };\n }\n case 'prune_duplicate_sessions': {\n const result = await this.pruneDuplicateSessions(request.payload);\n return { success: true, result };\n }\n case 'send_signal': {\n const runtime = this.requireRuntime(request.payload.sessionId);\n runtime.sendSignal(request.payload.signal);\n const record = this.registry.getSession(request.payload.sessionId);\n this.recordRuntimeTransition(request.payload.sessionId, 'send_signal', record?.lifecycle, request.payload.signal, true);\n return { success: true, result: record };\n }\n case 'force_detach_client': {\n const session = this.registry.getSession(request.payload.sessionId);\n if (session?.writeOwner?.clientId === request.payload.clientId) {\n const released = this.registry.releaseWrite({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n });\n this.emitEvent({ type: 'write_owner_changed', sessionId: released.sessionId, owner: released.writeOwner });\n }\n const record = this.registry.detachClient({\n sessionId: request.payload.sessionId,\n clientId: request.payload.clientId,\n });\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'client_detached', sessionId: record.sessionId, clientId: request.payload.clientId });\n this.recordRuntimeTransition(record.sessionId, 'force_detach_client', record.lifecycle, request.payload.clientId, true);\n return { success: true, result: record };\n }\n default:\n return { success: false, error: `Unsupported session host request: ${(request as { type?: string })?.type || 'unknown'}` };\n }\n } catch (error: any) {\n return { success: false, error: error?.message || String(error) };\n }\n }\n\n private requireRuntime(sessionId: string): PtySessionRuntime {\n const runtime = this.runtimes.get(sessionId);\n if (!runtime) throw new Error(`Runtime not found for session: ${sessionId}`);\n return runtime;\n }\n\n private getAttachedClient(sessionId: string, clientId: string): SessionAttachedClient | null {\n const session = this.registry.getSession(sessionId);\n return session?.attachedClients.find((client) => client.clientId === clientId) || null;\n }\n\n private emitEvent(event: SessionHostEvent): void {\n // Diagnostic-only events are stored locally (recentLogs/Requests/Transitions)\n // and accessible via get_host_diagnostics. Broadcasting them to every socket\n // creates O(N²) traffic when many CLI sessions are active.\n const diagnosticOnly = event.type === 'request_trace'\n || event.type === 'runtime_transition'\n || event.type === 'host_log';\n if (!diagnosticOnly) {\n const targetSessionId = 'sessionId' in event ? (event as { sessionId: string }).sessionId : null;\n for (const socket of [...this.sockets]) {\n // If the event is session-specific, only send to sockets subscribed to that session.\n if (targetSessionId && event.type === 'session_output') {\n const sessions = this.socketSessions.get(socket);\n if (!sessions?.has(targetSessionId)) continue;\n } else if (targetSessionId && this.socketSessions.size > 0) {\n const sessions = this.socketSessions.get(socket);\n if (sessions && !sessions.has(targetSessionId)) continue;\n }\n this.writeEnvelopeSafely(socket, {\n kind: 'event',\n event,\n });\n }\n }\n this.emit('event', event);\n }\n\n private subscribeSocketToSession(socket: net.Socket, sessionId: string): void {\n let sessions = this.socketSessions.get(socket);\n if (!sessions) {\n sessions = new Set();\n this.socketSessions.set(socket, sessions);\n }\n sessions.add(sessionId);\n }\n\n private async handleIncomingRequest(socket: net.Socket, envelope: SessionHostRequestEnvelope): Promise<void> {\n const sessionId = getRequestSessionId(envelope.request);\n if (sessionId && (envelope.request.type === 'create_session' || envelope.request.type === 'attach_session')) {\n this.subscribeSocketToSession(socket, sessionId);\n }\n const startedAt = Date.now();\n const response = await this.handleRequest(envelope.request);\n if (sessionId && envelope.request.type === 'create_session' && response.success) {\n // sessionId may have been auto-generated — subscribe to whatever was actually created\n const createdId = (response.result as { sessionId?: string } | undefined)?.sessionId;\n if (createdId && createdId !== sessionId) this.subscribeSocketToSession(socket, createdId);\n }\n this.recordRequestTrace({\n timestamp: startedAt,\n requestId: envelope.requestId,\n type: envelope.request.type,\n sessionId: getRequestSessionId(envelope.request),\n clientId: getRequestClientId(envelope.request),\n success: response.success,\n durationMs: Math.max(0, Date.now() - startedAt),\n error: response.success ? undefined : response.error,\n });\n this.writeEnvelopeSafely(socket, createResponseEnvelope(envelope.requestId, response));\n }\n\n private writeEnvelopeSafely(socket: net.Socket, envelope: SessionHostRequestEnvelope | ReturnType<typeof createResponseEnvelope> | { kind: 'event'; event: SessionHostEvent }): void {\n if (socket.destroyed || !socket.writable || socket.writableEnded) {\n this.sockets.delete(socket);\n return;\n }\n const payload = `${JSON.stringify(envelope)}\\n`;\n try {\n socket.write(payload, (error?: Error | null) => {\n if (!error) return;\n this.sockets.delete(socket);\n try {\n socket.destroy();\n } catch {\n // noop\n }\n });\n } catch {\n this.sockets.delete(socket);\n try {\n socket.destroy();\n } catch {\n // noop\n }\n }\n }\n\n private schedulePersist(sessionId: string): void {\n const existing = this.persistTimers.get(sessionId);\n if (existing) clearTimeout(existing);\n this.persistTimers.set(sessionId, setTimeout(() => {\n this.persistTimers.delete(sessionId);\n this.persistNow(sessionId);\n }, 200));\n }\n\n private persistNow(sessionId: string): void {\n const record = this.registry.getSession(sessionId);\n if (!record) return;\n const snapshot = this.getSnapshot(sessionId);\n try {\n this.storage.save(record, snapshot);\n } catch (error: any) {\n const code = typeof error?.code === 'string' ? error.code : 'persist_failed';\n console.error(`[session-host] Persist failed for ${sessionId}: ${code}: ${error?.message || error}`);\n }\n }\n\n private getHostDiagnostics(payload?: { includeSessions?: boolean; limit?: number }): SessionHostDiagnostics {\n return buildHostDiagnostics({\n payload,\n hostStartedAt: this.startedAt,\n endpointPath: this.endpoint.path,\n runtimeCount: this.runtimes.size,\n sessions: this.registry.listSessions(),\n recentLogs: this.recentLogs,\n recentRequests: this.recentRequests,\n recentTransitions: this.recentTransitions,\n });\n }\n\n private recordHostLog(\n level: SessionHostLogEntry['level'],\n message: string,\n sessionId?: string,\n data?: Record<string, unknown>,\n ): void {\n const entry: SessionHostLogEntry = {\n timestamp: Date.now(),\n level,\n message,\n sessionId,\n data,\n };\n pushRecent(this.recentLogs, entry);\n this.emitEvent({ type: 'host_log', entry });\n this.emit('log', `[${level}] ${message}`);\n }\n\n private recordRequestTrace(trace: SessionHostRequestTrace): void {\n pushRecent(this.recentRequests, trace);\n this.emitEvent({ type: 'request_trace', trace });\n if (!trace.success) {\n this.recordHostLog(\n 'warn',\n `request ${trace.type} failed after ${trace.durationMs}ms${trace.error ? `: ${trace.error}` : ''}`,\n trace.sessionId,\n { requestId: trace.requestId, clientId: trace.clientId },\n );\n }\n }\n\n private scheduleNoOutputInputDiagnostic(params: {\n sessionId: string;\n clientId: string;\n input: string;\n beforeSnapshotSeq: number;\n }): void {\n if (!params.input || /^\\x1b/.test(params.input)) {\n return;\n }\n\n const hasPotentialEcho = /[^\\x00-\\x1F\\x7F]/.test(params.input);\n if (!hasPotentialEcho && params.input !== '\\r' && params.input !== '\\n') {\n return;\n }\n\n setTimeout(() => {\n let afterSnapshotSeq = params.beforeSnapshotSeq;\n try {\n afterSnapshotSeq = this.registry.getSnapshot(params.sessionId)?.seq ?? params.beforeSnapshotSeq;\n } catch {\n return;\n }\n if (afterSnapshotSeq > params.beforeSnapshotSeq) {\n return;\n }\n\n const now = Date.now();\n const lastWarnAt = this.lastNoOutputInputWarnAt.get(params.sessionId) || 0;\n if (now - lastWarnAt < 10_000) {\n return;\n }\n this.lastNoOutputInputWarnAt.set(params.sessionId, now);\n const record = this.registry.getSession(params.sessionId);\n this.recordHostLog(\n 'warn',\n 'send_input produced no terminal output after PTY write; runtime may be ignoring stdin or stuck in a hidden input reader',\n params.sessionId,\n {\n clientId: params.clientId,\n inputLength: params.input.length,\n beforeSnapshotSeq: params.beforeSnapshotSeq,\n afterSnapshotSeq,\n lifecycle: record?.lifecycle,\n osPid: record?.osPid,\n providerType: record?.providerType,\n },\n );\n this.recordRuntimeTransition(\n params.sessionId,\n 'send_input_no_output_after_write',\n record?.lifecycle,\n `clientId=${params.clientId} inputLength=${params.input.length} seq=${params.beforeSnapshotSeq}`,\n false,\n 'no terminal output after PTY write',\n );\n }, 250);\n }\n\n private recordRuntimeTransition(\n sessionId: string,\n action: string,\n lifecycle?: SessionHostRuntimeTransition['lifecycle'],\n detail?: string,\n success = true,\n error?: string,\n ): void {\n const transition: SessionHostRuntimeTransition = {\n timestamp: Date.now(),\n sessionId,\n action,\n lifecycle,\n detail,\n success,\n error,\n };\n pushRecent(this.recentTransitions, transition);\n this.emitEvent({ type: 'runtime_transition', transition });\n }\n\n private waitForRuntimeExit(sessionId: string, timeoutMs = 5_000): Promise<number | null> {\n if (!this.runtimes.has(sessionId)) {\n return Promise.resolve(this.registry.getSession(sessionId)?.lifecycle === 'failed' ? 1 : 0);\n }\n return new Promise<number | null>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const waiters = this.exitWaiters.get(sessionId) || [];\n this.exitWaiters.set(sessionId, waiters.filter((waiter) => waiter !== onExit));\n reject(new Error(`Timed out waiting for runtime ${sessionId} to exit`));\n }, timeoutMs);\n const onExit = (exitCode: number | null) => {\n clearTimeout(timeout);\n resolve(exitCode);\n };\n const waiters = this.exitWaiters.get(sessionId) || [];\n waiters.push(onExit);\n this.exitWaiters.set(sessionId, waiters);\n });\n }\n\n private resolveExitWaiters(sessionId: string, exitCode: number | null): void {\n const waiters = this.exitWaiters.get(sessionId);\n if (!waiters?.length) return;\n this.exitWaiters.delete(sessionId);\n for (const waiter of waiters) {\n try {\n waiter(exitCode);\n } catch {\n // noop\n }\n }\n }\n\n private getSnapshot(sessionId: string, sinceSeq?: number) {\n const snapshot = this.registry.getSnapshot(sessionId, sinceSeq);\n const record = this.registry.getSession(sessionId);\n const runtimeText = typeof sinceSeq === 'number'\n ? ''\n : (this.runtimes.get(sessionId)?.getSnapshotText?.() || '');\n return mergeRuntimeSnapshot(snapshot, record, { sinceSeq, runtimeText });\n }\n\n flushAllPersistence(): void {\n for (const sessionId of this.runtimes.keys()) {\n this.persistNow(sessionId);\n }\n for (const record of this.registry.listSessions()) {\n this.persistNow(record.sessionId);\n }\n }\n\n private async restartRuntime(sessionId: string): Promise<SessionHostRecord> {\n const existing = this.registry.getSession(sessionId);\n if (!existing) {\n throw new Error(`Unknown session: ${sessionId}`);\n }\n\n if (this.runtimes.has(sessionId)) {\n this.stopRequests.set(sessionId, 'restart');\n this.registry.setLifecycle(sessionId, 'stopping');\n this.persistNow(sessionId);\n this.recordRuntimeTransition(sessionId, 'restart_requested', 'stopping', undefined, true);\n this.requireRuntime(sessionId).stop();\n await this.waitForRuntimeExit(sessionId);\n }\n\n const latest = this.registry.getSession(sessionId) || existing;\n const restarted = this.startRuntime(latest, buildPayloadFromRecord(latest), 'session_resumed');\n this.recordRuntimeTransition(sessionId, 'restart_completed', restarted.lifecycle, undefined, true);\n return restarted;\n }\n\n private async pruneDuplicateSessions(payload?: {\n providerType?: string;\n workspace?: string;\n dryRun?: boolean;\n }): Promise<SessionHostPruneDuplicatesResult> {\n const providerFilter = typeof payload?.providerType === 'string' ? payload.providerType.trim() : '';\n const workspaceFilter = typeof payload?.workspace === 'string' ? payload.workspace.trim() : '';\n const dryRun = payload?.dryRun === true;\n\n const { duplicateGroups, keptSessionIds, duplicateRecords } = planDuplicatePrune(\n this.registry.listSessions(),\n { providerFilter, workspaceFilter },\n );\n\n const prunedSessionIds: string[] = [];\n if (!dryRun) {\n for (const duplicate of duplicateRecords) {\n await this.pruneDuplicateRuntime(duplicate);\n prunedSessionIds.push(duplicate.sessionId);\n }\n }\n\n this.recordHostLog(\n dryRun ? 'info' : 'warn',\n `${dryRun ? 'session host dry-run found' : 'session host pruned'} ${duplicateGroups.length} duplicate group(s)`,\n undefined,\n {\n providerType: providerFilter || undefined,\n workspace: workspaceFilter || undefined,\n dryRun,\n prunedSessionIds,\n keptSessionIds,\n },\n );\n\n return {\n duplicateGroupCount: duplicateGroups.length,\n keptSessionIds,\n prunedSessionIds,\n groups: duplicateGroups,\n };\n }\n\n private restorePersistedRuntimes(): void {\n const states = this.storage.loadAll();\n let skippedAutoResumeSessions = 0;\n for (const persisted of states) {\n const { recoveredRecord, wasLiveRuntime, hadRecoveryInterest } = buildRecoveredRecord(persisted);\n this.registry.restoreSession(recoveredRecord, persisted.snapshot);\n this.storage.save(recoveredRecord, persisted.snapshot);\n if (wasLiveRuntime && hadRecoveryInterest) {\n skippedAutoResumeSessions += 1;\n }\n }\n\n if (skippedAutoResumeSessions > 0) {\n this.recordHostLog('warn', `session host restored ${skippedAutoResumeSessions} live runtime snapshot(s) without auto-resume`);\n }\n }\n\n private async pruneDuplicateRuntime(record: SessionHostRecord): Promise<void> {\n const providerSessionId = typeof record.meta?.providerSessionId === 'string'\n ? String(record.meta.providerSessionId)\n : undefined;\n this.recordRuntimeTransition(\n record.sessionId,\n 'prune_duplicate_session',\n record.lifecycle,\n providerSessionId ? `providerSessionId=${providerSessionId}` : undefined,\n true,\n );\n\n if (this.runtimes.has(record.sessionId)) {\n this.stopRequests.set(record.sessionId, 'prune');\n this.registry.setLifecycle(record.sessionId, 'stopping');\n this.persistNow(record.sessionId);\n this.requireRuntime(record.sessionId).stop();\n await this.waitForRuntimeExit(record.sessionId).catch((error: any) => {\n this.recordRuntimeTransition(record.sessionId, 'prune_duplicate_timeout', 'stopping', undefined, false, error?.message || String(error));\n });\n }\n\n this.registry.deleteSession(record.sessionId);\n this.storage.remove(record.sessionId);\n this.storage.removeTombstone(record.sessionId);\n this.stopRequests.delete(record.sessionId);\n }\n\n private startRuntime(\n record: SessionHostRecord,\n payload: CreateSessionPayload,\n startEventType: 'session_started' | 'session_resumed',\n ): SessionHostRecord {\n const runtime = new PtySessionRuntime({\n sessionId: record.sessionId,\n payload,\n onData: (data) => {\n const { seq } = this.registry.appendOutput(record.sessionId, data);\n this.schedulePersist(record.sessionId);\n this.emitEvent({ type: 'session_output', sessionId: record.sessionId, seq, data });\n },\n onExit: (exitCode, signal) => this.handleRuntimeExit(record, exitCode, signal),\n });\n\n this.registry.setLifecycle(record.sessionId, 'starting');\n const pid = runtime.start();\n this.runtimes.set(record.sessionId, runtime);\n const startedRecord = this.registry.markStarted(record.sessionId, pid);\n this.persistNow(record.sessionId);\n this.emitEvent({ type: startEventType, sessionId: record.sessionId, pid });\n this.recordRuntimeTransition(record.sessionId, startEventType, startedRecord.lifecycle, `pid=${pid}`, true);\n return startedRecord;\n }\n\n /**\n * Handle a PTY termination: classify the (exitCode, signal) pair, stamp the\n * record + tombstone, emit exactly one structured diagnostic, and schedule\n * cleanup of the live persistence file (the tombstone is retained).\n */\n private handleRuntimeExit(record: SessionHostRecord, exitCode: number | null, signal: number | null): SessionTermination {\n // Capture pre-termination context BEFORE mutating the record.\n const priorRecord = this.registry.getSession(record.sessionId);\n const termination = classifyTermination({\n exitCode,\n signal,\n osPid: priorRecord?.osPid,\n previousLifecycle: priorRecord?.lifecycle,\n lastOutputAt: priorRecord?.lastActivityAt,\n requestedStop: this.stopRequests.get(record.sessionId),\n terminatedAt: Date.now(),\n });\n this.stopRequests.delete(record.sessionId);\n\n this.registry.markStopped(record.sessionId, termination.lifecycle, termination);\n this.runtimes.delete(record.sessionId);\n this.resolveExitWaiters(record.sessionId, exitCode);\n this.persistNow(record.sessionId);\n // Persist a tombstone that survives live-record cleanup so the termination\n // stays inspectable after the 5s removal below.\n this.storage.saveTombstone(record.sessionId, termination);\n this.emitEvent({ type: 'session_exit', sessionId: record.sessionId, exitCode, signal, termination });\n const summary = `reason=${termination.reason} exitCode=${termination.exitCode === null ? 'unknown' : termination.exitCode} signal=${termination.signal ?? 'none'}`;\n // Exactly one structured, secret-free termination diagnostic.\n this.recordHostLog(\n termination.lifecycle === 'stopped' ? 'info' : 'warn',\n `session terminated: ${summary}`,\n record.sessionId,\n {\n runtimeKey: record.runtimeKey,\n providerType: record.providerType,\n osPid: termination.osPid,\n exitCode: termination.exitCode,\n signal: termination.signal,\n reason: termination.reason,\n previousLifecycle: termination.previousLifecycle,\n lifecycle: termination.lifecycle,\n lastOutputAt: termination.lastOutputAt,\n requestedStop: termination.requestedStop,\n },\n );\n this.recordRuntimeTransition(\n record.sessionId,\n 'session_exit',\n termination.lifecycle,\n summary,\n termination.lifecycle === 'stopped',\n termination.lifecycle === 'stopped' ? undefined : summary,\n );\n // Clean up the live persistence file after a brief delay (allow post-mortem\n // reads). The tombstone written above is retained.\n setTimeout(() => this.storage.remove(record.sessionId), 5_000).unref?.();\n return termination;\n }\n}\n","import * as fs from 'fs';\nimport * as os from 'os';\nimport * as pty from 'node-pty';\nimport type { IPty } from 'node-pty';\nimport type { CreateSessionPayload, SessionTerminalSnapshot } from '@adhdev/session-host-core';\nimport {\n sanitizeSpawnEnv,\n ensureNodePtySpawnHelperPermissions,\n resolveSessionHostCols,\n resolveSessionHostRows,\n} from '@adhdev/session-host-core';\n\ntype TerminalMirrorHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n formatPlainText(): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyTerminalHandle = {\n write(data: string | Uint8Array): void;\n resize(cols: number, rows: number): void;\n formatVT(): string;\n formatPlainText(options?: { trim?: boolean }): string;\n getCursorPosition(): { col: number; row: number };\n dispose(): void;\n};\n\ntype GhosttyBinding = {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle;\n};\n\ntype XtermBufferLine = {\n translateToString(trimRight?: boolean): string;\n};\n\ntype XtermBuffer = {\n length: number;\n viewportY: number;\n cursorX?: number;\n cursorY?: number;\n getLine(index: number): XtermBufferLine | undefined;\n};\n\ntype XtermTerminal = {\n buffer: { active: XtermBuffer };\n loadAddon(addon: { activate(terminal: XtermTerminal): void }): void;\n write(data: string, callback?: () => void): void;\n resize(cols: number, rows: number): void;\n dispose(): void;\n};\n\ntype XtermCtor = new (options: { cols: number; rows: number; scrollback: number }) => XtermTerminal;\n\ntype XtermSerializeAddon = {\n serialize(options?: { range?: { start: number; end: number }; scrollback?: number; excludeModes?: boolean }): string;\n dispose(): void;\n};\n\nlet terminalMirrorFactory:\n | ((options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle)\n | null\n | undefined;\nlet terminalMirrorWarning: string | null = null;\nlet terminalMirrorBackendLogged = false;\n\nensureNodePtySpawnHelperPermissions((msg: string) => console.log(`[session-host] ${msg}`));\n\nfunction logTerminalMirrorBackend(message: string, level: 'info' | 'warn' = 'info'): void {\n if (terminalMirrorBackendLogged) return;\n terminalMirrorBackendLogged = true;\n const prefix = '[session-host]';\n if (level === 'warn') console.warn(`${prefix} ${message}`);\n else console.log(`${prefix} ${message}`);\n}\n\nexport interface PtyRuntimeOptions {\n sessionId: string;\n payload: CreateSessionPayload;\n onData: (data: string) => void;\n onExit: (exitCode: number | null, signal: number | null) => void;\n}\n\n// Use shared spawn env sanitizer — alias for backward compat within this file\nconst buildRuntimeEnv = sanitizeSpawnEnv;\n\nfunction computeTerminalQueryTail(buffer: string): string {\n const prefixes = ['\\x1b[6n', '\\x1b[?6n'];\n const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;\n const start = Math.max(0, buffer.length - maxLength);\n for (let i = start; i < buffer.length; i++) {\n const suffix = buffer.slice(i);\n if (prefixes.some((pattern) => suffix.length < pattern.length && pattern.startsWith(suffix))) {\n return suffix;\n }\n }\n return '';\n}\n\nfunction formatXtermViewportPlain(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(buffer.length || 0, start + Math.max(1, rows | 0)));\n const lines: string[] = [];\n\n for (let i = start; i < end; i++) {\n const line = buffer.getLine(i);\n const raw = line ? line.translateToString(false) : '';\n lines.push(raw.replace(/\\s+$/, ''));\n }\n\n let first = 0;\n let last = lines.length;\n while (first < last && !lines[first]?.trim()) first++;\n while (last > first && !lines[last - 1]?.trim()) last--;\n // Use CRLF row boundaries for unambiguous terminal replay regardless of the\n // browser xterm convertEol setting. CRLF is always explicit; bare LF depends\n // on convertEol being true to reset the cursor column, which is not guaranteed\n // for all xterm consumer configurations.\n return lines.slice(first, last).join('\\r\\n');\n}\n\nfunction createXtermSerializeAddon(terminal: XtermTerminal): XtermSerializeAddon | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/addon-serialize');\n const SerializeAddon = mod.SerializeAddon || mod.default?.SerializeAddon || mod.default;\n if (!SerializeAddon) return null;\n const addon = new SerializeAddon() as XtermSerializeAddon & { activate(terminal: XtermTerminal): void };\n terminal.loadAddon(addon);\n return addon;\n } catch {\n return null;\n }\n}\n\nfunction formatCursorRestore(terminal: XtermTerminal, rows: number): string {\n const buffer = terminal.buffer.active;\n const row = Math.max(0, Math.min(Math.max(0, rows | 0) - 1, buffer.cursorY || 0));\n const col = Math.max(0, buffer.cursorX || 0);\n return `\\x1b[${row + 1};${col + 1}H`;\n}\n\nfunction serializeXtermViewport(terminal: XtermTerminal, serializer: XtermSerializeAddon, rows: number): string {\n const buffer = terminal.buffer.active;\n const start = Math.max(0, buffer.viewportY || 0);\n const end = Math.max(start, Math.min(Math.max(0, buffer.length || 0) - 1, start + Math.max(1, rows | 0) - 1));\n if (end < start) return '';\n const viewport = serializer.serialize({\n range: { start, end },\n excludeModes: true,\n });\n // Range serialization reproduces the visible cells, but leaves the replay cursor\n // at the end of the serialized viewport. CLIs like Claude frequently update the\n // current status line with relative cursor movement; if the dashboard seeds a\n // snapshot and then receives an incremental update, that update must continue\n // from the live cursor row, not from the next line after the viewport replay.\n return `${viewport}${formatCursorRestore(terminal, rows)}`;\n}\n\nfunction createXtermMirror(options: { cols: number; rows: number; scrollback: number }): TerminalMirrorHandle {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const mod = require('@xterm/xterm');\n const Terminal = (mod.Terminal || mod.default?.Terminal || mod.default) as XtermCtor | undefined;\n if (!Terminal) {\n throw new Error('@xterm/xterm Terminal export not found');\n }\n\n let currentRows = Math.max(1, options.rows | 0);\n const terminal = new Terminal({\n cols: Math.max(1, options.cols | 0),\n rows: currentRows,\n scrollback: Math.max(0, options.scrollback | 0),\n });\n const serializer = createXtermSerializeAddon(terminal);\n\n return {\n write(data: string | Uint8Array): void {\n if (!data) return;\n terminal.write(typeof data === 'string' ? data : Buffer.from(data).toString('utf8'));\n },\n resize(cols: number, rows: number): void {\n currentRows = Math.max(1, rows | 0);\n terminal.resize(Math.max(1, cols | 0), currentRows);\n },\n formatVT(): string {\n if (serializer) return serializeXtermViewport(terminal, serializer, currentRows);\n return formatXtermViewportPlain(terminal, currentRows);\n },\n formatPlainText(): string {\n return formatXtermViewportPlain(terminal, currentRows).replace(/\\r\\n/g, '\\n');\n },\n getCursorPosition(): { col: number; row: number } {\n const buffer = terminal.buffer.active;\n return {\n col: Math.max(0, buffer.cursorX || 0),\n row: Math.max(0, buffer.cursorY || 0),\n };\n },\n dispose(): void {\n serializer?.dispose();\n terminal.dispose();\n },\n };\n}\n\nfunction normalizeGhosttyBinding(mod: any): GhosttyBinding | null {\n const raw = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;\n if (!raw) return null;\n\n // Keep Ghostty as the authoritative emulator for terminal query responses, but use\n // xterm's serialized active viewport for UI seeding. Ghostty's formatter serializes\n // scrollback before the active viewport; after full-screen Claude Code redraws (for\n // example `/status` -> Esc), replaying that as a fresh terminal seed makes stale\n // splash-screen rows visible as duplicated logos. xterm's serialize addon gives us\n // the viewport-only seed without dropping SGR color/style or CRLF row movement.\n return {\n createTerminal(options: { cols: number; rows: number; scrollback: number }): GhosttyTerminalHandle {\n const handle = raw.createTerminal(options) as any;\n const viewportSnapshot = createXtermMirror(options);\n return {\n write(data: string | Uint8Array): void {\n handle.write(data);\n viewportSnapshot.write(data);\n },\n resize(cols: number, rows: number): void {\n handle.resize(cols, rows);\n viewportSnapshot.resize(cols, rows);\n },\n formatVT(): string {\n return viewportSnapshot.formatVT();\n },\n formatPlainText(): string {\n return viewportSnapshot.formatPlainText();\n },\n getCursorPosition(): { col: number; row: number } {\n if (typeof handle.getCursorPosition === 'function') return handle.getCursorPosition() as { col: number; row: number };\n return viewportSnapshot.getCursorPosition();\n },\n dispose(): void {\n handle.dispose();\n viewportSnapshot.dispose();\n },\n };\n },\n };\n}\n\nexport const __testing = {\n createXtermMirror,\n formatXtermViewportPlain,\n serializeXtermViewport,\n};\n\nfunction getTerminalMirrorFactory(): (options: { cols: number; rows: number; scrollback: number }) => TerminalMirrorHandle {\n if (terminalMirrorFactory) return terminalMirrorFactory;\n if (terminalMirrorFactory === null) {\n throw new Error(terminalMirrorWarning || 'No terminal mirror backend available');\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const ghosttyMod = require('@adhdev/ghostty-vt-node');\n const binding = normalizeGhosttyBinding(ghosttyMod);\n if (!binding) {\n throw new Error('@adhdev/ghostty-vt-node does not export createTerminal()');\n }\n terminalMirrorFactory = (options) => binding.createTerminal(options);\n logTerminalMirrorBackend('terminal mirror backend=ghostty-vt');\n return terminalMirrorFactory;\n } catch (ghosttyError: any) {\n try {\n terminalMirrorFactory = createXtermMirror;\n terminalMirrorWarning = `Ghostty VT unavailable; falling back to xterm mirror (${ghosttyError?.message || String(ghosttyError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n return terminalMirrorFactory;\n } catch (xtermError: any) {\n terminalMirrorFactory = null;\n terminalMirrorWarning = `No terminal mirror backend available (ghostty: ${ghosttyError?.message || String(ghosttyError)}; xterm: ${xtermError?.message || String(xtermError)})`;\n logTerminalMirrorBackend(terminalMirrorWarning, 'warn');\n throw new Error(terminalMirrorWarning);\n }\n }\n}\n\nexport class PtySessionRuntime {\n readonly sessionId: string;\n readonly payload: CreateSessionPayload;\n private cols: number;\n private rows: number;\n\n private ptyProcess: IPty | null = null;\n private screenMirror: TerminalMirrorHandle | null = null;\n private pendingQueryScanTail = '';\n private terminalModeScanTail = '';\n private altScreen = false;\n private pasteMode = false;\n private scrollRegion: { top: number; bot: number };\n private onDataCallback: (data: string) => void;\n private onExitCallback: (exitCode: number | null, signal: number | null) => void;\n\n constructor(options: PtyRuntimeOptions) {\n this.sessionId = options.sessionId;\n this.payload = options.payload;\n this.cols = resolveSessionHostCols(options.payload.cols);\n this.rows = resolveSessionHostRows(options.payload.rows);\n this.scrollRegion = { top: 0, bot: this.rows - 1 };\n this.onDataCallback = options.onData;\n this.onExitCallback = options.onExit;\n }\n\n start(): number {\n if (this.ptyProcess) return this.ptyProcess.pid;\n\n const command = this.payload.launchCommand.command;\n const args = this.payload.launchCommand.args || [];\n const env = buildRuntimeEnv(process.env, this.payload.launchCommand.env);\n\n // Validate workspace directory — an invalid cwd causes a native crash on Windows\n // (node-pty error code 267: ERROR_DIRECTORY) that bypasses JS try/catch\n let cwd = this.payload.workspace || process.cwd();\n if (cwd) {\n try {\n const stat = fs.statSync(cwd);\n if (!stat.isDirectory()) cwd = os.homedir();\n } catch {\n cwd = os.homedir();\n }\n }\n\n this.ptyProcess = pty.spawn(command, args, {\n name: 'xterm-256color',\n cols: this.cols,\n rows: this.rows,\n cwd,\n env,\n });\n this.screenMirror = getTerminalMirrorFactory()({\n cols: this.cols,\n rows: this.rows,\n scrollback: 32768,\n });\n\n this.ptyProcess.onData((data: string) => {\n this.screenMirror?.write(data);\n this.trackTerminalModes(data);\n this.respondToTerminalQueries(data);\n this.onDataCallback(data);\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this.ptyProcess = null;\n this.screenMirror?.dispose();\n this.screenMirror = null;\n this.pendingQueryScanTail = '';\n this.terminalModeScanTail = '';\n // Preserve the nullable/unknown exitCode and signal exactly as node-pty\n // reports them: a signal-terminated process arrives as exitCode=null and\n // must stay distinguishable from a clean exit 0.\n this.onExitCallback(\n typeof exitCode === 'number' ? exitCode : null,\n typeof signal === 'number' ? signal : null,\n );\n });\n\n return this.ptyProcess.pid;\n }\n\n write(data: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.write(data);\n }\n\n resize(cols: number, rows: number): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n this.ptyProcess.resize(cols, rows);\n this.cols = Math.max(1, cols | 0);\n this.rows = Math.max(1, rows | 0);\n this.scrollRegion = {\n top: Math.min(this.scrollRegion.top, this.rows - 1),\n bot: Math.min(Math.max(this.scrollRegion.top, this.scrollRegion.bot), this.rows - 1),\n };\n this.screenMirror?.resize(cols, rows);\n }\n\n stop(): void {\n if (!this.ptyProcess) return;\n this.ptyProcess.kill();\n }\n\n sendSignal(signal: string): void {\n if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);\n const normalized = String(signal || '').trim().toUpperCase();\n if (!normalized) throw new Error('signal is required');\n\n try {\n process.kill(this.ptyProcess.pid, normalized as NodeJS.Signals);\n } catch {\n if (normalized === 'SIGTERM' || normalized === 'SIGKILL') {\n this.ptyProcess.kill();\n return;\n }\n throw new Error(`Unsupported signal for runtime ${this.sessionId}: ${normalized}`);\n }\n }\n\n getSnapshotText(): string {\n return this.screenMirror?.formatVT() || '';\n }\n\n getTerminalSnapshot(): SessionTerminalSnapshot {\n if (!this.ptyProcess || !this.screenMirror) {\n throw new Error(`Session not running: ${this.sessionId}`);\n }\n const cursor = this.screenMirror.getCursorPosition();\n return {\n text: this.screenMirror.formatPlainText(),\n state: {\n cursor: {\n row: Math.max(0, cursor.row | 0),\n col: Math.max(0, cursor.col | 0),\n },\n altScreen: this.altScreen,\n pasteMode: this.pasteMode,\n rawMode: true,\n scrollRegion: { ...this.scrollRegion },\n cols: this.cols,\n rows: this.rows,\n },\n };\n }\n\n private trackTerminalModes(data: string): void {\n if (!data) return;\n const combined = this.terminalModeScanTail + data;\n const privateMode = /\\x1b\\[\\?([0-9;]*)([hl])/g;\n let privateMatch: RegExpExecArray | null;\n while ((privateMatch = privateMode.exec(combined)) !== null) {\n const enabled = privateMatch[2] === 'h';\n for (const mode of privateMatch[1].split(';')) {\n if (mode === '47' || mode === '1047' || mode === '1049') this.altScreen = enabled;\n if (mode === '2004') this.pasteMode = enabled;\n }\n }\n\n const scrollRegion = /\\x1b\\[(\\d*)(?:;(\\d*))?r/g;\n let scrollMatch: RegExpExecArray | null;\n while ((scrollMatch = scrollRegion.exec(combined)) !== null) {\n const top = scrollMatch[1] ? Number.parseInt(scrollMatch[1], 10) - 1 : 0;\n const bot = scrollMatch[2] ? Number.parseInt(scrollMatch[2], 10) - 1 : this.rows - 1;\n this.scrollRegion = {\n top: Math.max(0, Math.min(this.rows - 1, top)),\n bot: Math.max(0, Math.min(this.rows - 1, bot)),\n };\n if (this.scrollRegion.bot < this.scrollRegion.top) {\n this.scrollRegion = { top: 0, bot: this.rows - 1 };\n }\n }\n\n const lastEscape = combined.lastIndexOf('\\x1b');\n this.terminalModeScanTail = lastEscape >= 0 && combined.length - lastEscape < 64\n ? combined.slice(lastEscape)\n : '';\n }\n\n private respondToTerminalQueries(data: string): void {\n if (!this.ptyProcess || !this.screenMirror || !data) return;\n\n const combined = this.pendingQueryScanTail + data;\n const regex = /\\x1b\\[(\\?)?6n/g;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(combined)) !== null) {\n const cursor = this.screenMirror.getCursorPosition();\n const row = Math.max(1, (cursor.row | 0) + 1);\n const col = Math.max(1, (cursor.col | 0) + 1);\n const response = match[1]\n ? `\\x1b[?${row};${col}R`\n : `\\x1b[${row};${col}R`;\n this.ptyProcess.write(response);\n }\n\n this.pendingQueryScanTail = computeTerminalQueryTail(combined);\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { resolveInstanceConfigDir } from '@adhdev/session-host-core';\nimport type { SessionBufferSnapshot, SessionHostRecord, SessionTermination } from '@adhdev/session-host-core';\n\nexport interface PersistedRuntimeState {\n record: SessionHostRecord;\n snapshot: SessionBufferSnapshot;\n updatedAt: number;\n}\n\nexport interface PersistedTombstone {\n sessionId: string;\n termination: SessionTermination;\n updatedAt: number;\n}\n\ninterface SessionHostStorageOptions {\n appName?: string;\n /**\n * Explicit storage root (the instance's session-host state dir). Defaults to\n * `<instanceConfigDir>/session-host/<appName>` — derived from\n * ADHDEV_CONFIG_DIR so each daemon instance persists its own runtime records\n * and tombstones. The default instance resolves to `<home>/.adhdev`,\n * byte-identical to the pre-instance layout.\n */\n rootDir?: string;\n}\n\nexport class SessionHostStorage {\n private readonly rootDir: string;\n private readonly runtimesDir: string;\n private readonly tombstonesDir: string;\n\n constructor(options: SessionHostStorageOptions = {}) {\n const appName = options.appName || 'adhdev';\n this.rootDir = options.rootDir\n || path.join(resolveInstanceConfigDir(process.env), 'session-host', appName);\n this.runtimesDir = path.join(this.rootDir, 'runtimes');\n this.tombstonesDir = path.join(this.rootDir, 'tombstones');\n }\n\n loadAll(): PersistedRuntimeState[] {\n if (!fs.existsSync(this.runtimesDir)) return [];\n const entries = fs.readdirSync(this.runtimesDir, { withFileTypes: true });\n const states: PersistedRuntimeState[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.runtimesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedRuntimeState;\n if (parsed?.record?.sessionId) {\n states.push(parsed);\n }\n } catch {\n // Ignore malformed snapshots; host should still boot.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n save(record: SessionHostRecord, snapshot: SessionBufferSnapshot): void {\n fs.mkdirSync(this.runtimesDir, { recursive: true });\n const filePath = path.join(this.runtimesDir, `${record.sessionId}.json`);\n const payload: PersistedRuntimeState = {\n record,\n snapshot,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n remove(sessionId: string): void {\n const filePath = path.join(this.runtimesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n\n /**\n * Persist a compact termination tombstone. Kept in a separate directory from\n * live runtimes so it survives the post-exit cleanup of the runtime file and\n * remains inspectable for post-mortem diagnostics.\n */\n saveTombstone(sessionId: string, termination: SessionTermination): void {\n fs.mkdirSync(this.tombstonesDir, { recursive: true });\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n const payload: PersistedTombstone = {\n sessionId,\n termination,\n updatedAt: Date.now(),\n };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), 'utf8');\n }\n\n loadTombstone(sessionId: string): PersistedTombstone | null {\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n try {\n const parsed = JSON.parse(fs.readFileSync(filePath, 'utf8')) as PersistedTombstone;\n return parsed?.sessionId ? parsed : null;\n } catch {\n return null;\n }\n }\n\n loadAllTombstones(): PersistedTombstone[] {\n if (!fs.existsSync(this.tombstonesDir)) return [];\n const entries = fs.readdirSync(this.tombstonesDir, { withFileTypes: true });\n const states: PersistedTombstone[] = [];\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.json')) continue;\n const fullPath = path.join(this.tombstonesDir, entry.name);\n try {\n const parsed = JSON.parse(fs.readFileSync(fullPath, 'utf8')) as PersistedTombstone;\n if (parsed?.sessionId) states.push(parsed);\n } catch {\n // Ignore malformed tombstones.\n }\n }\n return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));\n }\n\n removeTombstone(sessionId: string): void {\n const filePath = path.join(this.tombstonesDir, `${sessionId}.json`);\n try {\n fs.unlinkSync(filePath);\n } catch {\n // File may not exist — ignore.\n }\n }\n}\n","import {\n SESSION_HOST_SUPPORTED_REQUEST_TYPES,\n} from '@adhdev/session-host-core';\nimport type {\n SessionHostDiagnostics,\n SessionHostLogEntry,\n SessionHostRecord,\n SessionHostRequestTrace,\n SessionHostRuntimeTransition,\n} from '@adhdev/session-host-core';\n\nexport const MAX_RECENT_DIAGNOSTICS = 200;\n\nexport function pushRecent<T>(bucket: T[], entry: T, max = MAX_RECENT_DIAGNOSTICS): void {\n bucket.push(entry);\n if (bucket.length > max) {\n bucket.splice(0, bucket.length - max);\n }\n}\n\nexport function getSessionHostRecoveryLabel(record: SessionHostRecord): string | null {\n const recoveryState = typeof record.meta?.runtimeRecoveryState === 'string'\n ? String(record.meta.runtimeRecoveryState).trim()\n : '';\n if (!recoveryState) return null;\n if (recoveryState === 'auto_resumed') return 'restored after restart';\n if (recoveryState === 'resume_failed') return 'restore failed';\n if (recoveryState === 'host_restart_interrupted') return 'host restart interrupted';\n if (recoveryState === 'orphan_snapshot') return 'snapshot recovered';\n return recoveryState.replace(/_/g, ' ');\n}\n\nexport function getSessionSurfaceKind(\n record: SessionHostRecord,\n): 'live_runtime' | 'recovery_snapshot' | 'inactive_record' {\n if (['starting', 'running', 'stopping', 'interrupted'].includes(record.lifecycle)) {\n return 'live_runtime';\n }\n if ((record.lifecycle === 'stopped' || record.lifecycle === 'failed') && (record.meta?.restoredFromStorage === true || getSessionHostRecoveryLabel(record))) {\n return 'recovery_snapshot';\n }\n return 'inactive_record';\n}\n\nexport function annotateSessionSurface(record: SessionHostRecord): SessionHostRecord {\n return {\n ...record,\n surfaceKind: getSessionSurfaceKind(record),\n };\n}\n\nexport function sanitizeDiagnosticsRecord(record: SessionHostRecord): SessionHostRecord {\n return {\n ...record,\n launchCommand: {\n command: record.launchCommand.command,\n args: Array.isArray(record.launchCommand.args) ? [...record.launchCommand.args] : [],\n },\n };\n}\n\nexport interface BuildHostDiagnosticsParams {\n payload?: { includeSessions?: boolean; limit?: number };\n hostStartedAt: number;\n endpointPath: string;\n runtimeCount: number;\n sessions: SessionHostRecord[];\n recentLogs: SessionHostLogEntry[];\n recentRequests: SessionHostRequestTrace[];\n recentTransitions: SessionHostRuntimeTransition[];\n}\n\nexport function buildHostDiagnostics(params: BuildHostDiagnosticsParams): SessionHostDiagnostics {\n const limit = Math.max(1, Math.min(200, Number(params.payload?.limit) || 50));\n const allSessions = params.payload?.includeSessions === false\n ? undefined\n : params.sessions\n .map((record) => annotateSessionSurface(record))\n .map((record) => sanitizeDiagnosticsRecord(record));\n const liveRuntimes = allSessions?.filter((record) => record.surfaceKind === 'live_runtime');\n const recoverySnapshots = allSessions?.filter((record) => record.surfaceKind === 'recovery_snapshot').slice(0, limit);\n const inactiveRecords = allSessions?.filter((record) => record.surfaceKind === 'inactive_record').slice(0, limit);\n const sessions = allSessions\n ? [\n ...(liveRuntimes || []),\n ...(recoverySnapshots || []),\n ...(inactiveRecords || []),\n ]\n : undefined;\n return {\n hostStartedAt: params.hostStartedAt,\n endpoint: params.endpointPath,\n runtimeCount: params.runtimeCount,\n supportedRequestTypes: [...SESSION_HOST_SUPPORTED_REQUEST_TYPES],\n sessions,\n liveRuntimes,\n recoverySnapshots,\n inactiveRecords,\n recentLogs: params.recentLogs.slice(-limit),\n recentRequests: params.recentRequests.slice(-limit),\n recentTransitions: params.recentTransitions.slice(-limit),\n };\n}\n","import {\n resolveSessionHostCols,\n resolveSessionHostRows,\n} from '@adhdev/session-host-core';\nimport type {\n CreateSessionPayload,\n SessionHostDuplicateSessionGroup,\n SessionHostRecord,\n} from '@adhdev/session-host-core';\nimport type { PersistedRuntimeState } from './storage.js';\n\nexport function compareDuplicateCandidates(a: SessionHostRecord, b: SessionHostRecord): number {\n const score = (record: SessionHostRecord) => {\n const lifecycleScore = record.lifecycle === 'running'\n ? 4\n : record.lifecycle === 'starting'\n ? 3\n : record.lifecycle === 'stopping'\n ? 2\n : record.lifecycle === 'interrupted'\n ? 1\n : 0;\n return [\n lifecycleScore,\n record.writeOwner ? 1 : 0,\n Array.isArray(record.attachedClients) ? record.attachedClients.length : 0,\n record.lastActivityAt || 0,\n record.startedAt || 0,\n record.createdAt || 0,\n ];\n };\n\n const aScore = score(a);\n const bScore = score(b);\n for (let i = 0; i < aScore.length; i += 1) {\n if (aScore[i] === bScore[i]) continue;\n return bScore[i] - aScore[i];\n }\n return 0;\n}\n\nexport interface DuplicatePrunePlan {\n duplicateGroups: SessionHostDuplicateSessionGroup[];\n keptSessionIds: string[];\n // Records to prune, in group order. Only populated for non-dry-run callers.\n duplicateRecords: SessionHostRecord[];\n}\n\nexport function planDuplicatePrune(\n sessions: SessionHostRecord[],\n filters: { providerFilter: string; workspaceFilter: string },\n): DuplicatePrunePlan {\n const candidates = sessions\n .filter((record) => ['starting', 'running', 'stopping', 'interrupted'].includes(record.lifecycle))\n .filter((record) => !filters.providerFilter || record.providerType === filters.providerFilter)\n .filter((record) => !filters.workspaceFilter || record.workspace === filters.workspaceFilter);\n\n const groups = new Map<string, SessionHostRecord[]>();\n for (const record of candidates) {\n const providerSessionId = typeof record.meta?.providerSessionId === 'string'\n ? String(record.meta.providerSessionId).trim()\n : '';\n if (!providerSessionId) continue;\n const bindingKey = `${record.providerType}::${record.workspace}::${providerSessionId}`;\n const bucket = groups.get(bindingKey) || [];\n bucket.push(record);\n groups.set(bindingKey, bucket);\n }\n\n const duplicateGroups: SessionHostDuplicateSessionGroup[] = [];\n const keptSessionIds: string[] = [];\n const duplicateRecords: SessionHostRecord[] = [];\n\n for (const [bindingKey, records] of groups.entries()) {\n if (records.length < 2) continue;\n const sorted = [...records].sort((a, b) => compareDuplicateCandidates(a, b));\n const kept = sorted[0];\n const duplicates = sorted.slice(1);\n const providerSessionId = typeof kept.meta?.providerSessionId === 'string'\n ? String(kept.meta.providerSessionId)\n : '';\n duplicateGroups.push({\n bindingKey,\n providerType: kept.providerType,\n workspace: kept.workspace,\n providerSessionId,\n keptSessionId: kept.sessionId,\n prunedSessionIds: duplicates.map((record) => record.sessionId),\n });\n keptSessionIds.push(kept.sessionId);\n for (const duplicate of duplicates) {\n duplicateRecords.push(duplicate);\n }\n }\n\n return { duplicateGroups, keptSessionIds, duplicateRecords };\n}\n\nexport function buildPayloadFromRecord(record: SessionHostRecord): CreateSessionPayload {\n return {\n sessionId: record.sessionId,\n runtimeKey: record.runtimeKey,\n displayName: record.displayName,\n providerType: record.providerType,\n category: record.category,\n workspace: record.workspace,\n launchCommand: record.launchCommand,\n cols: resolveSessionHostCols(typeof record.meta?.sessionHostCols === 'number' ? record.meta.sessionHostCols as number : undefined),\n rows: resolveSessionHostRows(typeof record.meta?.sessionHostRows === 'number' ? record.meta.sessionHostRows as number : undefined),\n meta: record.meta,\n };\n}\n\nexport interface RecoveredRuntimeState {\n recoveredRecord: SessionHostRecord;\n wasLiveRuntime: boolean;\n hadRecoveryInterest: boolean;\n}\n\nexport function buildRecoveredRecord(persisted: PersistedRuntimeState): RecoveredRuntimeState {\n const wasLiveRuntime = !['stopped', 'failed'].includes(persisted.record.lifecycle);\n const hadAttachedClients = Array.isArray(persisted.record.attachedClients) && persisted.record.attachedClients.length > 0;\n const hadWriteOwner = !!persisted.record.writeOwner;\n const hadRecoveryInterest = hadAttachedClients || hadWriteOwner;\n const recoveredRecord: SessionHostRecord = {\n ...persisted.record,\n attachedClients: [],\n writeOwner: null,\n lifecycle: wasLiveRuntime ? 'stopped' : persisted.record.lifecycle,\n lastActivityAt: Date.now(),\n meta: {\n ...(persisted.record.meta || {}),\n restoredFromStorage: true,\n runtimeRecoveryState: wasLiveRuntime ? 'orphan_snapshot' : 'snapshot',\n runtimeHadAttachedClientsAtCrash: hadAttachedClients,\n runtimeHadWriteOwnerAtCrash: hadWriteOwner,\n runtimeAutoResumeSkipped: wasLiveRuntime && hadRecoveryInterest,\n },\n };\n return { recoveredRecord, wasLiveRuntime, hadRecoveryInterest };\n}\n","import type {\n SessionBufferSnapshot,\n SessionHostRecord,\n SessionHostRequest,\n} from '@adhdev/session-host-core';\n\nexport function getRequestSessionId(request: SessionHostRequest): string | undefined {\n const payload = (request as { payload?: Record<string, unknown> }).payload;\n return typeof payload?.sessionId === 'string' ? payload.sessionId : undefined;\n}\n\nexport function getRequestClientId(request: SessionHostRequest): string | undefined {\n const payload = (request as { payload?: Record<string, unknown> }).payload;\n return typeof payload?.clientId === 'string' ? payload.clientId : undefined;\n}\n\n// Merges the registry buffer snapshot with the live runtime's rendered viewport\n// text. For incremental reads (sinceSeq provided) the buffer snapshot is\n// authoritative and the runtime viewport is not overlaid.\nexport function mergeRuntimeSnapshot(\n base: SessionBufferSnapshot,\n record: SessionHostRecord | null | undefined,\n opts: { sinceSeq?: number; runtimeText: string },\n): SessionBufferSnapshot {\n const cols = typeof record?.meta?.sessionHostCols === 'number' ? (record.meta.sessionHostCols as number) : 80;\n const rows = typeof record?.meta?.sessionHostRows === 'number' ? (record.meta.sessionHostRows as number) : 24;\n if (typeof opts.sinceSeq === 'number' || !opts.runtimeText) {\n return {\n ...base,\n cols,\n rows,\n };\n }\n return {\n ...base,\n text: opts.runtimeText,\n truncated: false,\n cols,\n rows,\n };\n}\n"],"mappings":"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","names":["fs","path","import_session_host_core","fs","import_session_host_core","fs","import_session_host_core","import_session_host_core","import_session_host_core","waiters"]}
|