pty-manager 1.7.1 → 1.7.2
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 +3 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +3 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/pty-manager.ts","../src/adapters/adapter-registry.ts","../src/pty-session.ts","../src/logger.ts","../src/task-completion-trace.ts","../src/adapters/base-adapter.ts","../src/adapters/adapter-factory.ts","../src/adapters/shell-adapter.ts","../src/bun-compat.ts"],"sourcesContent":["/**\n * pty-manager\n *\n * PTY session manager with lifecycle management,\n * pluggable adapters, and blocking prompt detection.\n */\n\n// Core classes\nexport { PTYManager } from './pty-manager';\nexport { PTYSession, SPECIAL_KEYS } from './pty-session';\nexport {\n extractTaskCompletionTraceRecords,\n buildTaskCompletionTimeline,\n} from './task-completion-trace';\n\n// Adapter system\nexport {\n AdapterRegistry,\n BaseCLIAdapter,\n createAdapter,\n ShellAdapter,\n} from './adapters';\n\nexport type { CLIAdapter, ShellAdapterOptions } from './adapters';\n\n// Types\nexport type {\n // Session types\n SessionStatus,\n MessageType,\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n\n // Adapter types\n ParsedOutput,\n LoginDetection,\n AuthRequiredMethod,\n AuthRequiredInfo,\n BlockingPromptType,\n BlockingPromptDetection,\n AutoResponseRule,\n BlockingPromptInfo,\n\n // Stall detection types\n StallClassification,\n\n // Manager types\n Logger,\n StopOptions,\n LogOptions,\n TerminalAttachment,\n PTYManagerConfig,\n\n // Factory types\n AdapterFactoryConfig,\n} from './types';\n\n// Event types\nexport type { PTYManagerEvents } from './pty-manager';\nexport type { PTYSessionEvents } from './pty-session';\nexport type {\n TaskCompletionTraceRecord,\n TaskCompletionTimelineStep,\n TaskCompletionTurnTimeline,\n TaskCompletionTimelineResult,\n BuildTimelineOptions,\n} from './task-completion-trace';\n\n// Bun compatibility layer\nexport {\n BunCompatiblePTYManager,\n createPTYManager,\n isBun,\n} from './bun-compat';\n\nexport type {\n WorkerSessionHandle,\n BunPTYManagerOptions,\n} from './bun-compat';\n","/**\n * PTY Manager\n *\n * Manages multiple PTY sessions for CLI tools.\n */\n\nimport { EventEmitter } from 'events';\nimport type { CLIAdapter } from './adapters/adapter-interface';\nimport { AdapterRegistry } from './adapters/adapter-registry';\nimport { PTYSession } from './pty-session';\nimport { consoleLogger } from './logger';\nimport type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AuthRequiredInfo,\n AutoResponseRule,\n StallClassification,\n StopOptions,\n LogOptions,\n TerminalAttachment,\n PTYManagerConfig,\n Logger,\n} from './types';\n\nexport interface PTYManagerEvents {\n session_started: (session: SessionHandle) => void;\n session_ready: (session: SessionHandle) => void;\n session_stopped: (session: SessionHandle, reason: string) => void;\n session_error: (session: SessionHandle, error: string) => void;\n login_required: (session: SessionHandle, instructions?: string, url?: string) => void;\n auth_required: (session: SessionHandle, info: AuthRequiredInfo) => void;\n blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n stall_detected: (session: SessionHandle, recentOutput: string, stallDurationMs: number) => void;\n session_status_changed: (session: SessionHandle) => void;\n task_complete: (session: SessionHandle) => void;\n}\n\n\n\nexport class PTYManager extends EventEmitter {\n private sessions: Map<string, PTYSession> = new Map();\n private outputLogs: Map<string, string[]> = new Map();\n private maxLogLines: number;\n private logger: Logger;\n public readonly adapters: AdapterRegistry;\n\n // Stall detection config\n private _stallDetectionEnabled: boolean;\n private _stallTimeoutMs: number;\n private _onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number\n ) => Promise<StallClassification | null>;\n\n constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\n this._stallDetectionEnabled = config.stallDetectionEnabled ?? false;\n this._stallTimeoutMs = config.stallTimeoutMs ?? 8000;\n this._onStallClassify = config.onStallClassify;\n }\n\n /**\n * Register a CLI adapter\n */\n registerAdapter(adapter: CLIAdapter): void {\n this.adapters.register(adapter);\n }\n\n /**\n * Spawn a new PTY session\n */\n async spawn(config: SpawnConfig): Promise<SessionHandle> {\n // Get adapter for this type\n const adapter = this.adapters.get(config.type);\n if (!adapter) {\n throw new Error(`No adapter found for type: ${config.type}. Registered adapters: ${this.adapters.list().join(', ') || 'none'}`);\n }\n\n // Check if ID already exists\n if (config.id && this.sessions.has(config.id)) {\n throw new Error(`Session with ID ${config.id} already exists`);\n }\n\n this.logger.info(\n { type: config.type, name: config.name },\n 'Spawning session'\n );\n\n // Create session\n const session = new PTYSession(\n adapter,\n config,\n this.logger,\n this._stallDetectionEnabled,\n this._stallTimeoutMs,\n );\n\n // Set up event forwarding\n this.setupSessionEvents(session);\n\n // Store session\n this.sessions.set(session.id, session);\n this.outputLogs.set(session.id, []);\n\n // Start the session\n await session.start();\n\n const handle = session.toHandle();\n this.emit('session_started', handle);\n\n return handle;\n }\n\n /**\n * Set up event handlers for a session\n */\n private setupSessionEvents(session: PTYSession): void {\n session.on('output', (data: string) => {\n // Store in log buffer\n const logs = this.outputLogs.get(session.id) || [];\n const lines = data.split('\\n');\n logs.push(...lines);\n\n // Trim to max lines\n while (logs.length > this.maxLogLines) {\n logs.shift();\n }\n this.outputLogs.set(session.id, logs);\n });\n\n session.on('ready', () => {\n this.emit('session_ready', session.toHandle());\n });\n\n session.on('login_required', (instructions?: string, url?: string) => {\n this.emit('login_required', session.toHandle(), instructions, url);\n });\n\n session.on('auth_required', (info: AuthRequiredInfo) => {\n this.emit('auth_required', session.toHandle(), info);\n });\n\n session.on('blocking_prompt', (promptInfo: BlockingPromptInfo, autoResponded: boolean) => {\n this.emit('blocking_prompt', session.toHandle(), promptInfo, autoResponded);\n });\n\n session.on('message', (message: SessionMessage) => {\n this.emit('message', message);\n });\n\n session.on('question', (question: string) => {\n this.emit('question', session.toHandle(), question);\n });\n\n session.on('exit', (code: number) => {\n const reason = code === 0 ? 'normal exit' : `exit code ${code}`;\n this.emit('session_stopped', session.toHandle(), reason);\n });\n\n session.on('error', (error: Error) => {\n this.emit('session_error', session.toHandle(), error.message);\n });\n\n session.on('status_changed', () => {\n // Refresh the handle so the parent sees the updated status\n this.emit('session_status_changed', session.toHandle());\n });\n\n session.on('task_complete', () => {\n this.emit('task_complete', session.toHandle());\n });\n\n session.on('stall_detected', (recentOutput: string, stallDurationMs: number) => {\n const handle = session.toHandle();\n this.emit('stall_detected', handle, recentOutput, stallDurationMs);\n\n // Call external classifier if configured\n if (this._onStallClassify) {\n // Sanitize output before passing to LLM classifier to mitigate prompt injection.\n // Truncate to 1500 chars and strip sequences that could be used to manipulate the classifier.\n const sanitized = recentOutput\n .slice(-1500)\n .replace(/\\b(ignore|disregard|forget)\\s+(all\\s+)?(previous|above|prior)\\s+(instructions?|prompts?|rules?)\\b/gi, '[REDACTED]')\n .replace(/\\b(you\\s+are|act\\s+as|pretend\\s+to\\s+be|you\\s+must|system\\s*:)\\b/gi, '[REDACTED]');\n this._onStallClassify(session.id, sanitized, stallDurationMs)\n .then((classification) => {\n session.handleStallClassification(classification);\n })\n .catch((err) => {\n this.logger.error(\n { sessionId: session.id, error: err },\n 'Stall classification callback failed'\n );\n // Reset timer so detection continues\n session.handleStallClassification(null);\n });\n }\n });\n }\n\n /**\n * Stop a session\n */\n async stop(sessionId: string, options?: StopOptions): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n this.logger.info({ sessionId, force: options?.force }, 'Stopping session');\n\n const timeout = options?.timeout || 5000;\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n // Force kill if graceful shutdown times out\n session.kill('SIGKILL');\n resolve();\n }, timeout);\n\n session.once('exit', () => {\n clearTimeout(timer);\n session.removeAllListeners();\n this.sessions.delete(sessionId);\n this.outputLogs.delete(sessionId);\n resolve();\n });\n\n // Send graceful signal\n session.kill(options?.force ? 'SIGKILL' : 'SIGTERM');\n });\n }\n\n /**\n * Stop all sessions\n */\n async stopAll(options?: StopOptions): Promise<void> {\n const stopPromises = Array.from(this.sessions.keys()).map((id) =>\n this.stop(id, options).catch((err) => {\n this.logger.warn({ sessionId: id, error: err }, 'Error stopping session');\n })\n );\n\n await Promise.all(stopPromises);\n }\n\n /**\n * Get a session by ID\n */\n get(sessionId: string): SessionHandle | null {\n const session = this.sessions.get(sessionId);\n return session ? session.toHandle() : null;\n }\n\n /**\n * List all sessions\n */\n list(filter?: SessionFilter): SessionHandle[] {\n const handles: SessionHandle[] = [];\n\n for (const session of this.sessions.values()) {\n const handle = session.toHandle();\n\n // Apply filters\n if (filter) {\n if (filter.status) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!statuses.includes(handle.status)) continue;\n }\n\n if (filter.type) {\n const types = Array.isArray(filter.type) ? filter.type : [filter.type];\n if (!types.includes(handle.type)) continue;\n }\n }\n\n handles.push(handle);\n }\n\n return handles;\n }\n\n /**\n * Send a message to a session\n */\n send(sessionId: string, message: string): SessionMessage {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n return session.send(message);\n }\n\n /**\n * Get logs for a session\n */\n async *logs(sessionId: string, options?: LogOptions): AsyncIterable<string> {\n const logBuffer = this.outputLogs.get(sessionId);\n if (!logBuffer) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const lines = options?.tail\n ? logBuffer.slice(-options.tail)\n : logBuffer;\n\n for (const line of lines) {\n yield line;\n }\n }\n\n /**\n * Get metrics for a session\n */\n metrics(sessionId: string): { uptime?: number; messageCount?: number } | null {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return null;\n }\n\n const handle = session.toHandle();\n const uptime = handle.startedAt\n ? Math.floor((Date.now() - handle.startedAt.getTime()) / 1000)\n : undefined;\n\n return { uptime };\n }\n\n /**\n * Shutdown manager and stop all sessions\n */\n async shutdown(): Promise<void> {\n this.logger.info({ count: this.sessions.size }, 'Shutting down all sessions');\n\n await this.stopAll({ timeout: 3000 });\n\n this.sessions.clear();\n this.outputLogs.clear();\n }\n\n /**\n * Get count of sessions by status\n */\n getStatusCounts(): Record<SessionStatus, number> {\n const counts: Record<SessionStatus, number> = {\n pending: 0,\n starting: 0,\n authenticating: 0,\n ready: 0,\n busy: 0,\n stopping: 0,\n stopped: 0,\n error: 0,\n };\n\n for (const session of this.sessions.values()) {\n counts[session.status]++;\n }\n\n return counts;\n }\n\n /**\n * Attach to a session's terminal for raw I/O streaming\n */\n attachTerminal(sessionId: string): TerminalAttachment | null {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return null;\n }\n\n return {\n /**\n * Subscribe to raw terminal output\n * Returns an unsubscribe function\n */\n onData: (callback: (data: string) => void) => {\n session.on('output', callback);\n return () => session.off('output', callback);\n },\n\n /**\n * Write raw data to terminal (no formatting applied)\n */\n write: (data: string) => {\n session.writeRaw(data);\n },\n\n /**\n * Resize the terminal\n */\n resize: (cols: number, rows: number) => {\n session.resize(cols, rows);\n },\n };\n }\n\n /**\n * Check if a session exists\n */\n has(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n /**\n * Get the underlying PTYSession (for advanced use)\n */\n getSession(sessionId: string): PTYSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Stall Detection Configuration\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Configure stall detection at runtime.\n * Affects newly spawned sessions only — existing sessions keep their config.\n */\n configureStallDetection(\n enabled: boolean,\n timeoutMs?: number,\n classify?: (sessionId: string, recentOutput: string, stallDurationMs: number) => Promise<StallClassification | null>,\n ): void {\n this._stallDetectionEnabled = enabled;\n if (timeoutMs !== undefined) {\n this._stallTimeoutMs = timeoutMs;\n }\n if (classify !== undefined) {\n this._onStallClassify = classify;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Add an auto-response rule to a session.\n * Session rules are checked before adapter rules.\n */\n addAutoResponseRule(sessionId: string, rule: AutoResponseRule): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.addAutoResponseRule(rule);\n }\n\n /**\n * Remove an auto-response rule from a session by pattern.\n * Returns true if a rule was removed.\n */\n removeAutoResponseRule(sessionId: string, pattern: RegExp): boolean {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n return session.removeAutoResponseRule(pattern);\n }\n\n /**\n * Set all auto-response rules for a session, replacing existing ones.\n */\n setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.setAutoResponseRules(rules);\n }\n\n /**\n * Get all auto-response rules for a session.\n */\n getAutoResponseRules(sessionId: string): AutoResponseRule[] {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n return session.getAutoResponseRules();\n }\n\n /**\n * Clear all auto-response rules for a session.\n */\n clearAutoResponseRules(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.clearAutoResponseRules();\n }\n}\n","/**\n * Adapter Registry\n *\n * Registry for managing CLI adapters.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\n\n/**\n * Registry of available CLI adapters\n */\nexport class AdapterRegistry {\n private adapters: Map<string, CLIAdapter> = new Map();\n\n /**\n * Register an adapter\n */\n register(adapter: CLIAdapter): void {\n this.adapters.set(adapter.adapterType, adapter);\n }\n\n /**\n * Get adapter for type\n */\n get(adapterType: string): CLIAdapter | undefined {\n return this.adapters.get(adapterType);\n }\n\n /**\n * Check if adapter exists for type\n */\n has(adapterType: string): boolean {\n return this.adapters.has(adapterType);\n }\n\n /**\n * Unregister an adapter\n */\n unregister(adapterType: string): boolean {\n return this.adapters.delete(adapterType);\n }\n\n /**\n * List all registered adapter types\n */\n list(): string[] {\n return Array.from(this.adapters.keys());\n }\n\n /**\n * Get all adapters\n */\n all(): CLIAdapter[] {\n return Array.from(this.adapters.values());\n }\n\n /**\n * Clear all adapters\n */\n clear(): void {\n this.adapters.clear();\n }\n}\n","/**\n * PTY Session\n *\n * Manages a single pseudo-terminal session for a CLI tool.\n */\n\nimport { EventEmitter } from 'events';\nimport { randomUUID } from 'crypto';\nimport type * as ptyModule from 'node-pty';\nimport type { CLIAdapter } from './adapters/adapter-interface';\nimport type {\n SpawnConfig,\n SessionStatus,\n SessionHandle,\n SessionMessage,\n BlockingPromptInfo,\n AuthRequiredInfo,\n LoginDetection,\n AutoResponseRule,\n StallClassification,\n Logger,\n} from './types';\nimport { consoleLogger } from './logger';\n\n// Lazy-load node-pty to avoid issues in environments where it's not installed\nlet ptyCache: typeof ptyModule | null = null;\nfunction loadPty(): typeof ptyModule {\n if (!ptyCache) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n ptyCache = require('node-pty') as typeof ptyModule;\n } catch {\n throw new Error(\n 'node-pty is required but not installed. Run: npm install node-pty'\n );\n }\n }\n return ptyCache!;\n}\n\nexport interface PTYSessionEvents {\n output: (data: string) => void;\n ready: () => void;\n login_required: (instructions?: string, url?: string) => void;\n auth_required: (info: AuthRequiredInfo) => void;\n blocking_prompt: (prompt: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (question: string) => void;\n exit: (code: number) => void;\n error: (error: Error) => void;\n stall_detected: (recentOutput: string, stallDurationMs: number) => void;\n status_changed: (status: SessionStatus) => void;\n task_complete: () => void;\n}\n\n\n\n/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Special key mappings to escape sequences\n *\n * Modifier codes for arrows/function keys:\n * 2 = Shift, 3 = Alt, 4 = Shift+Alt, 5 = Ctrl, 6 = Ctrl+Shift, 7 = Ctrl+Alt, 8 = Ctrl+Alt+Shift\n */\nexport const SPECIAL_KEYS: Record<string, string> = {\n // Control keys (Ctrl+letter = ASCII control code)\n 'ctrl+a': '\\x01',\n 'ctrl+b': '\\x02',\n 'ctrl+c': '\\x03',\n 'ctrl+d': '\\x04',\n 'ctrl+e': '\\x05',\n 'ctrl+f': '\\x06',\n 'ctrl+g': '\\x07',\n 'ctrl+h': '\\x08',\n 'ctrl+i': '\\x09',\n 'ctrl+j': '\\x0a',\n 'ctrl+k': '\\x0b',\n 'ctrl+l': '\\x0c',\n 'ctrl+m': '\\x0d',\n 'ctrl+n': '\\x0e',\n 'ctrl+o': '\\x0f',\n 'ctrl+p': '\\x10',\n 'ctrl+q': '\\x11',\n 'ctrl+r': '\\x12',\n 'ctrl+s': '\\x13',\n 'ctrl+t': '\\x14',\n 'ctrl+u': '\\x15',\n 'ctrl+v': '\\x16',\n 'ctrl+w': '\\x17',\n 'ctrl+x': '\\x18',\n 'ctrl+y': '\\x19',\n 'ctrl+z': '\\x1a',\n 'ctrl+[': '\\x1b',\n 'ctrl+\\\\': '\\x1c',\n 'ctrl+]': '\\x1d',\n 'ctrl+^': '\\x1e',\n 'ctrl+_': '\\x1f',\n\n // Alt+letter (Meta key = ESC + letter)\n 'alt+a': '\\x1ba', 'alt+b': '\\x1bb', 'alt+c': '\\x1bc', 'alt+d': '\\x1bd',\n 'alt+e': '\\x1be', 'alt+f': '\\x1bf', 'alt+g': '\\x1bg', 'alt+h': '\\x1bh',\n 'alt+i': '\\x1bi', 'alt+j': '\\x1bj', 'alt+k': '\\x1bk', 'alt+l': '\\x1bl',\n 'alt+m': '\\x1bm', 'alt+n': '\\x1bn', 'alt+o': '\\x1bo', 'alt+p': '\\x1bp',\n 'alt+q': '\\x1bq', 'alt+r': '\\x1br', 'alt+s': '\\x1bs', 'alt+t': '\\x1bt',\n 'alt+u': '\\x1bu', 'alt+v': '\\x1bv', 'alt+w': '\\x1bw', 'alt+x': '\\x1bx',\n 'alt+y': '\\x1by', 'alt+z': '\\x1bz',\n 'alt+backspace': '\\x1b\\x7f', // Delete word backward\n\n // Navigation - plain\n 'up': '\\x1b[A',\n 'down': '\\x1b[B',\n 'right': '\\x1b[C',\n 'left': '\\x1b[D',\n 'home': '\\x1b[H',\n 'end': '\\x1b[F',\n 'pageup': '\\x1b[5~',\n 'pagedown': '\\x1b[6~',\n\n // Navigation - with Shift (modifier 2)\n 'shift+up': '\\x1b[1;2A',\n 'shift+down': '\\x1b[1;2B',\n 'shift+right': '\\x1b[1;2C',\n 'shift+left': '\\x1b[1;2D',\n 'shift+home': '\\x1b[1;2H',\n 'shift+end': '\\x1b[1;2F',\n 'shift+pageup': '\\x1b[5;2~',\n 'shift+pagedown': '\\x1b[6;2~',\n\n // Navigation - with Alt (modifier 3)\n 'alt+up': '\\x1b[1;3A',\n 'alt+down': '\\x1b[1;3B',\n 'alt+right': '\\x1b[1;3C', // Forward word\n 'alt+left': '\\x1b[1;3D', // Backward word\n\n // Navigation - with Ctrl (modifier 5)\n 'ctrl+up': '\\x1b[1;5A',\n 'ctrl+down': '\\x1b[1;5B',\n 'ctrl+right': '\\x1b[1;5C', // Forward word\n 'ctrl+left': '\\x1b[1;5D', // Backward word\n 'ctrl+home': '\\x1b[1;5H',\n 'ctrl+end': '\\x1b[1;5F',\n\n // Navigation - with Ctrl+Shift (modifier 6) - select word\n 'ctrl+shift+up': '\\x1b[1;6A',\n 'ctrl+shift+down': '\\x1b[1;6B',\n 'ctrl+shift+right': '\\x1b[1;6C',\n 'ctrl+shift+left': '\\x1b[1;6D',\n 'ctrl+shift+home': '\\x1b[1;6H',\n 'ctrl+shift+end': '\\x1b[1;6F',\n\n // Navigation - with Shift+Alt (modifier 4)\n 'shift+alt+up': '\\x1b[1;4A',\n 'shift+alt+down': '\\x1b[1;4B',\n 'shift+alt+right': '\\x1b[1;4C',\n 'shift+alt+left': '\\x1b[1;4D',\n\n // Editing\n 'enter': '\\r',\n 'return': '\\r',\n 'tab': '\\t',\n 'shift+tab': '\\x1b[Z', // Reverse tab\n 'backspace': '\\x7f',\n 'delete': '\\x1b[3~',\n 'shift+delete': '\\x1b[3;2~',\n 'ctrl+delete': '\\x1b[3;5~', // Delete word forward\n 'insert': '\\x1b[2~',\n 'escape': '\\x1b',\n 'esc': '\\x1b',\n 'space': ' ',\n\n // Function keys - plain\n 'f1': '\\x1bOP',\n 'f2': '\\x1bOQ',\n 'f3': '\\x1bOR',\n 'f4': '\\x1bOS',\n 'f5': '\\x1b[15~',\n 'f6': '\\x1b[17~',\n 'f7': '\\x1b[18~',\n 'f8': '\\x1b[19~',\n 'f9': '\\x1b[20~',\n 'f10': '\\x1b[21~',\n 'f11': '\\x1b[23~',\n 'f12': '\\x1b[24~',\n\n // Function keys - with Shift (modifier 2)\n 'shift+f1': '\\x1b[1;2P',\n 'shift+f2': '\\x1b[1;2Q',\n 'shift+f3': '\\x1b[1;2R',\n 'shift+f4': '\\x1b[1;2S',\n 'shift+f5': '\\x1b[15;2~',\n 'shift+f6': '\\x1b[17;2~',\n 'shift+f7': '\\x1b[18;2~',\n 'shift+f8': '\\x1b[19;2~',\n 'shift+f9': '\\x1b[20;2~',\n 'shift+f10': '\\x1b[21;2~',\n 'shift+f11': '\\x1b[23;2~',\n 'shift+f12': '\\x1b[24;2~',\n\n // Function keys - with Ctrl (modifier 5)\n 'ctrl+f1': '\\x1b[1;5P',\n 'ctrl+f2': '\\x1b[1;5Q',\n 'ctrl+f3': '\\x1b[1;5R',\n 'ctrl+f4': '\\x1b[1;5S',\n 'ctrl+f5': '\\x1b[15;5~',\n 'ctrl+f6': '\\x1b[17;5~',\n 'ctrl+f7': '\\x1b[18;5~',\n 'ctrl+f8': '\\x1b[19;5~',\n 'ctrl+f9': '\\x1b[20;5~',\n 'ctrl+f10': '\\x1b[21;5~',\n 'ctrl+f11': '\\x1b[23;5~',\n 'ctrl+f12': '\\x1b[24;5~',\n};\n\n/**\n * Bracketed paste mode escape sequences\n */\nconst BRACKETED_PASTE_START = '\\x1b[200~';\nconst BRACKETED_PASTE_END = '\\x1b[201~';\n\nexport class PTYSession extends EventEmitter {\n private ptyProcess: ptyModule.IPty | null = null;\n private outputBuffer: string = '';\n private _status: SessionStatus = 'pending';\n private _startedAt: Date | null = null;\n private _lastActivityAt: Date | null = null;\n private messageCounter: number = 0;\n private logger: Logger;\n private sessionRules: AutoResponseRule[] = [];\n private _firedOnceRules: Set<string> = new Set();\n private _lastBlockingPromptHash: string | null = null;\n private _ruleOverrides: Map<string, Partial<AutoResponseRule>> = new Map();\n private _disabledRulePatterns: Set<string> = new Set();\n\n // Stall detection\n private _stallTimer: ReturnType<typeof setTimeout> | null = null;\n private _stallTimeoutMs: number;\n private _stallDetectionEnabled: boolean;\n private _lastStallHash: string | null = null;\n private _stallStartedAt: number | null = null;\n private _lastContentHash: string | null = null;\n private _stallBackoffMs: number = 0; // Initialized in constructor from _stallTimeoutMs\n private static readonly MAX_STALL_BACKOFF_MS = 30_000;\n private _stallEmissionCount: number = 0;\n private static readonly MAX_STALL_EMISSIONS = 5;\n\n // Task completion detection (idle detection when busy)\n private _taskCompleteTimer: ReturnType<typeof setTimeout> | null = null;\n private _taskCompletePending = false;\n private static readonly TASK_COMPLETE_DEBOUNCE_MS = 1500;\n\n // Ready detection settle delay — defers session_ready until output goes quiet\n private _readySettleTimer: ReturnType<typeof setTimeout> | null = null;\n private _readySettlePending = false;\n\n // Deferred output processing — prevents node-pty's synchronous data\n // delivery from starving the event loop (timers, I/O callbacks, etc.)\n private _processScheduled = false;\n\n // Output buffer cap — prevents unbounded growth during long tasks\n private static readonly MAX_OUTPUT_BUFFER = 100_000; // 100 KB\n\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger,\n stallDetectionEnabled?: boolean,\n defaultStallTimeoutMs?: number,\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\n this._stallDetectionEnabled = stallDetectionEnabled ?? false;\n this._stallTimeoutMs = config.stallTimeoutMs ?? defaultStallTimeoutMs ?? 8000;\n this._stallBackoffMs = this._stallTimeoutMs;\n\n // Process rule overrides from spawn config\n if (config.ruleOverrides) {\n for (const [key, value] of Object.entries(config.ruleOverrides)) {\n if (value === null) {\n this._disabledRulePatterns.add(key);\n } else {\n this._ruleOverrides.set(key, value);\n }\n }\n }\n }\n\n get status(): SessionStatus {\n return this._status;\n }\n\n get pid(): number | undefined {\n return this.ptyProcess?.pid;\n }\n\n get startedAt(): Date | undefined {\n return this._startedAt ?? undefined;\n }\n\n get lastActivityAt(): Date | undefined {\n return this._lastActivityAt ?? undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Add an auto-response rule to this session.\n * Session rules are checked before adapter rules.\n */\n addAutoResponseRule(rule: AutoResponseRule): void {\n // Check for duplicate pattern\n const existingIndex = this.sessionRules.findIndex(\n (r) => r.pattern.source === rule.pattern.source && r.pattern.flags === rule.pattern.flags\n );\n\n if (existingIndex >= 0) {\n // Replace existing rule with same pattern\n this.sessionRules[existingIndex] = rule;\n this.logger.debug(\n { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },\n 'Replaced existing auto-response rule'\n );\n } else {\n this.sessionRules.push(rule);\n this.logger.debug(\n { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },\n 'Added auto-response rule'\n );\n }\n }\n\n /**\n * Remove an auto-response rule by pattern.\n * Returns true if a rule was removed.\n */\n removeAutoResponseRule(pattern: RegExp): boolean {\n const initialLength = this.sessionRules.length;\n this.sessionRules = this.sessionRules.filter(\n (r) => !(r.pattern.source === pattern.source && r.pattern.flags === pattern.flags)\n );\n\n const removed = this.sessionRules.length < initialLength;\n if (removed) {\n this.logger.debug(\n { sessionId: this.id, pattern: pattern.source },\n 'Removed auto-response rule'\n );\n }\n return removed;\n }\n\n /**\n * Set all session auto-response rules, replacing existing ones.\n */\n setAutoResponseRules(rules: AutoResponseRule[]): void {\n this.sessionRules = [...rules];\n this.logger.debug(\n { sessionId: this.id, count: rules.length },\n 'Set auto-response rules'\n );\n }\n\n /**\n * Get all session auto-response rules.\n */\n getAutoResponseRules(): AutoResponseRule[] {\n return [...this.sessionRules];\n }\n\n /**\n * Clear all session auto-response rules.\n */\n clearAutoResponseRules(): void {\n this.sessionRules = [];\n this.logger.debug({ sessionId: this.id }, 'Cleared auto-response rules');\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Stall Detection\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Start or reset the stall detection timer.\n * Active when status is \"busy\" or \"authenticating\" and stall detection is enabled.\n *\n * Content-based: hashes the ANSI-stripped buffer tail and only resets the\n * timer when visible content actually changes. This prevents TUI spinners\n * (which produce new ANSI sequences but no new visible text) from endlessly\n * resetting the timer.\n */\n private resetStallTimer(): void {\n if (!this._stallDetectionEnabled || (this._status !== 'busy' && this._status !== 'authenticating')) {\n this.clearStallTimer();\n return;\n }\n\n // Strip the full buffer FIRST, then slice the tail of the normalized text.\n // Stripping before slicing ensures the 500-char window covers the same\n // visible content regardless of how many raw escape sequences surround it.\n // (Slicing raw first caused different cursor-positioning codes at the\n // truncation boundary to produce different stripped text each TUI redraw.)\n const stripped = this.stripAnsiForStall(this.outputBuffer).trim();\n const visible = this.stripAnsiForClassifier(this.outputBuffer).trim();\n const tail = stripped.slice(-500);\n const fallbackTail = visible.slice(-500);\n const hash = this.simpleHash(tail || fallbackTail);\n\n if (hash === this._lastContentHash) {\n // Content unchanged (e.g., spinner animation) — don't reset the timer\n return;\n }\n this._lastContentHash = hash;\n this._stallEmissionCount = 0;\n\n // Content changed — clear and restart the timer, reset backoff\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallStartedAt = Date.now();\n this._lastStallHash = null; // New content, reset dedup hash for emissions\n this._stallBackoffMs = this._stallTimeoutMs; // Reset backoff on new real content\n\n this._stallTimer = setTimeout(() => {\n this.onStallTimerFired();\n }, this._stallTimeoutMs);\n }\n\n /**\n * Clear the stall detection timer.\n */\n private clearStallTimer(): void {\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallStartedAt = null;\n this._lastContentHash = null;\n this._stallBackoffMs = this._stallTimeoutMs;\n this._stallEmissionCount = 0;\n }\n\n /**\n * Called when the stall timer fires (no output for stallTimeoutMs).\n */\n private onStallTimerFired(): void {\n if (this._status !== 'busy' && this._status !== 'authenticating') {\n return; // Status changed while timer was running\n }\n\n // Fast path: try adapter-level task completion detection first.\n // This must run BEFORE detectLoading because the buffer may contain\n // both stale loading patterns (e.g. \"esc to interrupt\" from the spinner)\n // and a completion signal (e.g. \"Baked for 2s\" + prompt). Task completion\n // is the more specific/certain signal and should take priority.\n if (this._status === 'busy' && this.adapter.detectTaskComplete?.(this.outputBuffer)) {\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('status_changed', 'ready');\n this.emit('task_complete');\n this.logger.info(\n { sessionId: this.id },\n 'Task complete (adapter fast-path) — agent returned to idle prompt'\n );\n return;\n }\n\n // Loading suppression: if the adapter detects an active loading indicator\n // (thinking spinner, \"esc to interrupt\", \"Reading N files\", etc.),\n // the agent is provably working — suppress stall detection and reschedule.\n if (this.adapter.detectLoading?.(this.outputBuffer)) {\n this.logger.debug(\n { sessionId: this.id },\n 'Loading pattern detected — suppressing stall emission'\n );\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n\n // Compute dedup hash from last 500 chars of outputBuffer\n const tail = this.outputBuffer.slice(-500);\n const hash = this.simpleHash(tail);\n\n if (hash === this._lastStallHash) {\n // Buffer tail unchanged since last stall emission — don't re-emit.\n // Schedule another check with current backoff.\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n this._lastStallHash = hash;\n\n this._stallEmissionCount++;\n if (this._stallEmissionCount > PTYSession.MAX_STALL_EMISSIONS) {\n this.logger.warn(\n { sessionId: this.id, count: this._stallEmissionCount },\n 'Max stall emissions reached — suspending stall detection for this task'\n );\n this.clearStallTimer();\n return;\n }\n\n // Compute recent output for classifier: last 2000 chars, ANSI-stripped\n // while preserving visible symbols/text used by TUI CLIs.\n const recentRaw = this.outputBuffer.slice(-2000);\n const recentOutput = this.stripAnsiForClassifier(recentRaw).trim();\n\n const stallDurationMs = this._stallStartedAt\n ? Date.now() - this._stallStartedAt\n : this._stallTimeoutMs;\n\n this.logger.debug(\n {\n sessionId: this.id,\n stallDurationMs,\n bufferTailLength: tail.length,\n recentOutputLength: recentOutput.length,\n recentOutputHash: this.simpleHash(recentOutput.slice(-500)),\n },\n 'Stall detected'\n );\n\n this.emit('stall_detected', recentOutput, stallDurationMs);\n\n // Schedule next check with current backoff\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n }\n\n /**\n * Promise-based delay helper.\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Simple string hash for deduplication.\n */\n private simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash |= 0;\n }\n return hash.toString(36);\n }\n\n private mapLoginTypeToAuthMethod(type: LoginDetection['type'] | undefined): AuthRequiredInfo['method'] {\n switch (type) {\n case 'api_key':\n return 'api_key';\n case 'device_code':\n return 'device_code';\n case 'oauth':\n case 'browser':\n return 'oauth_browser';\n default:\n return 'unknown';\n }\n }\n\n private extractDeviceCode(text: string): string | undefined {\n const stripped = this.stripAnsiForClassifier(text);\n const explicitMatch = stripped.match(\n /(?:one-time|one time|device)?\\s*code[:\\s]+([A-Z0-9]{3,}(?:-[A-Z0-9]{3,})+)/i\n );\n if (explicitMatch?.[1]) {\n return explicitMatch[1].toUpperCase();\n }\n\n if (!/code/i.test(stripped)) {\n return undefined;\n }\n const fallbackMatch = stripped.match(/\\b([A-Z0-9]{3,}(?:-[A-Z0-9]{3,})+)\\b/);\n return fallbackMatch?.[1]?.toUpperCase();\n }\n\n private getPromptSnippet(maxChars = 280): string | undefined {\n const normalized = this.stripAnsiForClassifier(this.outputBuffer)\n .replace(/\\s+/g, ' ')\n .trim();\n if (!normalized) {\n return undefined;\n }\n return normalized.length <= maxChars\n ? normalized\n : normalized.slice(-maxChars);\n }\n\n private emitAuthRequired(details: {\n type?: LoginDetection['type'];\n url?: string;\n deviceCode?: string;\n instructions?: string;\n }): void {\n const info: AuthRequiredInfo = {\n method: this.mapLoginTypeToAuthMethod(details.type),\n url: details.url,\n deviceCode: details.deviceCode ?? this.extractDeviceCode(this.outputBuffer),\n instructions: details.instructions,\n promptSnippet: this.getPromptSnippet(),\n };\n\n this.emit('auth_required', info);\n this.emit('login_required', info.instructions, info.url);\n }\n\n /**\n * Strip ANSI codes, cursor movement, box-drawing, and spinner characters.\n * Used for stall detection hashing and auto-response pattern matching.\n *\n * Cursor movement codes are replaced with spaces (not removed) to preserve\n * word boundaries — e.g. \"Do\\x1b[5Cyou\" becomes \"Do you\", not \"Doyou\".\n */\n private stripAnsiForStall(str: string): string {\n // Replace ALL cursor movement/positioning codes with a space to preserve word boundaries:\n // \\x1b[nC (forward), \\x1b[nD (back), \\x1b[nA (up), \\x1b[nB (down), \\x1b[nG (column)\n // \\x1b[n;mH and \\x1b[n;mf (absolute positioning)\n // \\x1b[nJ (erase display), \\x1b[nK (erase line) — also space to keep words apart\n // \\x1b[nd (vertical position), \\x1b[nE/nF (cursor next/prev line)\n let result = str.replace(/\\x1b\\[\\d*[CDABGdEF]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*(?:;\\d+)?[Hf]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*[JK]/g, ' ');\n\n // Strip OSC sequences (Operating System Command): \\x1b] ... BEL or \\x1b] ... ST\n // Used for hyperlinks, window titles, Kitty graphics. Payload text would pollute output.\n result = result.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n\n // Strip DCS sequences (Device Control String): \\x1bP ... ST\n result = result.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n\n // Strip remaining ANSI escape sequences (SGR, cursor show/hide, etc.)\n // eslint-disable-next-line no-control-regex\n result = result.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n\n // Strip bare control characters (backspace, bell, carriage return, etc.)\n // Preserves only \\x09 (tab) and \\x0a (newline).\n // eslint-disable-next-line no-control-regex\n result = result.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f]/g, '');\n\n // Normalize non-breaking spaces (NBSP \\xa0) to regular spaces\n result = result.replace(/\\xa0/g, ' ');\n\n // Strip TUI box-drawing, spinner, and decorative Unicode characters\n result = result.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆◇▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥]/g, ' ');\n\n // Normalize countdown/duration text (e.g., \"8m 17s\" → \"0s\") to prevent\n // TUI countdown timers from resetting the stall timer every second.\n result = result.replace(/\\d+[hms](?:\\s+\\d+[hms])*/g, '0s');\n\n // Collapse multiple spaces\n result = result.replace(/ {2,}/g, ' ');\n\n return result;\n }\n\n /**\n * Less-aggressive ANSI stripping for classifier context.\n * Preserves visible TUI symbols (e.g. ❯, ✻) and durations while removing\n * escape/control sequences so the classifier keeps useful evidence.\n */\n private stripAnsiForClassifier(str: string): string {\n let result = str.replace(/\\x1b\\[\\d*[CDABGdEF]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*(?:;\\d+)?[Hf]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*[JK]/g, ' ');\n\n // Strip OSC and DCS payloads\n result = result.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n result = result.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n\n // Strip remaining ANSI escape sequences\n // eslint-disable-next-line no-control-regex\n result = result.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n\n // Strip bare control chars except tab/newline\n // eslint-disable-next-line no-control-regex\n result = result.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f]/g, '');\n\n // Normalize NBSP and collapse spaces\n result = result.replace(/\\xa0/g, ' ');\n result = result.replace(/ {2,}/g, ' ');\n return result;\n }\n\n /**\n * Handle external stall classification result.\n * Called by the manager after onStallClassify resolves.\n */\n handleStallClassification(classification: StallClassification | null): void {\n // Guard against async race — session may no longer be busy/authenticating\n if (this._status !== 'busy' && this._status !== 'authenticating') {\n return;\n }\n\n if (!classification || classification.state === 'still_working') {\n // Exponential backoff — double the check interval (capped at 30s).\n // This avoids hammering the LLM classifier every few seconds when\n // the agent is legitimately working on a long task.\n this._stallBackoffMs = Math.min(\n this._stallBackoffMs * 2,\n PTYSession.MAX_STALL_BACKOFF_MS,\n );\n this.logger.debug(\n { sessionId: this.id, nextCheckMs: this._stallBackoffMs },\n 'Still working — backing off stall check interval'\n );\n\n // Force timer restart with backed-off interval, even if buffer\n // content hasn't changed.\n this._lastContentHash = null;\n this._lastStallHash = null; // Reset dedup hash so next fire can re-emit\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n\n switch (classification.state) {\n case 'waiting_for_input': {\n const promptInfo: BlockingPromptInfo = {\n type: 'stall_classified',\n prompt: classification.prompt,\n canAutoRespond: !!classification.suggestedResponse,\n };\n\n if (classification.suggestedResponse) {\n this.logger.info(\n { sessionId: this.id, response: classification.suggestedResponse },\n 'Auto-responding to stall-classified prompt'\n );\n const resp = classification.suggestedResponse;\n if (resp.startsWith('keys:')) {\n const keys = resp.slice(5).split(',').map(k => k.trim());\n this.sendKeySequence(keys);\n } else {\n this.writeRaw(resp + '\\r');\n }\n this.emit('blocking_prompt', promptInfo, true);\n this.outputBuffer = ''; // Prevent stale text from triggering false detections\n } else {\n this.emit('blocking_prompt', promptInfo, false);\n }\n break;\n }\n\n case 'task_complete':\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Stall classified as task_complete, transitioning to ready');\n break;\n\n case 'error':\n this.clearStallTimer();\n this.emit('error', new Error(classification.prompt || 'Stall classified as error'));\n break;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Task Completion Detection\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Schedule a task_complete transition after a debounce period.\n * Uses a settle pattern: each call resets the debounce timer instead of\n * being a no-op when already scheduled. This allows TUI agents that\n * continue rendering decorative output (status bar, update notices) after\n * the prompt to eventually settle, rather than having the timer cancelled\n * by every new data chunk. The callback re-verifies the task-complete\n * signal before transitioning, so stale triggers are safe.\n */\n private scheduleTaskComplete(): void {\n const wasPending = this._taskCompletePending;\n this.traceTaskCompletion('debounce_schedule', {\n wasPending,\n debounceMs: PTYSession.TASK_COMPLETE_DEBOUNCE_MS,\n });\n\n if (this._taskCompleteTimer) {\n clearTimeout(this._taskCompleteTimer);\n }\n this._taskCompletePending = true;\n\n this._taskCompleteTimer = setTimeout(() => {\n this._taskCompleteTimer = null;\n this._taskCompletePending = false;\n\n const signal = this.isTaskCompleteSignal(this.outputBuffer);\n this.traceTaskCompletion('debounce_fire', { signal });\n\n // Re-check: still busy and task-complete signal still present?\n if (this._status !== 'busy') {\n this.traceTaskCompletion('debounce_reject_status', { signal });\n return;\n }\n if (!signal) {\n this.traceTaskCompletion('debounce_reject_signal', { signal });\n return;\n }\n\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('status_changed', 'ready');\n this.emit('task_complete');\n this.traceTaskCompletion('transition_ready', { signal: true });\n this.logger.info({ sessionId: this.id }, 'Task complete — agent returned to idle prompt');\n }, PTYSession.TASK_COMPLETE_DEBOUNCE_MS);\n }\n\n /**\n * Adapter-level task completion check with compatibility fallback.\n * Prefer detectTaskComplete() because detectReady() may be broad for TUIs.\n */\n private isTaskCompleteSignal(output: string): boolean {\n if (this.adapter.detectTaskComplete) {\n return this.adapter.detectTaskComplete(output);\n }\n return this.adapter.detectReady(output);\n }\n\n /**\n * Claude-oriented task completion traces for PTY debugging.\n * Disabled by default; enable via config.traceTaskCompletion.\n */\n private traceTaskCompletion(\n event: string,\n ctx: Partial<{\n signal: boolean;\n wasPending: boolean;\n debounceMs: number;\n }> = {},\n ): void {\n if (!this.shouldTraceTaskCompletion()) return;\n\n const output = this.outputBuffer;\n const detectTaskComplete = this.adapter.detectTaskComplete\n ? this.adapter.detectTaskComplete(output)\n : undefined;\n const detectReady = this.adapter.detectReady(output);\n const detectLoading = this.adapter.detectLoading\n ? this.adapter.detectLoading(output)\n : undefined;\n const normalizedTail = this.stripAnsiForStall(output.slice(-280));\n\n this.logger.debug(\n {\n sessionId: this.id,\n adapterType: this.adapter.adapterType,\n event,\n status: this._status,\n taskCompletePending: this._taskCompletePending,\n signal: ctx.signal,\n wasPending: ctx.wasPending,\n debounceMs: ctx.debounceMs,\n detectTaskComplete,\n detectReady,\n detectLoading,\n tailHash: this.simpleHash(normalizedTail),\n tailSnippet: normalizedTail.slice(-140),\n },\n 'Task completion trace'\n );\n }\n\n private shouldTraceTaskCompletion(): boolean {\n return this.config.traceTaskCompletion === true;\n }\n\n /**\n * Cancel a pending task_complete timer (new output arrived that\n * doesn't match the idle prompt, so the agent is still working).\n */\n private cancelTaskComplete(): void {\n if (this._taskCompleteTimer) {\n clearTimeout(this._taskCompleteTimer);\n this._taskCompleteTimer = null;\n }\n this._taskCompletePending = false;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Ready Detection Settle Delay\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Schedule or reset the ready-settle timer.\n * Defers emitting session_ready until output goes quiet for readySettleMs\n * after detectReady first matches. This prevents sending input while\n * TUI agents are still rendering (status bar, shortcuts, update notices).\n */\n private scheduleReadySettle(): void {\n this._readySettlePending = true;\n if (this._readySettleTimer) {\n clearTimeout(this._readySettleTimer);\n }\n const settleMs = this.config.readySettleMs ?? this.adapter.readySettleMs ?? 100;\n this._readySettleTimer = setTimeout(() => {\n this._readySettleTimer = null;\n this._readySettlePending = false;\n // Re-verify state and ready indicator\n if (this._status !== 'starting' && this._status !== 'authenticating') return;\n if (!this.adapter.detectReady(this.outputBuffer)) return;\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready (after settle)');\n }, settleMs);\n }\n\n /**\n * Cancel a pending ready-settle timer (ready indicator disappeared\n * or session status changed).\n */\n private cancelReadySettle(): void {\n if (this._readySettleTimer) {\n clearTimeout(this._readySettleTimer);\n this._readySettleTimer = null;\n }\n this._readySettlePending = false;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Start the PTY session\n */\n async start(): Promise<void> {\n if (this.ptyProcess) {\n throw new Error('Session already started');\n }\n\n const nodePty = loadPty();\n\n this._status = 'starting';\n this._startedAt = new Date();\n\n const command = this.adapter.getCommand();\n const args = this.adapter.getArgs(this.config);\n const adapterEnv = this.adapter.getEnv(this.config);\n\n const env = {\n ...process.env,\n ...adapterEnv,\n ...this.config.env,\n // Force terminal settings\n TERM: 'xterm-256color',\n COLORTERM: 'truecolor',\n };\n\n this.logger.info(\n { sessionId: this.id, command, args: args.join(' ') },\n 'Starting PTY session'\n );\n\n try {\n this.ptyProcess = nodePty.spawn(command, args, {\n name: 'xterm-256color',\n cols: this.config.cols || 120,\n rows: this.config.rows || 40,\n cwd: this.config.workdir || process.cwd(),\n env: env as Record<string, string>,\n });\n\n this.setupEventHandlers();\n\n this.logger.info(\n { sessionId: this.id, pid: this.ptyProcess.pid },\n 'PTY session started'\n );\n } catch (error) {\n this._status = 'error';\n this.logger.error(\n { sessionId: this.id, error },\n 'Failed to start PTY session'\n );\n throw error;\n }\n }\n\n /**\n * Set up event handlers for the PTY\n */\n private setupEventHandlers(): void {\n if (!this.ptyProcess) return;\n\n this.ptyProcess.onData((data) => {\n this._lastActivityAt = new Date();\n this.outputBuffer += data;\n\n // Cap the buffer to prevent unbounded growth during long tasks.\n // Detection only ever inspects the tail, so trimming is safe.\n if (this.outputBuffer.length > PTYSession.MAX_OUTPUT_BUFFER) {\n this.outputBuffer = this.outputBuffer.slice(-PTYSession.MAX_OUTPUT_BUFFER);\n }\n\n // Emit raw output immediately (callers may need it for real-time display)\n this.emit('output', data);\n\n // Defer all heavy detection work to the next event-loop tick.\n // node-pty delivers data synchronously from its native read loop;\n // running regex-heavy detection inline can starve the event loop\n // and prevent timers (stall detection, task_complete debounce)\n // from firing — especially on macOS ARM64 where the PTY read can\n // hold the libuv poll phase.\n if (!this._processScheduled) {\n this._processScheduled = true;\n setImmediate(() => {\n this._processScheduled = false;\n this.processOutputBuffer();\n });\n }\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\n this.clearStallTimer();\n this.logger.info(\n { sessionId: this.id, exitCode, signal },\n 'PTY session exited'\n );\n this.emit('exit', exitCode);\n });\n }\n\n /**\n * Process the accumulated output buffer.\n * Called via setImmediate() from the onData handler so that heavy regex\n * work runs in its own event-loop tick, not inside node-pty's native callback.\n */\n private processOutputBuffer(): void {\n // Reset stall timer on any new output while busy or authenticating\n if (this._status === 'busy' || this._status === 'authenticating') {\n this.resetStallTimer();\n }\n\n // If a ready-settle is pending, reset the timer on new data instead of\n // re-running all detection. If the ready indicator disappears, cancel.\n if (this._readySettlePending) {\n if (\n (this._status === 'starting' || this._status === 'authenticating') &&\n this.adapter.detectReady(this.outputBuffer)\n ) {\n this.scheduleReadySettle();\n } else {\n this.cancelReadySettle();\n }\n return;\n }\n\n // Ready detection — check FIRST, before blocking prompt detection.\n // After an auto-response (e.g. trust prompt), the buffer may contain\n // leftover prompt text that would falsely trigger detectBlockingPrompt\n // and block detectReady from ever running. Adapter detectReady\n // implementations have negative guards for trust/auth prompts, so\n // this is safe — it won't prematurely mark the session as ready.\n if (\n (this._status === 'starting' || this._status === 'authenticating') &&\n this.adapter.detectReady(this.outputBuffer)\n ) {\n this.scheduleReadySettle();\n return;\n }\n\n // Task completion detection — when busy and the agent returns to idle.\n // Uses a settle pattern: once triggered, the debounce timer resets on each\n // new data chunk instead of being cancelled. The callback re-verifies\n // the task-complete signal before transitioning, so stale triggers are safe.\n if (this._status === 'busy') {\n const signal = this.isTaskCompleteSignal(this.outputBuffer);\n if (this._taskCompletePending || signal) {\n this.traceTaskCompletion('busy_signal', { signal });\n this.scheduleTaskComplete();\n }\n // No else/cancel — timer self-validates on fire\n }\n\n // Auto-response / blocking prompt detection — runs after detectReady.\n // Handles trust confirmations, permission prompts, apply changes, etc.\n // throughout the entire session lifecycle.\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Login detection — only during startup/auth (not after ready/busy)\n if (this._status !== 'ready' && this._status !== 'busy') {\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.clearStallTimer();\n this.emitAuthRequired({\n type: loginDetection.type,\n url: loginDetection.url,\n deviceCode: loginDetection.deviceCode,\n instructions: loginDetection.instructions,\n });\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.clearStallTimer();\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message only when ready.\n // Parsing clears outputBuffer; doing this while busy can starve task-complete\n // and stall detection of evidence during heavy TUI rendering.\n if (this._status === 'ready') {\n this.tryParseOutput();\n }\n }\n\n /**\n * Detect blocking prompts and handle them with auto-responses or user notification.\n * Deduplicates emissions - won't re-emit the same blocking prompt repeatedly.\n */\n private detectAndHandleBlockingPrompt(): boolean {\n // First, check adapter's auto-response rules\n const autoHandled = this.tryAutoResponse();\n if (autoHandled) {\n return true;\n }\n\n // Then check the adapter's detectBlockingPrompt method\n if (this.adapter.detectBlockingPrompt) {\n const detection = this.adapter.detectBlockingPrompt(this.outputBuffer);\n\n if (detection.detected) {\n // Deduplicate: don't re-emit the same blocking prompt\n const promptHash = `${detection.type}:${detection.prompt || ''}`;\n if (promptHash === this._lastBlockingPromptHash) {\n // Still blocked by same prompt, but don't spam events\n return true;\n }\n this._lastBlockingPromptHash = promptHash;\n\n const promptInfo: BlockingPromptInfo = {\n type: detection.type || 'unknown',\n prompt: detection.prompt,\n options: detection.options,\n canAutoRespond: detection.canAutoRespond || false,\n instructions: detection.instructions,\n url: detection.url,\n };\n\n // If we can auto-respond and have a suggested response, do it\n if (detection.canAutoRespond && detection.suggestedResponse && !this.config.skipAdapterAutoResponse) {\n this.logger.info(\n {\n sessionId: this.id,\n promptType: detection.type,\n response: detection.suggestedResponse,\n },\n 'Auto-responding to blocking prompt'\n );\n\n const resp = detection.suggestedResponse;\n if (resp.startsWith('keys:')) {\n const keys = resp.slice(5).split(',').map(k => k.trim());\n this.sendKeySequence(keys);\n } else {\n this.writeRaw(resp + '\\r');\n }\n this._lastBlockingPromptHash = null; // Clear after auto-response\n this.outputBuffer = ''; // Prevent stale text from triggering false detections\n this.emit('blocking_prompt', promptInfo, true);\n return true;\n }\n\n // Otherwise, notify that user intervention is needed\n if (detection.type === 'login') {\n this._status = 'authenticating';\n // Surface login prompts through the dedicated auth event so callers\n // can open OAuth/device-code URLs without parsing blocking_prompt.\n const inferred = this.adapter.detectLogin(this.outputBuffer);\n this.emitAuthRequired({\n type: inferred.required ? inferred.type : undefined,\n url: detection.url ?? inferred.url,\n deviceCode: inferred.required ? inferred.deviceCode : undefined,\n instructions: detection.instructions ?? inferred.instructions,\n });\n }\n\n this.logger.warn(\n {\n sessionId: this.id,\n promptType: detection.type,\n prompt: detection.prompt,\n },\n 'Blocking prompt requires user intervention'\n );\n\n this.emit('blocking_prompt', promptInfo, false);\n return true;\n } else {\n // No blocking prompt detected - clear the hash\n this._lastBlockingPromptHash = null;\n }\n }\n\n return false;\n }\n\n /**\n * Try to match and apply auto-response rules.\n * Session rules are checked first, then adapter rules.\n */\n private tryAutoResponse(): boolean {\n // Combine session rules (higher priority) with adapter rules (filtered/merged by overrides)\n const adapterRules = (this.adapter.autoResponseRules || [])\n .filter(r => !this._disabledRulePatterns.has(r.pattern.source))\n .map(r => {\n const override = this._ruleOverrides.get(r.pattern.source);\n return override ? { ...r, ...override } : r;\n });\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n // Strip ANSI codes, cursor movement, box-drawing, and spinner chars\n // so regex patterns match the visible text, not raw terminal sequences.\n const stripped = this.stripAnsiForStall(this.outputBuffer);\n\n for (const rule of allRules) {\n // Skip once-rules that have already fired\n if (rule.once) {\n const ruleKey = `${rule.pattern.source}:${rule.pattern.flags}`;\n if (this._firedOnceRules.has(ruleKey)) {\n continue;\n }\n }\n\n if (rule.pattern.test(stripped)) {\n // Check if it's safe to auto-respond (default: true)\n const safe = rule.safe !== false;\n const isSessionRule = this.sessionRules.includes(rule);\n\n if (safe) {\n this.logger.info(\n {\n sessionId: this.id,\n promptType: rule.type,\n description: rule.description,\n response: rule.response,\n source: isSessionRule ? 'session' : 'adapter',\n },\n 'Applying auto-response rule'\n );\n\n // Determine how to send the response\n const useKeys = rule.keys && rule.keys.length > 0;\n const isTuiDefault = !rule.responseType && !rule.keys && this.adapter.usesTuiMenus;\n\n if (useKeys) {\n // Explicit key sequence\n this.sendKeySequence(rule.keys!);\n } else if (isTuiDefault) {\n // TUI adapter with no explicit responseType — default to Enter\n this.sendKeys('enter');\n } else {\n // Text response (backward compat)\n this.writeRaw(rule.response + '\\r');\n }\n\n // Track once-rules so they don't fire again on TUI re-renders\n if (rule.once) {\n const ruleKey = `${rule.pattern.source}:${rule.pattern.flags}`;\n this._firedOnceRules.add(ruleKey);\n }\n\n // Clear the entire buffer — the prompt has been handled and leftover\n // text (e.g. \"Press enter to continue\") would block detectReady().\n this.outputBuffer = '';\n\n const promptInfo: BlockingPromptInfo = {\n type: rule.type,\n prompt: rule.description,\n canAutoRespond: true,\n };\n\n this.emit('blocking_prompt', promptInfo, true);\n return true;\n } else {\n // Not safe to auto-respond, emit for user intervention\n const promptInfo: BlockingPromptInfo = {\n type: rule.type,\n prompt: rule.description,\n canAutoRespond: false,\n instructions: `Prompt matched but requires user confirmation: ${rule.description}`,\n };\n\n this.emit('blocking_prompt', promptInfo, false);\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Try to parse the output buffer into structured messages\n */\n private tryParseOutput(): void {\n const parsed = this.adapter.parseOutput(this.outputBuffer);\n\n if (parsed && parsed.isComplete) {\n // Clear the buffer for the parsed content\n this.outputBuffer = '';\n\n const message: SessionMessage = {\n id: `${this.id}-msg-${++this.messageCounter}`,\n sessionId: this.id,\n direction: 'outbound',\n type: parsed.type,\n content: parsed.content,\n metadata: parsed.metadata,\n timestamp: new Date(),\n };\n\n this.emit('message', message);\n\n // Also emit specific event for questions\n if (parsed.isQuestion) {\n this.emit('question', parsed.content);\n }\n }\n }\n\n /**\n * Write data to the PTY (formatted by adapter)\n */\n write(data: string): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n const formatted = this.adapter.formatInput(data);\n this.ptyProcess.write(formatted + '\\r');\n\n this.logger.debug({ sessionId: this.id, input: data }, 'Sent input to session');\n }\n\n /**\n * Write raw data directly to the PTY (no formatting)\n */\n writeRaw(data: string): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n this.ptyProcess.write(data);\n }\n\n /**\n * Send a task/message to the session\n *\n * Text and Enter are sent as separate writes with a small delay.\n * This is required for TUI-based CLIs (Gemini CLI, ink/React-based tools)\n * which drop the trailing \\r if it arrives in the same write buffer\n * during a render cycle.\n */\n send(message: string): SessionMessage {\n this._status = 'busy';\n this.outputBuffer = ''; // Clear stale startup/previous-task text so detectReady guards don't false-negative\n this.emit('status_changed', 'busy');\n this.resetStallTimer();\n\n const msg: SessionMessage = {\n id: `${this.id}-msg-${++this.messageCounter}`,\n sessionId: this.id,\n direction: 'inbound',\n type: 'task',\n content: message,\n timestamp: new Date(),\n };\n\n // Write formatted text without Enter\n const formatted = this.adapter.formatInput(message);\n this.writeRaw(formatted);\n\n // Send Enter separately after a brief delay\n // TUI-based CLIs need this as a discrete event to register the submission\n setTimeout(() => this.sendKeys('enter'), 50);\n\n this.logger.debug({ sessionId: this.id, input: message }, 'Sent input to session');\n\n return msg;\n }\n\n /**\n * Resize the PTY terminal\n */\n resize(cols: number, rows: number): void {\n this.ptyProcess?.resize(cols, rows);\n }\n\n /**\n * Send special keys to the PTY\n *\n * Supported keys:\n * - Control: ctrl+c, ctrl+d, ctrl+z, ctrl+l, ctrl+a, ctrl+e, ctrl+k, ctrl+u, ctrl+w, ctrl+r\n * - Navigation: up, down, left, right, home, end, pageup, pagedown\n * - Editing: enter, tab, backspace, delete, insert, escape\n * - Function: f1-f12\n *\n * @param keys - Key name(s) to send, e.g. \"ctrl+c\" or [\"up\", \"up\", \"enter\"]\n */\n sendKeys(keys: string | string[]): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n const keyList = Array.isArray(keys) ? keys : [keys];\n\n for (const key of keyList) {\n const normalizedKey = key.toLowerCase().trim();\n const sequence = SPECIAL_KEYS[normalizedKey];\n\n if (sequence) {\n this._lastActivityAt = new Date();\n this.ptyProcess.write(sequence);\n this.logger.debug({ sessionId: this.id, key: normalizedKey }, 'Sent special key');\n } else {\n this.logger.warn(\n { sessionId: this.id, key: normalizedKey },\n 'Unknown special key, sending as literal'\n );\n this.ptyProcess.write(key);\n }\n }\n }\n\n /**\n * Select a TUI menu option by index (0-based).\n * Sends Down arrow `optionIndex` times, then Enter, with 50ms delays.\n */\n async selectMenuOption(optionIndex: number): Promise<void> {\n for (let i = 0; i < optionIndex; i++) {\n this.sendKeys('down');\n await this.delay(50);\n }\n this.sendKeys('enter');\n }\n\n /**\n * Send a sequence of keys with staggered timing.\n * Each key is sent 50ms apart using setTimeout to keep the caller synchronous.\n */\n private sendKeySequence(keys: string[]): void {\n keys.forEach((key, i) => {\n setTimeout(() => this.sendKeys(key), i * 50);\n });\n }\n\n /**\n * Paste text using bracketed paste mode\n *\n * Bracketed paste mode wraps the pasted text in escape sequences\n * that tell the terminal this is pasted content, not typed input.\n * This prevents issues with pasting text that contains special characters\n * or looks like commands.\n *\n * @param text - Text to paste\n * @param useBracketedPaste - Whether to use bracketed paste mode (default: true)\n */\n paste(text: string, useBracketedPaste: boolean = true): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n\n if (useBracketedPaste) {\n this.ptyProcess.write(BRACKETED_PASTE_START + text + BRACKETED_PASTE_END);\n this.logger.debug(\n { sessionId: this.id, length: text.length },\n 'Pasted text with bracketed paste mode'\n );\n } else {\n this.ptyProcess.write(text);\n this.logger.debug(\n { sessionId: this.id, length: text.length },\n 'Pasted text without bracketed paste'\n );\n }\n }\n\n /**\n * Kill the PTY process\n */\n kill(signal?: string): void {\n if (this.ptyProcess) {\n this._status = 'stopping';\n this.clearStallTimer();\n this.cancelTaskComplete();\n this.cancelReadySettle();\n this.ptyProcess.kill(signal);\n this.logger.info({ sessionId: this.id, signal }, 'Killing PTY session');\n }\n }\n\n /**\n * Get current output buffer\n */\n getOutputBuffer(): string {\n return this.outputBuffer;\n }\n\n /**\n * Clear output buffer\n */\n clearOutputBuffer(): void {\n this.outputBuffer = '';\n }\n\n /**\n * Convert to SessionHandle\n */\n toHandle(): SessionHandle {\n return {\n id: this.id,\n name: this.config.name,\n type: this.config.type,\n status: this._status,\n pid: this.pid,\n startedAt: this._startedAt ?? undefined,\n lastActivityAt: this._lastActivityAt ?? undefined,\n };\n }\n}\n","/**\n * Console-based logger fallback.\n *\n * Shared between PTYManager and PTYSession to avoid duplication.\n * Supports both pino-style (context, message) and printf-style (message, context) calls.\n */\n\nimport type { Logger } from './types';\n\nexport const consoleLogger: Logger = {\n debug: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.debug(args[0], args[1]);\n } else {\n console.debug(args[1], args[0]);\n }\n },\n info: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.info(args[0], args[1]);\n } else {\n console.info(args[1], args[0]);\n }\n },\n warn: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.warn(args[0], args[1]);\n } else {\n console.warn(args[1], args[0]);\n }\n },\n error: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.error(args[0], args[1]);\n } else {\n console.error(args[1], args[0]);\n }\n },\n};\n","/**\n * Task completion trace analysis helpers.\n *\n * Parses structured \"Task completion trace\" logs and builds a compact\n * per-turn confidence timeline useful for debugging idle/completion detection.\n */\n\nexport interface TaskCompletionTraceRecord {\n sessionId?: string;\n adapterType?: string;\n event: string;\n status?: string;\n taskCompletePending?: boolean;\n signal?: boolean;\n wasPending?: boolean;\n debounceMs?: number;\n detectTaskComplete?: boolean;\n detectReady?: boolean;\n detectLoading?: boolean;\n tailHash?: string;\n tailSnippet?: string;\n timestamp?: string | number | Date;\n}\n\nexport interface TaskCompletionTimelineStep {\n event: string;\n atIndex: number;\n status: 'active' | 'active_loading' | 'likely_complete' | 'completed' | 'rejected';\n confidence: number;\n signal?: boolean;\n detectTaskComplete?: boolean;\n detectReady?: boolean;\n detectLoading?: boolean;\n}\n\nexport interface TaskCompletionTurnTimeline {\n turn: number;\n startIndex: number;\n endIndex: number;\n completed: boolean;\n maxConfidence: number;\n finalConfidence: number;\n events: TaskCompletionTimelineStep[];\n}\n\nexport interface TaskCompletionTimelineResult {\n turns: TaskCompletionTurnTimeline[];\n totalRecords: number;\n ignoredRecords: number;\n}\n\nexport interface BuildTimelineOptions {\n adapterType?: string;\n}\n\n/**\n * Extract trace records from mixed log inputs.\n * Accepts structured objects and JSON lines.\n */\nexport function extractTaskCompletionTraceRecords(\n entries: Array<string | Record<string, unknown>>,\n): TaskCompletionTraceRecord[] {\n const out: TaskCompletionTraceRecord[] = [];\n\n for (const entry of entries) {\n let obj: Record<string, unknown> | null = null;\n\n if (typeof entry === 'string') {\n const line = entry.trim();\n if (!line.startsWith('{') || !line.endsWith('}')) continue;\n try {\n obj = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue;\n }\n } else if (entry && typeof entry === 'object') {\n obj = entry;\n }\n\n if (!obj) continue;\n if (obj.msg !== 'Task completion trace') continue;\n if (typeof obj.event !== 'string') continue;\n\n out.push({\n sessionId: asString(obj.sessionId),\n adapterType: asString(obj.adapterType),\n event: obj.event,\n status: asString(obj.status),\n taskCompletePending: asBool(obj.taskCompletePending),\n signal: asBool(obj.signal),\n wasPending: asBool(obj.wasPending),\n debounceMs: asNumber(obj.debounceMs),\n detectTaskComplete: asBool(obj.detectTaskComplete),\n detectReady: asBool(obj.detectReady),\n detectLoading: asBool(obj.detectLoading),\n tailHash: asString(obj.tailHash),\n tailSnippet: asString(obj.tailSnippet),\n timestamp: asTimestamp(obj.time) ?? asTimestamp(obj.timestamp),\n });\n }\n\n return out;\n}\n\n/**\n * Build a per-turn confidence timeline from task-completion traces.\n */\nexport function buildTaskCompletionTimeline(\n records: TaskCompletionTraceRecord[],\n options: BuildTimelineOptions = {},\n): TaskCompletionTimelineResult {\n const filtered = records.filter((r) => {\n if (!options.adapterType) return true;\n return r.adapterType === options.adapterType;\n });\n\n const turns: TaskCompletionTurnTimeline[] = [];\n let current: TaskCompletionTurnTimeline | null = null;\n let ignored = 0;\n\n filtered.forEach((record, index) => {\n if (record.event === 'busy_signal' && current && current.completed) {\n current = null;\n }\n\n if (!current) {\n current = {\n turn: turns.length + 1,\n startIndex: index,\n endIndex: index,\n completed: false,\n maxConfidence: 0,\n finalConfidence: 0,\n events: [],\n };\n turns.push(current);\n }\n\n const step = toStep(record, index);\n if (!step) {\n ignored++;\n return;\n }\n\n current.events.push(step);\n current.endIndex = index;\n current.maxConfidence = Math.max(current.maxConfidence, step.confidence);\n current.finalConfidence = step.confidence;\n\n if (step.status === 'completed') {\n current.completed = true;\n }\n });\n\n return {\n turns,\n totalRecords: filtered.length,\n ignoredRecords: ignored,\n };\n}\n\nfunction toStep(record: TaskCompletionTraceRecord, atIndex: number): TaskCompletionTimelineStep | null {\n const event = record.event;\n const confidence = scoreConfidence(record);\n\n if (event === 'transition_ready') {\n return withCommon(record, {\n event,\n atIndex,\n status: 'completed',\n confidence: 100,\n });\n }\n\n if (event === 'debounce_reject_signal' || event === 'debounce_reject_status') {\n return withCommon(record, {\n event,\n atIndex,\n status: 'rejected',\n confidence,\n });\n }\n\n if (record.detectLoading) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'active_loading',\n confidence,\n });\n }\n\n if (event === 'debounce_fire' && record.signal) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'likely_complete',\n confidence,\n });\n }\n\n if (\n event === 'busy_signal' ||\n event === 'debounce_schedule' ||\n event === 'debounce_fire'\n ) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'active',\n confidence,\n });\n }\n\n return null;\n}\n\nfunction scoreConfidence(record: TaskCompletionTraceRecord): number {\n let score = 10;\n\n if (record.detectLoading) score -= 40;\n if (record.detectReady) score += 20;\n if (record.detectTaskComplete) score += 45;\n if (record.signal) score += 20;\n if (record.event === 'debounce_reject_signal' || record.event === 'debounce_reject_status') {\n score -= 30;\n }\n if (record.event === 'transition_ready') score = 100;\n\n if (score < 0) return 0;\n if (score > 100) return 100;\n return score;\n}\n\nfunction withCommon(\n record: TaskCompletionTraceRecord,\n step: Omit<TaskCompletionTimelineStep, 'signal' | 'detectTaskComplete' | 'detectReady' | 'detectLoading'>,\n): TaskCompletionTimelineStep {\n return {\n ...step,\n signal: record.signal,\n detectTaskComplete: record.detectTaskComplete,\n detectReady: record.detectReady,\n detectLoading: record.detectLoading,\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asBool(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nfunction asTimestamp(value: unknown): string | number | Date | undefined {\n if (typeof value === 'string' || typeof value === 'number' || value instanceof Date) {\n return value;\n }\n return undefined;\n}\n\n","/**\n * Base CLI Adapter\n *\n * Abstract base class with common functionality for CLI adapters.\n */\n\nimport { spawn } from 'child_process';\nimport type { CLIAdapter } from './adapter-interface';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n} from '../types';\n\n/**\n * Abstract base class for CLI adapters with common functionality\n */\nexport abstract class BaseCLIAdapter implements CLIAdapter {\n abstract readonly adapterType: string;\n abstract readonly displayName: string;\n\n /**\n * Auto-response rules for handling known blocking prompts.\n * Subclasses should override this to add CLI-specific rules.\n */\n readonly autoResponseRules: AutoResponseRule[] = [];\n\n /**\n * Whether this CLI uses TUI menus requiring arrow-key navigation.\n * Defaults to false; coding agent adapters override to true.\n */\n readonly usesTuiMenus: boolean = false;\n\n abstract getCommand(): string;\n abstract getArgs(config: SpawnConfig): string[];\n abstract getEnv(config: SpawnConfig): Record<string, string>;\n abstract detectLogin(output: string): LoginDetection;\n abstract detectReady(output: string): boolean;\n abstract parseOutput(output: string): ParsedOutput | null;\n abstract getPromptPattern(): RegExp;\n\n /**\n * Default exit detection - look for common exit patterns\n */\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n // Check for common exit/error patterns\n if (output.includes('Process exited with code')) {\n const match = output.match(/Process exited with code (\\d+)/);\n return {\n exited: true,\n code: match ? parseInt(match[1], 10) : 1,\n };\n }\n\n if (output.includes('Command not found') || output.includes('command not found')) {\n return {\n exited: true,\n code: 127,\n error: 'Command not found',\n };\n }\n\n return { exited: false };\n }\n\n /**\n * Default blocking prompt detection - looks for common prompt patterns.\n * Subclasses should override for CLI-specific detection.\n */\n detectBlockingPrompt(output: string): BlockingPromptDetection {\n let stripped = this.stripAnsi(output);\n\n // Strip TUI box-drawing/chrome characters so patterns work for ink/React CLIs\n // (Gemini CLI, Claude Code TUI mode, etc.)\n stripped = stripped.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⏺←→↑↓]/g, ' ');\n stripped = stripped.replace(/ {2,}/g, ' ');\n\n // Check for login/auth first (highest priority)\n const loginDetection = this.detectLogin(output);\n if (loginDetection.required) {\n return {\n detected: true,\n type: 'login',\n prompt: loginDetection.instructions,\n url: loginDetection.url,\n canAutoRespond: false,\n instructions: loginDetection.instructions,\n };\n }\n\n // Check for common update prompts\n if (/update (available|now|ready)/i.test(stripped) && /\\[y\\/n\\]/i.test(stripped)) {\n return {\n detected: true,\n type: 'update',\n prompt: 'Update available',\n options: ['y', 'n'],\n suggestedResponse: 'n',\n canAutoRespond: true,\n instructions: 'CLI update available - auto-declining to continue',\n };\n }\n\n // Check for terms of service / license acceptance\n if (/accept.*(terms|license|agreement)/i.test(stripped) && /\\[y\\/n\\]/i.test(stripped)) {\n return {\n detected: true,\n type: 'tos',\n prompt: 'Terms/license acceptance required',\n options: ['y', 'n'],\n canAutoRespond: false,\n instructions: 'Please accept the terms of service manually',\n };\n }\n\n // Check for model/version selection\n if (/choose.*model|select.*model|which model/i.test(stripped)) {\n return {\n detected: true,\n type: 'model_select',\n prompt: 'Model selection required',\n canAutoRespond: false,\n instructions: 'Please select a model',\n };\n }\n\n // Check for project/workspace selection\n if (/choose.*(project|workspace)|select.*(project|workspace)/i.test(stripped)) {\n return {\n detected: true,\n type: 'project_select',\n prompt: 'Project/workspace selection required',\n canAutoRespond: false,\n instructions: 'Please select a project or workspace',\n };\n }\n\n // Check for generic y/n prompts - multiple formats\n // [y/n], (y/n), [Y/n], [y/N], (Y)es/(N)o, Yes/No\n if (/\\[y\\/n\\]|\\(y\\/n\\)|\\[Y\\/n\\]|\\[y\\/N\\]|\\(Y\\)es\\/\\(N\\)o|Yes\\/No\\??/i.test(stripped)) {\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-200), // Last 200 chars for context\n options: ['y', 'n'],\n canAutoRespond: false,\n instructions: 'Confirmation prompt detected',\n };\n }\n\n // Check for numbered menu prompts (1. Yes / 2. No, or › 1. Yes)\n if (/^\\s*[›>]?\\s*[1-9]\\.\\s+\\w+/m.test(stripped) && /\\?\\s*$/m.test(stripped)) {\n // Extract numbered options\n const optionMatches = stripped.match(/[›>]?\\s*([1-9])\\.\\s+([^\\n]+)/g);\n const options = optionMatches\n ? optionMatches.map((m) => m.replace(/^[›>\\s]*/, '').trim())\n : [];\n\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-300),\n options: options.length > 0 ? options : undefined,\n canAutoRespond: false,\n instructions: 'Menu selection prompt detected',\n };\n }\n\n // Check for \"Enter to confirm\" / \"Press enter to continue\" style prompts\n if (/press enter|hit enter|enter to (confirm|continue|proceed)|press return/i.test(stripped)) {\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-200),\n suggestedResponse: '\\n',\n canAutoRespond: false,\n instructions: 'Enter/confirm prompt detected',\n };\n }\n\n // Check for trust/permission prompts (Claude Code style)\n if (/trust|allow|permission|grant access/i.test(stripped) && /\\?\\s*$/m.test(stripped)) {\n return {\n detected: true,\n type: 'permission',\n prompt: stripped.slice(-200),\n canAutoRespond: false,\n instructions: 'Permission/trust prompt detected',\n };\n }\n\n // Fallback: any line ending with ? that wasn't caught above\n // Only trigger if it looks like a standalone prompt (short, ends with ?)\n const lines = stripped.split('\\n').filter((l) => l.trim());\n const lastLine = lines[lines.length - 1] || '';\n if (/\\?\\s*$/.test(lastLine) && lastLine.length < 200) {\n return {\n detected: true,\n type: 'unknown',\n prompt: lastLine.trim(),\n canAutoRespond: false,\n instructions: 'Question prompt detected',\n };\n }\n\n return { detected: false };\n }\n\n /**\n * Default task completion detection — delegates to detectReady().\n * Subclasses should override to match high-confidence completion patterns\n * (e.g. duration summaries) that short-circuit the LLM stall classifier.\n */\n detectTaskComplete(output: string): boolean {\n return this.detectReady(output);\n }\n\n /**\n * Default input formatting - just return as-is\n */\n formatInput(message: string): string {\n return message;\n }\n\n /**\n * Validate CLI installation by running --version or --help\n */\n async validateInstallation(): Promise<{ installed: boolean; version?: string; error?: string }> {\n return new Promise((resolve) => {\n const command = this.getCommand();\n\n try {\n const proc = spawn(command, ['--version'], {\n shell: true,\n timeout: 5000,\n });\n\n let output = '';\n\n proc.stdout?.on('data', (data) => {\n output += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n output += data.toString();\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n // Try to extract version from output\n const versionMatch = output.match(/(\\d+\\.\\d+\\.\\d+)/);\n resolve({\n installed: true,\n version: versionMatch ? versionMatch[1] : undefined,\n });\n } else {\n resolve({\n installed: false,\n error: `Command exited with code ${code}`,\n });\n }\n });\n\n proc.on('error', (err) => {\n resolve({\n installed: false,\n error: err.message,\n });\n });\n } catch (err) {\n resolve({\n installed: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n });\n }\n });\n }\n\n /**\n * Helper to check if output contains a question\n */\n protected containsQuestion(output: string): boolean {\n const questionPatterns = [\n /\\?$/m, // Ends with ?\n /would you like/i,\n /do you want/i,\n /should I/i,\n /shall I/i,\n /please (choose|select|confirm)/i,\n /\\(y\\/n\\)/i,\n /\\[y\\/N\\]/i,\n /\\[Y\\/n\\]/i,\n ];\n\n return questionPatterns.some((pattern) => pattern.test(output));\n }\n\n /**\n * Helper to strip ANSI escape codes from output\n */\n protected stripAnsi(str: string): string {\n // Replace cursor-forward sequences (\\x1b[<n>C) with spaces before stripping.\n // TUI CLIs use these instead of literal spaces for word positioning.\n const withSpaces = str.replace(/\\x1b\\[\\d*C/g, ' ');\n // Strip OSC sequences: \\x1b] ... BEL or \\x1b] ... ST\n const withoutOsc = withSpaces.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n // Strip DCS sequences: \\x1bP ... ST\n const withoutDcs = withoutOsc.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n // eslint-disable-next-line no-control-regex\n return withoutDcs.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n }\n}\n","/**\n * Adapter Factory\n *\n * Factory function for creating CLI adapters from configuration.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\nimport { BaseCLIAdapter } from './base-adapter';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n AdapterFactoryConfig,\n} from '../types';\n\n/**\n * Creates a CLI adapter from configuration\n */\nexport function createAdapter(config: AdapterFactoryConfig): CLIAdapter {\n return new ConfiguredAdapter(config);\n}\n\n/**\n * Adapter implementation created from configuration\n */\nclass ConfiguredAdapter extends BaseCLIAdapter {\n readonly adapterType: string;\n readonly displayName: string;\n readonly autoResponseRules: AutoResponseRule[];\n\n constructor(private config: AdapterFactoryConfig) {\n super();\n this.adapterType = config.command.replace(/[^a-zA-Z0-9]/g, '-');\n this.displayName = config.command;\n this.autoResponseRules = this.buildAutoResponseRules();\n }\n\n private buildAutoResponseRules(): AutoResponseRule[] {\n if (!this.config.blockingPrompts) {\n return [];\n }\n\n return this.config.blockingPrompts\n .filter((p) => p.autoResponse !== undefined)\n .map((p) => ({\n pattern: p.pattern,\n type: p.type,\n response: p.autoResponse!,\n description: p.description || `Auto-respond to ${p.type} prompt`,\n safe: p.safe !== false,\n }));\n }\n\n getCommand(): string {\n return this.config.command;\n }\n\n getArgs(config: SpawnConfig): string[] {\n if (typeof this.config.args === 'function') {\n return this.config.args(config);\n }\n return this.config.args || [];\n }\n\n getEnv(config: SpawnConfig): Record<string, string> {\n if (typeof this.config.env === 'function') {\n return this.config.env(config);\n }\n return this.config.env || {};\n }\n\n detectLogin(output: string): LoginDetection {\n if (!this.config.loginDetection) {\n return { required: false };\n }\n\n const { patterns, extractUrl, extractInstructions } = this.config.loginDetection;\n const stripped = this.stripAnsi(output);\n\n for (const pattern of patterns) {\n if (pattern.test(stripped)) {\n return {\n required: true,\n type: 'browser',\n url: extractUrl?.(stripped) || undefined,\n instructions: extractInstructions?.(stripped) || 'Authentication required',\n };\n }\n }\n\n return { required: false };\n }\n\n detectBlockingPrompt(output: string): BlockingPromptDetection {\n // First check config-defined blocking prompts\n if (this.config.blockingPrompts) {\n const stripped = this.stripAnsi(output);\n\n for (const prompt of this.config.blockingPrompts) {\n if (prompt.pattern.test(stripped)) {\n return {\n detected: true,\n type: prompt.type,\n prompt: stripped.slice(-200),\n suggestedResponse: prompt.autoResponse,\n canAutoRespond: prompt.autoResponse !== undefined && prompt.safe !== false,\n instructions: prompt.description,\n };\n }\n }\n }\n\n // Fall back to base implementation\n return super.detectBlockingPrompt(output);\n }\n\n detectReady(output: string): boolean {\n if (!this.config.readyIndicators || this.config.readyIndicators.length === 0) {\n // Default: ready after any output\n return output.length > 10;\n }\n\n const stripped = this.stripAnsi(output);\n return this.config.readyIndicators.some((pattern) => pattern.test(stripped));\n }\n\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n if (this.config.exitIndicators) {\n for (const indicator of this.config.exitIndicators) {\n const match = output.match(indicator.pattern);\n if (match) {\n const code = indicator.codeExtractor?.(match) ?? 1;\n return { exited: true, code };\n }\n }\n }\n\n // Fall back to base implementation\n return super.detectExit(output);\n }\n\n parseOutput(output: string): ParsedOutput | null {\n if (this.config.parseOutput) {\n return this.config.parseOutput(output);\n }\n\n // Default parsing\n const cleaned = this.stripAnsi(output).trim();\n if (!cleaned) return null;\n\n return {\n type: 'response',\n content: cleaned,\n isComplete: true,\n isQuestion: this.containsQuestion(cleaned),\n };\n }\n\n formatInput(message: string): string {\n if (this.config.formatInput) {\n return this.config.formatInput(message);\n }\n return message;\n }\n\n getPromptPattern(): RegExp {\n return this.config.promptPattern || /[\\$#>]\\s*$/m;\n }\n}\n","/**\n * Shell Adapter\n *\n * Built-in adapter for bash/zsh shell sessions.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n} from '../types';\n\n/**\n * Options for the shell adapter\n */\nexport interface ShellAdapterOptions {\n /** Shell to use (default: $SHELL or /bin/bash) */\n shell?: string;\n\n /** Custom prompt string (default: 'pty> ') */\n prompt?: string;\n}\n\n/**\n * Built-in adapter for shell sessions (bash/zsh)\n */\nexport class ShellAdapter implements CLIAdapter {\n readonly adapterType = 'shell';\n readonly displayName = 'Shell';\n readonly autoResponseRules: AutoResponseRule[] = [];\n\n private shell: string;\n private promptStr: string;\n\n constructor(options: ShellAdapterOptions = {}) {\n this.shell = options.shell || process.env.SHELL || '/bin/bash';\n this.promptStr = options.prompt || 'pty> ';\n }\n\n getCommand(): string {\n return this.shell;\n }\n\n getArgs(_config: SpawnConfig): string[] {\n return [];\n }\n\n getEnv(_config: SpawnConfig): Record<string, string> {\n return {\n PS1: this.promptStr,\n };\n }\n\n detectLogin(_output: string): LoginDetection {\n // Shell doesn't need login\n return { required: false };\n }\n\n detectBlockingPrompt(_output: string): BlockingPromptDetection {\n // Shell typically doesn't have blocking prompts\n return { detected: false };\n }\n\n detectReady(output: string): boolean {\n // Ready when we see the prompt or any meaningful output\n return output.includes(this.promptStr) || output.includes('$') || output.length > 10;\n }\n\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n if (output.includes('exit')) {\n return { exited: true, code: 0 };\n }\n return { exited: false };\n }\n\n parseOutput(output: string): ParsedOutput | null {\n const cleaned = this.stripAnsi(output).trim();\n if (!cleaned) return null;\n\n return {\n type: 'response',\n content: cleaned,\n isComplete: true,\n isQuestion: false,\n };\n }\n\n formatInput(message: string): string {\n return message;\n }\n\n getPromptPattern(): RegExp {\n // Match our custom prompt or standard shell prompts\n const escaped = this.promptStr.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`(?:${escaped}|\\\\$|#|>)\\\\s*$`, 'm');\n }\n\n async validateInstallation(): Promise<{ installed: boolean; version?: string; error?: string }> {\n // Shell is always installed\n return { installed: true };\n }\n\n private stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n }\n}\n","/**\n * Bun-Compatible PTY Manager\n *\n * A wrapper that spawns a Node.js worker process to handle PTY operations,\n * allowing pty-manager to work from Bun or other non-Node runtimes.\n */\n\nimport { spawn, ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport * as path from 'path';\nimport * as readline from 'readline';\nimport type { SpawnConfig, AutoResponseRule, BlockingPromptType, SessionStatus, StallClassification, AuthRequiredInfo } from './types';\n\n/**\n * Serialized auto-response rule for IPC (pattern as string instead of RegExp)\n */\nexport interface SerializedRule {\n pattern: string;\n flags?: string;\n type: BlockingPromptType;\n response: string;\n responseType?: 'text' | 'keys';\n keys?: string[];\n description: string;\n safe?: boolean;\n once?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: SessionStatus;\n pid: number | undefined;\n cols: number;\n rows: number;\n startedAt?: Date;\n lastActivityAt?: Date;\n error?: string;\n exitCode?: number;\n}\n\nexport interface BunPTYManagerOptions {\n /** Path to node executable (default: 'node') */\n nodePath?: string;\n /** Path to worker script (default: auto-detected) */\n workerPath?: string;\n /** Environment variables for worker process */\n env?: Record<string, string>;\n /**\n * Adapter modules to load in the worker process.\n * Each module should export a `createAllAdapters()` function that returns an array of adapters.\n * Example: ['coding-agent-adapters']\n */\n adapterModules?: string[];\n\n /** Enable stall detection (default: false) */\n stallDetectionEnabled?: boolean;\n /** Default stall timeout in ms (default: 8000) */\n stallTimeoutMs?: number;\n /**\n * External classification callback invoked when a stall is detected.\n * The worker emits stall_detected; this callback runs on the parent side.\n */\n onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number,\n ) => Promise<StallClassification | null>;\n}\n\ninterface PendingOperation {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * PTY Manager that works with Bun and other non-Node runtimes\n * by spawning a Node.js worker process.\n */\nexport class BunCompatiblePTYManager extends EventEmitter {\n private worker: ChildProcess | null = null;\n private sessions: Map<string, WorkerSessionHandle> = new Map();\n private pending: Map<string, PendingOperation> = new Map();\n private ready = false;\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private nodePath: string;\n private workerPath: string;\n private env: Record<string, string>;\n private adapterModules: string[];\n private _stallDetectionEnabled: boolean;\n private _stallTimeoutMs: number;\n private _onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number,\n ) => Promise<StallClassification | null>;\n\n constructor(options: BunPTYManagerOptions = {}) {\n super();\n\n this.nodePath = options.nodePath || 'node';\n this.workerPath = options.workerPath || this.findWorkerPath();\n this.env = options.env || {};\n this.adapterModules = options.adapterModules || [];\n this._stallDetectionEnabled = options.stallDetectionEnabled ?? false;\n this._stallTimeoutMs = options.stallTimeoutMs ?? 8000;\n this._onStallClassify = options.onStallClassify;\n\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n this.startWorker();\n }\n\n private findWorkerPath(): string {\n // Try to find the worker script relative to this module\n const possiblePaths = [\n path.join(__dirname, 'pty-worker.js'),\n path.join(__dirname, '..', 'dist', 'pty-worker.js'),\n path.join(__dirname, '..', 'src', 'pty-worker.js'),\n ];\n\n // Return first path (we'll rely on Node to throw if it doesn't exist)\n return possiblePaths[0];\n }\n\n private startWorker(): void {\n this.worker = spawn(this.nodePath, [this.workerPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ...this.env },\n });\n\n if (!this.worker.stdout || !this.worker.stdin) {\n throw new Error('Failed to create worker process pipes');\n }\n\n const rl = readline.createInterface({\n input: this.worker.stdout,\n terminal: false,\n });\n\n rl.on('line', (line) => this.handleWorkerMessage(line));\n\n this.worker.stderr?.on('data', (data) => {\n this.emit('worker_error', data.toString());\n });\n\n this.worker.on('exit', (code, signal) => {\n this.ready = false;\n this.worker = null;\n this.emit('worker_exit', { code, signal });\n\n // Reject all pending operations\n for (const [key, op] of this.pending) {\n clearTimeout(op.timeout);\n op.reject(new Error('Worker process exited'));\n this.pending.delete(key);\n }\n\n // Mark all sessions as stopped\n for (const session of this.sessions.values()) {\n session.status = 'stopped';\n }\n });\n\n this.worker.on('error', (err) => {\n this.emit('worker_error', err);\n });\n }\n\n private handleWorkerMessage(line: string): void {\n let event: Record<string, unknown>;\n\n try {\n event = JSON.parse(line);\n } catch {\n this.emit('worker_error', `Invalid JSON from worker: ${line}`);\n return;\n }\n\n const eventType = event.event as string;\n const id = event.id as string | undefined;\n\n switch (eventType) {\n case 'worker_ready':\n // Register adapter modules before marking as ready\n if (this.adapterModules.length > 0) {\n this.sendCommand({ cmd: 'registerAdapters', modules: this.adapterModules });\n }\n // Send stall detection config to worker\n if (this._stallDetectionEnabled) {\n this.sendCommand({\n cmd: 'configureStallDetection',\n enabled: true,\n timeoutMs: this._stallTimeoutMs,\n });\n }\n this.ready = true;\n this.readyResolve();\n this.emit('ready');\n break;\n\n case 'spawned': {\n // Get config from event (worker sends it back)\n const session: WorkerSessionHandle = {\n id: id!,\n name: (event.name as string) || id!,\n type: (event.type as string) || 'shell',\n status: 'starting',\n pid: event.pid as number,\n cols: (event.cols as number) || 80,\n rows: (event.rows as number) || 24,\n startedAt: new Date(),\n };\n this.sessions.set(id!, session);\n this.emit('session_started', session);\n break;\n }\n\n case 'output': {\n const session = this.sessions.get(id!);\n if (session) {\n session.lastActivityAt = new Date();\n }\n this.emit('data', { id, data: event.data });\n this.emit(`data:${id}`, event.data);\n break;\n }\n\n case 'ready': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'ready';\n session.lastActivityAt = new Date();\n this.emit('session_ready', session);\n }\n break;\n }\n\n case 'exit': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'stopped';\n session.exitCode = event.code as number;\n session.lastActivityAt = new Date();\n this.emit('session_stopped', session, event.code, event.signal);\n this.sessions.delete(id!);\n }\n break;\n }\n\n case 'error':\n if (id) {\n const session = this.sessions.get(id);\n if (session) {\n session.status = 'error';\n session.error = event.message as string;\n session.lastActivityAt = new Date();\n }\n this.emit('session_error', { id, error: event.message });\n } else {\n this.emit('worker_error', event.message);\n }\n break;\n\n case 'blocking_prompt': {\n const session = this.sessions.get(id!);\n if (session) {\n this.emit('blocking_prompt', session, event.promptInfo, event.autoResponded);\n }\n break;\n }\n\n case 'login_required': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'authenticating';\n this.emit('login_required', session, event.instructions, event.url);\n }\n break;\n }\n\n case 'auth_required': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'authenticating';\n this.emit('auth_required', session, event.info as AuthRequiredInfo);\n }\n break;\n }\n\n case 'message': {\n const msg = event.message as Record<string, unknown>;\n // Convert timestamp back to Date\n this.emit('message', {\n ...msg,\n timestamp: new Date(msg.timestamp as string),\n });\n break;\n }\n\n case 'question': {\n const session = this.sessions.get(id!);\n if (session) {\n this.emit('question', session, event.question);\n }\n break;\n }\n\n case 'status_changed': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = event.status as SessionStatus;\n session.lastActivityAt = new Date();\n this.emit('session_status_changed', session);\n }\n break;\n }\n\n case 'task_complete': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'ready';\n session.lastActivityAt = new Date();\n this.emit('task_complete', session);\n }\n break;\n }\n\n case 'stall_detected': {\n const session = this.sessions.get(id!);\n if (session) {\n const recentOutput = event.recentOutput as string;\n const stallDurationMs = event.stallDurationMs as number;\n this.emit('stall_detected', session, recentOutput, stallDurationMs);\n\n // Call external classifier on parent side, send result back to worker\n if (this._onStallClassify) {\n this._onStallClassify(id!, recentOutput, stallDurationMs)\n .then((classification) => {\n this.sendCommand({\n cmd: 'classifyStallResult',\n id: id!,\n classification,\n });\n })\n .catch(() => {\n // On error, send null to reset the timer\n this.sendCommand({\n cmd: 'classifyStallResult',\n id: id!,\n classification: null,\n });\n });\n }\n }\n break;\n }\n\n case 'list': {\n // Convert date strings back to Date objects\n const sessions = (event.sessions as Record<string, unknown>[]).map((s) => ({\n ...s,\n startedAt: s.startedAt ? new Date(s.startedAt as string) : undefined,\n lastActivityAt: s.lastActivityAt ? new Date(s.lastActivityAt as string) : undefined,\n })) as WorkerSessionHandle[];\n this.resolvePending('list', sessions);\n break;\n }\n\n case 'rules': {\n // Convert serialized rules back to AutoResponseRule objects\n const serializedRules = event.rules as SerializedRule[];\n const rules = serializedRules.map((r) => ({\n pattern: new RegExp(r.pattern, r.flags || ''),\n type: r.type,\n response: r.response,\n responseType: r.responseType,\n keys: r.keys,\n description: r.description,\n safe: r.safe,\n once: r.once,\n })) as AutoResponseRule[];\n this.resolvePending(`getRules:${id}`, rules);\n break;\n }\n\n case 'ack': {\n const cmd = event.cmd as string;\n const success = event.success as boolean;\n const pendingKey = id ? `${cmd}:${id}` : cmd;\n const pending = this.pending.get(pendingKey);\n\n if (pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(pendingKey);\n\n if (success) {\n pending.resolve(true);\n } else {\n pending.reject(new Error(event.error as string));\n }\n }\n break;\n }\n }\n }\n\n private sendCommand(cmd: Record<string, unknown>): void {\n if (!this.worker?.stdin) {\n throw new Error('Worker not available');\n }\n\n this.worker.stdin.write(JSON.stringify(cmd) + '\\n');\n }\n\n private createPending(key: string, timeoutMs = 30000): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(key);\n reject(new Error(`Operation ${key} timed out`));\n }, timeoutMs);\n\n this.pending.set(key, { resolve, reject, timeout });\n });\n }\n\n private resolvePending(key: string, value: unknown): void {\n const pending = this.pending.get(key);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(key);\n pending.resolve(value);\n }\n }\n\n /**\n * Wait for the worker to be ready\n */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /**\n * Check if worker is ready\n */\n isReady(): boolean {\n return this.ready;\n }\n\n /**\n * Spawn a new PTY session\n */\n async spawn(config: SpawnConfig & { id: string }): Promise<WorkerSessionHandle> {\n await this.waitForReady();\n\n const { id } = config;\n\n this.sendCommand({ cmd: 'spawn', id, config });\n\n await this.createPending(`spawn:${id}`);\n\n return this.sessions.get(id)!;\n }\n\n /**\n * Send data to a session\n */\n async send(id: string, data: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'send', id, data });\n\n await this.createPending(`send:${id}`);\n }\n\n /**\n * Send special keys to a session\n */\n async sendKeys(id: string, keys: string | string[]): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'sendKeys', id, keys });\n\n await this.createPending(`sendKeys:${id}`);\n }\n\n /**\n * Paste text to a session\n */\n async paste(id: string, text: string, bracketed = true): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'paste', id, text, bracketed });\n\n await this.createPending(`paste:${id}`);\n }\n\n /**\n * Resize a session\n */\n async resize(id: string, cols: number, rows: number): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'resize', id, cols, rows });\n\n const session = this.sessions.get(id);\n if (session) {\n session.cols = cols;\n session.rows = rows;\n }\n\n await this.createPending(`resize:${id}`);\n }\n\n /**\n * Kill a session\n */\n async kill(id: string, signal?: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'kill', id, signal });\n\n await this.createPending(`kill:${id}`);\n }\n\n /**\n * Get a session by ID\n */\n get(id: string): WorkerSessionHandle | undefined {\n return this.sessions.get(id);\n }\n\n /**\n * List all sessions\n */\n async list(): Promise<WorkerSessionHandle[]> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'list' });\n\n const sessions = (await this.createPending('list')) as WorkerSessionHandle[];\n return sessions;\n }\n\n /**\n * Check if a session exists\n */\n has(id: string): boolean {\n return this.sessions.has(id);\n }\n\n /**\n * Subscribe to output from a specific session\n */\n onSessionData(id: string, callback: (data: string) => void): () => void {\n const handler = (data: string) => callback(data);\n this.on(`data:${id}`, handler);\n return () => this.off(`data:${id}`, handler);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n private serializeRule(rule: AutoResponseRule): SerializedRule {\n return {\n pattern: rule.pattern.source,\n flags: rule.pattern.flags || undefined,\n type: rule.type,\n response: rule.response,\n responseType: rule.responseType,\n keys: rule.keys,\n description: rule.description,\n safe: rule.safe,\n once: rule.once,\n };\n }\n\n /**\n * Add an auto-response rule to a session.\n * Session rules are checked before adapter rules.\n */\n async addAutoResponseRule(sessionId: string, rule: AutoResponseRule): Promise<void> {\n await this.waitForReady();\n\n const serialized = this.serializeRule(rule);\n this.sendCommand({ cmd: 'addRule', id: sessionId, rule: serialized });\n\n await this.createPending(`addRule:${sessionId}`);\n }\n\n /**\n * Remove an auto-response rule from a session by pattern.\n * Returns true if a rule was removed.\n */\n async removeAutoResponseRule(sessionId: string, pattern: RegExp): Promise<boolean> {\n await this.waitForReady();\n\n this.sendCommand({\n cmd: 'removeRule',\n id: sessionId,\n pattern: pattern.source,\n flags: pattern.flags || undefined,\n });\n\n try {\n await this.createPending(`removeRule:${sessionId}`);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Set all auto-response rules for a session, replacing existing ones.\n */\n async setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): Promise<void> {\n await this.waitForReady();\n\n const serialized = rules.map((r) => this.serializeRule(r));\n this.sendCommand({ cmd: 'setRules', id: sessionId, rules: serialized });\n\n await this.createPending(`setRules:${sessionId}`);\n }\n\n /**\n * Get all auto-response rules for a session.\n */\n async getAutoResponseRules(sessionId: string): Promise<AutoResponseRule[]> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'getRules', id: sessionId });\n\n const rules = (await this.createPending(`getRules:${sessionId}`)) as AutoResponseRule[];\n return rules;\n }\n\n /**\n * Select a TUI menu option by index (0-based) in a session.\n */\n async selectMenuOption(id: string, optionIndex: number): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'selectMenuOption', id, optionIndex });\n\n await this.createPending(`selectMenuOption:${id}`);\n }\n\n /**\n * Clear all auto-response rules for a session.\n */\n async clearAutoResponseRules(sessionId: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'clearRules', id: sessionId });\n\n await this.createPending(`clearRules:${sessionId}`);\n }\n\n /**\n * Shutdown the worker and all sessions\n */\n async shutdown(): Promise<void> {\n if (!this.worker) return;\n\n this.sendCommand({ cmd: 'shutdown' });\n\n await this.createPending('shutdown', 10000).catch(() => {\n // Force kill if shutdown times out\n this.worker?.kill('SIGKILL');\n });\n }\n\n /**\n * Restart the worker process\n */\n async restart(): Promise<void> {\n await this.shutdown();\n\n this.sessions.clear();\n this.ready = false;\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n this.startWorker();\n await this.waitForReady();\n }\n}\n\n/**\n * Detect if running in Bun\n */\nexport function isBun(): boolean {\n // Bun 1.1.24+ sets process.versions.bun (lowercase)\n return typeof process !== 'undefined' && 'bun' in process.versions;\n}\n\n/**\n * Create the appropriate PTY manager based on runtime\n */\nexport function createPTYManager(options?: BunPTYManagerOptions): BunCompatiblePTYManager {\n return new BunCompatiblePTYManager(options);\n}\n"],"mappings":"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","names":["import_events","import_child_process","import_events"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/pty-manager.ts","../src/adapters/adapter-registry.ts","../src/pty-session.ts","../src/logger.ts","../src/task-completion-trace.ts","../src/adapters/base-adapter.ts","../src/adapters/adapter-factory.ts","../src/adapters/shell-adapter.ts","../src/bun-compat.ts"],"sourcesContent":["/**\n * pty-manager\n *\n * PTY session manager with lifecycle management,\n * pluggable adapters, and blocking prompt detection.\n */\n\n// Core classes\nexport { PTYManager } from './pty-manager';\nexport { PTYSession, SPECIAL_KEYS } from './pty-session';\nexport {\n extractTaskCompletionTraceRecords,\n buildTaskCompletionTimeline,\n} from './task-completion-trace';\n\n// Adapter system\nexport {\n AdapterRegistry,\n BaseCLIAdapter,\n createAdapter,\n ShellAdapter,\n} from './adapters';\n\nexport type { CLIAdapter, ShellAdapterOptions } from './adapters';\n\n// Types\nexport type {\n // Session types\n SessionStatus,\n MessageType,\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n\n // Adapter types\n ParsedOutput,\n LoginDetection,\n AuthRequiredMethod,\n AuthRequiredInfo,\n BlockingPromptType,\n BlockingPromptDetection,\n AutoResponseRule,\n BlockingPromptInfo,\n\n // Stall detection types\n StallClassification,\n\n // Manager types\n Logger,\n StopOptions,\n LogOptions,\n TerminalAttachment,\n PTYManagerConfig,\n\n // Factory types\n AdapterFactoryConfig,\n} from './types';\n\n// Event types\nexport type { PTYManagerEvents } from './pty-manager';\nexport type { PTYSessionEvents } from './pty-session';\nexport type {\n TaskCompletionTraceRecord,\n TaskCompletionTimelineStep,\n TaskCompletionTurnTimeline,\n TaskCompletionTimelineResult,\n BuildTimelineOptions,\n} from './task-completion-trace';\n\n// Bun compatibility layer\nexport {\n BunCompatiblePTYManager,\n createPTYManager,\n isBun,\n} from './bun-compat';\n\nexport type {\n WorkerSessionHandle,\n BunPTYManagerOptions,\n} from './bun-compat';\n","/**\n * PTY Manager\n *\n * Manages multiple PTY sessions for CLI tools.\n */\n\nimport { EventEmitter } from 'events';\nimport type { CLIAdapter } from './adapters/adapter-interface';\nimport { AdapterRegistry } from './adapters/adapter-registry';\nimport { PTYSession } from './pty-session';\nimport { consoleLogger } from './logger';\nimport type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AuthRequiredInfo,\n AutoResponseRule,\n StallClassification,\n StopOptions,\n LogOptions,\n TerminalAttachment,\n PTYManagerConfig,\n Logger,\n} from './types';\n\nexport interface PTYManagerEvents {\n session_started: (session: SessionHandle) => void;\n session_ready: (session: SessionHandle) => void;\n session_stopped: (session: SessionHandle, reason: string) => void;\n session_error: (session: SessionHandle, error: string) => void;\n login_required: (session: SessionHandle, instructions?: string, url?: string) => void;\n auth_required: (session: SessionHandle, info: AuthRequiredInfo) => void;\n blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n stall_detected: (session: SessionHandle, recentOutput: string, stallDurationMs: number) => void;\n session_status_changed: (session: SessionHandle) => void;\n task_complete: (session: SessionHandle) => void;\n}\n\n\n\nexport class PTYManager extends EventEmitter {\n private sessions: Map<string, PTYSession> = new Map();\n private outputLogs: Map<string, string[]> = new Map();\n private maxLogLines: number;\n private logger: Logger;\n public readonly adapters: AdapterRegistry;\n\n // Stall detection config\n private _stallDetectionEnabled: boolean;\n private _stallTimeoutMs: number;\n private _onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number\n ) => Promise<StallClassification | null>;\n\n constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\n this._stallDetectionEnabled = config.stallDetectionEnabled ?? false;\n this._stallTimeoutMs = config.stallTimeoutMs ?? 8000;\n this._onStallClassify = config.onStallClassify;\n }\n\n /**\n * Register a CLI adapter\n */\n registerAdapter(adapter: CLIAdapter): void {\n this.adapters.register(adapter);\n }\n\n /**\n * Spawn a new PTY session\n */\n async spawn(config: SpawnConfig): Promise<SessionHandle> {\n // Get adapter for this type\n const adapter = this.adapters.get(config.type);\n if (!adapter) {\n throw new Error(`No adapter found for type: ${config.type}. Registered adapters: ${this.adapters.list().join(', ') || 'none'}`);\n }\n\n // Check if ID already exists\n if (config.id && this.sessions.has(config.id)) {\n throw new Error(`Session with ID ${config.id} already exists`);\n }\n\n this.logger.info(\n { type: config.type, name: config.name },\n 'Spawning session'\n );\n\n // Create session\n const session = new PTYSession(\n adapter,\n config,\n this.logger,\n this._stallDetectionEnabled,\n this._stallTimeoutMs,\n );\n\n // Set up event forwarding\n this.setupSessionEvents(session);\n\n // Store session\n this.sessions.set(session.id, session);\n this.outputLogs.set(session.id, []);\n\n // Start the session\n await session.start();\n\n const handle = session.toHandle();\n this.emit('session_started', handle);\n\n return handle;\n }\n\n /**\n * Set up event handlers for a session\n */\n private setupSessionEvents(session: PTYSession): void {\n session.on('output', (data: string) => {\n // Store in log buffer\n const logs = this.outputLogs.get(session.id) || [];\n const lines = data.split('\\n');\n logs.push(...lines);\n\n // Trim to max lines\n while (logs.length > this.maxLogLines) {\n logs.shift();\n }\n this.outputLogs.set(session.id, logs);\n });\n\n session.on('ready', () => {\n this.emit('session_ready', session.toHandle());\n });\n\n session.on('login_required', (instructions?: string, url?: string) => {\n this.emit('login_required', session.toHandle(), instructions, url);\n });\n\n session.on('auth_required', (info: AuthRequiredInfo) => {\n this.emit('auth_required', session.toHandle(), info);\n });\n\n session.on('blocking_prompt', (promptInfo: BlockingPromptInfo, autoResponded: boolean) => {\n this.emit('blocking_prompt', session.toHandle(), promptInfo, autoResponded);\n });\n\n session.on('message', (message: SessionMessage) => {\n this.emit('message', message);\n });\n\n session.on('question', (question: string) => {\n this.emit('question', session.toHandle(), question);\n });\n\n session.on('exit', (code: number) => {\n const reason = code === 0 ? 'normal exit' : `exit code ${code}`;\n this.emit('session_stopped', session.toHandle(), reason);\n });\n\n session.on('error', (error: Error) => {\n this.emit('session_error', session.toHandle(), error.message);\n });\n\n session.on('status_changed', () => {\n // Refresh the handle so the parent sees the updated status\n this.emit('session_status_changed', session.toHandle());\n });\n\n session.on('task_complete', () => {\n this.emit('task_complete', session.toHandle());\n });\n\n session.on('stall_detected', (recentOutput: string, stallDurationMs: number) => {\n const handle = session.toHandle();\n this.emit('stall_detected', handle, recentOutput, stallDurationMs);\n\n // Call external classifier if configured\n if (this._onStallClassify) {\n // Sanitize output before passing to LLM classifier to mitigate prompt injection.\n // Truncate to 1500 chars and strip sequences that could be used to manipulate the classifier.\n const sanitized = recentOutput\n .slice(-1500)\n .replace(/\\b(ignore|disregard|forget)\\s+(all\\s+)?(previous|above|prior)\\s+(instructions?|prompts?|rules?)\\b/gi, '[REDACTED]')\n .replace(/\\b(you\\s+are|act\\s+as|pretend\\s+to\\s+be|you\\s+must|system\\s*:)\\b/gi, '[REDACTED]');\n this._onStallClassify(session.id, sanitized, stallDurationMs)\n .then((classification) => {\n session.handleStallClassification(classification);\n })\n .catch((err) => {\n this.logger.error(\n { sessionId: session.id, error: err },\n 'Stall classification callback failed'\n );\n // Reset timer so detection continues\n session.handleStallClassification(null);\n });\n }\n });\n }\n\n /**\n * Stop a session\n */\n async stop(sessionId: string, options?: StopOptions): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n this.logger.info({ sessionId, force: options?.force }, 'Stopping session');\n\n const timeout = options?.timeout || 5000;\n\n return new Promise((resolve) => {\n const timer = setTimeout(() => {\n // Force kill if graceful shutdown times out\n session.kill('SIGKILL');\n resolve();\n }, timeout);\n\n session.once('exit', () => {\n clearTimeout(timer);\n session.removeAllListeners();\n this.sessions.delete(sessionId);\n this.outputLogs.delete(sessionId);\n resolve();\n });\n\n // Send graceful signal\n session.kill(options?.force ? 'SIGKILL' : 'SIGTERM');\n });\n }\n\n /**\n * Stop all sessions\n */\n async stopAll(options?: StopOptions): Promise<void> {\n const stopPromises = Array.from(this.sessions.keys()).map((id) =>\n this.stop(id, options).catch((err) => {\n this.logger.warn({ sessionId: id, error: err }, 'Error stopping session');\n })\n );\n\n await Promise.all(stopPromises);\n }\n\n /**\n * Get a session by ID\n */\n get(sessionId: string): SessionHandle | null {\n const session = this.sessions.get(sessionId);\n return session ? session.toHandle() : null;\n }\n\n /**\n * List all sessions\n */\n list(filter?: SessionFilter): SessionHandle[] {\n const handles: SessionHandle[] = [];\n\n for (const session of this.sessions.values()) {\n const handle = session.toHandle();\n\n // Apply filters\n if (filter) {\n if (filter.status) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!statuses.includes(handle.status)) continue;\n }\n\n if (filter.type) {\n const types = Array.isArray(filter.type) ? filter.type : [filter.type];\n if (!types.includes(handle.type)) continue;\n }\n }\n\n handles.push(handle);\n }\n\n return handles;\n }\n\n /**\n * Send a message to a session\n */\n send(sessionId: string, message: string): SessionMessage {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n return session.send(message);\n }\n\n /**\n * Get logs for a session\n */\n async *logs(sessionId: string, options?: LogOptions): AsyncIterable<string> {\n const logBuffer = this.outputLogs.get(sessionId);\n if (!logBuffer) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const lines = options?.tail\n ? logBuffer.slice(-options.tail)\n : logBuffer;\n\n for (const line of lines) {\n yield line;\n }\n }\n\n /**\n * Get metrics for a session\n */\n metrics(sessionId: string): { uptime?: number; messageCount?: number } | null {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return null;\n }\n\n const handle = session.toHandle();\n const uptime = handle.startedAt\n ? Math.floor((Date.now() - handle.startedAt.getTime()) / 1000)\n : undefined;\n\n return { uptime };\n }\n\n /**\n * Shutdown manager and stop all sessions\n */\n async shutdown(): Promise<void> {\n this.logger.info({ count: this.sessions.size }, 'Shutting down all sessions');\n\n await this.stopAll({ timeout: 3000 });\n\n this.sessions.clear();\n this.outputLogs.clear();\n }\n\n /**\n * Get count of sessions by status\n */\n getStatusCounts(): Record<SessionStatus, number> {\n const counts: Record<SessionStatus, number> = {\n pending: 0,\n starting: 0,\n authenticating: 0,\n ready: 0,\n busy: 0,\n stopping: 0,\n stopped: 0,\n error: 0,\n };\n\n for (const session of this.sessions.values()) {\n counts[session.status]++;\n }\n\n return counts;\n }\n\n /**\n * Attach to a session's terminal for raw I/O streaming\n */\n attachTerminal(sessionId: string): TerminalAttachment | null {\n const session = this.sessions.get(sessionId);\n if (!session) {\n return null;\n }\n\n return {\n /**\n * Subscribe to raw terminal output\n * Returns an unsubscribe function\n */\n onData: (callback: (data: string) => void) => {\n session.on('output', callback);\n return () => session.off('output', callback);\n },\n\n /**\n * Write raw data to terminal (no formatting applied)\n */\n write: (data: string) => {\n session.writeRaw(data);\n },\n\n /**\n * Resize the terminal\n */\n resize: (cols: number, rows: number) => {\n session.resize(cols, rows);\n },\n };\n }\n\n /**\n * Check if a session exists\n */\n has(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n /**\n * Get the underlying PTYSession (for advanced use)\n */\n getSession(sessionId: string): PTYSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Stall Detection Configuration\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Configure stall detection at runtime.\n * Affects newly spawned sessions only — existing sessions keep their config.\n */\n configureStallDetection(\n enabled: boolean,\n timeoutMs?: number,\n classify?: (sessionId: string, recentOutput: string, stallDurationMs: number) => Promise<StallClassification | null>,\n ): void {\n this._stallDetectionEnabled = enabled;\n if (timeoutMs !== undefined) {\n this._stallTimeoutMs = timeoutMs;\n }\n if (classify !== undefined) {\n this._onStallClassify = classify;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Add an auto-response rule to a session.\n * Session rules are checked before adapter rules.\n */\n addAutoResponseRule(sessionId: string, rule: AutoResponseRule): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.addAutoResponseRule(rule);\n }\n\n /**\n * Remove an auto-response rule from a session by pattern.\n * Returns true if a rule was removed.\n */\n removeAutoResponseRule(sessionId: string, pattern: RegExp): boolean {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n return session.removeAutoResponseRule(pattern);\n }\n\n /**\n * Set all auto-response rules for a session, replacing existing ones.\n */\n setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.setAutoResponseRules(rules);\n }\n\n /**\n * Get all auto-response rules for a session.\n */\n getAutoResponseRules(sessionId: string): AutoResponseRule[] {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n return session.getAutoResponseRules();\n }\n\n /**\n * Clear all auto-response rules for a session.\n */\n clearAutoResponseRules(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n session.clearAutoResponseRules();\n }\n}\n","/**\n * Adapter Registry\n *\n * Registry for managing CLI adapters.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\n\n/**\n * Registry of available CLI adapters\n */\nexport class AdapterRegistry {\n private adapters: Map<string, CLIAdapter> = new Map();\n\n /**\n * Register an adapter\n */\n register(adapter: CLIAdapter): void {\n this.adapters.set(adapter.adapterType, adapter);\n }\n\n /**\n * Get adapter for type\n */\n get(adapterType: string): CLIAdapter | undefined {\n return this.adapters.get(adapterType);\n }\n\n /**\n * Check if adapter exists for type\n */\n has(adapterType: string): boolean {\n return this.adapters.has(adapterType);\n }\n\n /**\n * Unregister an adapter\n */\n unregister(adapterType: string): boolean {\n return this.adapters.delete(adapterType);\n }\n\n /**\n * List all registered adapter types\n */\n list(): string[] {\n return Array.from(this.adapters.keys());\n }\n\n /**\n * Get all adapters\n */\n all(): CLIAdapter[] {\n return Array.from(this.adapters.values());\n }\n\n /**\n * Clear all adapters\n */\n clear(): void {\n this.adapters.clear();\n }\n}\n","/**\n * PTY Session\n *\n * Manages a single pseudo-terminal session for a CLI tool.\n */\n\nimport { EventEmitter } from 'events';\nimport { randomUUID } from 'crypto';\nimport type * as ptyModule from 'node-pty';\nimport type { CLIAdapter } from './adapters/adapter-interface';\nimport type {\n SpawnConfig,\n SessionStatus,\n SessionHandle,\n SessionMessage,\n BlockingPromptInfo,\n AuthRequiredInfo,\n LoginDetection,\n AutoResponseRule,\n StallClassification,\n Logger,\n} from './types';\nimport { consoleLogger } from './logger';\n\n// Lazy-load node-pty to avoid issues in environments where it's not installed\nlet ptyCache: typeof ptyModule | null = null;\nfunction loadPty(): typeof ptyModule {\n if (!ptyCache) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n ptyCache = require('node-pty') as typeof ptyModule;\n } catch {\n throw new Error(\n 'node-pty is required but not installed. Run: npm install node-pty'\n );\n }\n }\n return ptyCache!;\n}\n\nexport interface PTYSessionEvents {\n output: (data: string) => void;\n ready: () => void;\n login_required: (instructions?: string, url?: string) => void;\n auth_required: (info: AuthRequiredInfo) => void;\n blocking_prompt: (prompt: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (question: string) => void;\n exit: (code: number) => void;\n error: (error: Error) => void;\n stall_detected: (recentOutput: string, stallDurationMs: number) => void;\n status_changed: (status: SessionStatus) => void;\n task_complete: () => void;\n}\n\n\n\n/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${randomUUID().slice(0, 8)}`;\n}\n\n/**\n * Special key mappings to escape sequences\n *\n * Modifier codes for arrows/function keys:\n * 2 = Shift, 3 = Alt, 4 = Shift+Alt, 5 = Ctrl, 6 = Ctrl+Shift, 7 = Ctrl+Alt, 8 = Ctrl+Alt+Shift\n */\nexport const SPECIAL_KEYS: Record<string, string> = {\n // Control keys (Ctrl+letter = ASCII control code)\n 'ctrl+a': '\\x01',\n 'ctrl+b': '\\x02',\n 'ctrl+c': '\\x03',\n 'ctrl+d': '\\x04',\n 'ctrl+e': '\\x05',\n 'ctrl+f': '\\x06',\n 'ctrl+g': '\\x07',\n 'ctrl+h': '\\x08',\n 'ctrl+i': '\\x09',\n 'ctrl+j': '\\x0a',\n 'ctrl+k': '\\x0b',\n 'ctrl+l': '\\x0c',\n 'ctrl+m': '\\x0d',\n 'ctrl+n': '\\x0e',\n 'ctrl+o': '\\x0f',\n 'ctrl+p': '\\x10',\n 'ctrl+q': '\\x11',\n 'ctrl+r': '\\x12',\n 'ctrl+s': '\\x13',\n 'ctrl+t': '\\x14',\n 'ctrl+u': '\\x15',\n 'ctrl+v': '\\x16',\n 'ctrl+w': '\\x17',\n 'ctrl+x': '\\x18',\n 'ctrl+y': '\\x19',\n 'ctrl+z': '\\x1a',\n 'ctrl+[': '\\x1b',\n 'ctrl+\\\\': '\\x1c',\n 'ctrl+]': '\\x1d',\n 'ctrl+^': '\\x1e',\n 'ctrl+_': '\\x1f',\n\n // Alt+letter (Meta key = ESC + letter)\n 'alt+a': '\\x1ba', 'alt+b': '\\x1bb', 'alt+c': '\\x1bc', 'alt+d': '\\x1bd',\n 'alt+e': '\\x1be', 'alt+f': '\\x1bf', 'alt+g': '\\x1bg', 'alt+h': '\\x1bh',\n 'alt+i': '\\x1bi', 'alt+j': '\\x1bj', 'alt+k': '\\x1bk', 'alt+l': '\\x1bl',\n 'alt+m': '\\x1bm', 'alt+n': '\\x1bn', 'alt+o': '\\x1bo', 'alt+p': '\\x1bp',\n 'alt+q': '\\x1bq', 'alt+r': '\\x1br', 'alt+s': '\\x1bs', 'alt+t': '\\x1bt',\n 'alt+u': '\\x1bu', 'alt+v': '\\x1bv', 'alt+w': '\\x1bw', 'alt+x': '\\x1bx',\n 'alt+y': '\\x1by', 'alt+z': '\\x1bz',\n 'alt+backspace': '\\x1b\\x7f', // Delete word backward\n\n // Navigation - plain\n 'up': '\\x1b[A',\n 'down': '\\x1b[B',\n 'right': '\\x1b[C',\n 'left': '\\x1b[D',\n 'home': '\\x1b[H',\n 'end': '\\x1b[F',\n 'pageup': '\\x1b[5~',\n 'pagedown': '\\x1b[6~',\n\n // Navigation - with Shift (modifier 2)\n 'shift+up': '\\x1b[1;2A',\n 'shift+down': '\\x1b[1;2B',\n 'shift+right': '\\x1b[1;2C',\n 'shift+left': '\\x1b[1;2D',\n 'shift+home': '\\x1b[1;2H',\n 'shift+end': '\\x1b[1;2F',\n 'shift+pageup': '\\x1b[5;2~',\n 'shift+pagedown': '\\x1b[6;2~',\n\n // Navigation - with Alt (modifier 3)\n 'alt+up': '\\x1b[1;3A',\n 'alt+down': '\\x1b[1;3B',\n 'alt+right': '\\x1b[1;3C', // Forward word\n 'alt+left': '\\x1b[1;3D', // Backward word\n\n // Navigation - with Ctrl (modifier 5)\n 'ctrl+up': '\\x1b[1;5A',\n 'ctrl+down': '\\x1b[1;5B',\n 'ctrl+right': '\\x1b[1;5C', // Forward word\n 'ctrl+left': '\\x1b[1;5D', // Backward word\n 'ctrl+home': '\\x1b[1;5H',\n 'ctrl+end': '\\x1b[1;5F',\n\n // Navigation - with Ctrl+Shift (modifier 6) - select word\n 'ctrl+shift+up': '\\x1b[1;6A',\n 'ctrl+shift+down': '\\x1b[1;6B',\n 'ctrl+shift+right': '\\x1b[1;6C',\n 'ctrl+shift+left': '\\x1b[1;6D',\n 'ctrl+shift+home': '\\x1b[1;6H',\n 'ctrl+shift+end': '\\x1b[1;6F',\n\n // Navigation - with Shift+Alt (modifier 4)\n 'shift+alt+up': '\\x1b[1;4A',\n 'shift+alt+down': '\\x1b[1;4B',\n 'shift+alt+right': '\\x1b[1;4C',\n 'shift+alt+left': '\\x1b[1;4D',\n\n // Editing\n 'enter': '\\r',\n 'return': '\\r',\n 'tab': '\\t',\n 'shift+tab': '\\x1b[Z', // Reverse tab\n 'backspace': '\\x7f',\n 'delete': '\\x1b[3~',\n 'shift+delete': '\\x1b[3;2~',\n 'ctrl+delete': '\\x1b[3;5~', // Delete word forward\n 'insert': '\\x1b[2~',\n 'escape': '\\x1b',\n 'esc': '\\x1b',\n 'space': ' ',\n\n // Function keys - plain\n 'f1': '\\x1bOP',\n 'f2': '\\x1bOQ',\n 'f3': '\\x1bOR',\n 'f4': '\\x1bOS',\n 'f5': '\\x1b[15~',\n 'f6': '\\x1b[17~',\n 'f7': '\\x1b[18~',\n 'f8': '\\x1b[19~',\n 'f9': '\\x1b[20~',\n 'f10': '\\x1b[21~',\n 'f11': '\\x1b[23~',\n 'f12': '\\x1b[24~',\n\n // Function keys - with Shift (modifier 2)\n 'shift+f1': '\\x1b[1;2P',\n 'shift+f2': '\\x1b[1;2Q',\n 'shift+f3': '\\x1b[1;2R',\n 'shift+f4': '\\x1b[1;2S',\n 'shift+f5': '\\x1b[15;2~',\n 'shift+f6': '\\x1b[17;2~',\n 'shift+f7': '\\x1b[18;2~',\n 'shift+f8': '\\x1b[19;2~',\n 'shift+f9': '\\x1b[20;2~',\n 'shift+f10': '\\x1b[21;2~',\n 'shift+f11': '\\x1b[23;2~',\n 'shift+f12': '\\x1b[24;2~',\n\n // Function keys - with Ctrl (modifier 5)\n 'ctrl+f1': '\\x1b[1;5P',\n 'ctrl+f2': '\\x1b[1;5Q',\n 'ctrl+f3': '\\x1b[1;5R',\n 'ctrl+f4': '\\x1b[1;5S',\n 'ctrl+f5': '\\x1b[15;5~',\n 'ctrl+f6': '\\x1b[17;5~',\n 'ctrl+f7': '\\x1b[18;5~',\n 'ctrl+f8': '\\x1b[19;5~',\n 'ctrl+f9': '\\x1b[20;5~',\n 'ctrl+f10': '\\x1b[21;5~',\n 'ctrl+f11': '\\x1b[23;5~',\n 'ctrl+f12': '\\x1b[24;5~',\n};\n\n/**\n * Bracketed paste mode escape sequences\n */\nconst BRACKETED_PASTE_START = '\\x1b[200~';\nconst BRACKETED_PASTE_END = '\\x1b[201~';\n\nexport class PTYSession extends EventEmitter {\n private ptyProcess: ptyModule.IPty | null = null;\n private outputBuffer: string = '';\n private _status: SessionStatus = 'pending';\n private _startedAt: Date | null = null;\n private _lastActivityAt: Date | null = null;\n private messageCounter: number = 0;\n private logger: Logger;\n private sessionRules: AutoResponseRule[] = [];\n private _firedOnceRules: Set<string> = new Set();\n private _lastBlockingPromptHash: string | null = null;\n private _ruleOverrides: Map<string, Partial<AutoResponseRule>> = new Map();\n private _disabledRulePatterns: Set<string> = new Set();\n\n // Stall detection\n private _stallTimer: ReturnType<typeof setTimeout> | null = null;\n private _stallTimeoutMs: number;\n private _stallDetectionEnabled: boolean;\n private _lastStallHash: string | null = null;\n private _stallStartedAt: number | null = null;\n private _lastContentHash: string | null = null;\n private _stallBackoffMs: number = 0; // Initialized in constructor from _stallTimeoutMs\n private static readonly MAX_STALL_BACKOFF_MS = 30_000;\n private _stallEmissionCount: number = 0;\n private static readonly MAX_STALL_EMISSIONS = 5;\n\n // Task completion detection (idle detection when busy)\n private _taskCompleteTimer: ReturnType<typeof setTimeout> | null = null;\n private _taskCompletePending = false;\n private static readonly TASK_COMPLETE_DEBOUNCE_MS = 1500;\n\n // Ready detection settle delay — defers session_ready until output goes quiet\n private _readySettleTimer: ReturnType<typeof setTimeout> | null = null;\n private _readySettlePending = false;\n\n // Deferred output processing — prevents node-pty's synchronous data\n // delivery from starving the event loop (timers, I/O callbacks, etc.)\n private _processScheduled = false;\n\n // Output buffer cap — prevents unbounded growth during long tasks\n private static readonly MAX_OUTPUT_BUFFER = 100_000; // 100 KB\n\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger,\n stallDetectionEnabled?: boolean,\n defaultStallTimeoutMs?: number,\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\n this._stallDetectionEnabled = stallDetectionEnabled ?? false;\n this._stallTimeoutMs = config.stallTimeoutMs ?? defaultStallTimeoutMs ?? 8000;\n this._stallBackoffMs = this._stallTimeoutMs;\n\n // Process rule overrides from spawn config\n if (config.ruleOverrides) {\n for (const [key, value] of Object.entries(config.ruleOverrides)) {\n if (value === null) {\n this._disabledRulePatterns.add(key);\n } else {\n this._ruleOverrides.set(key, value);\n }\n }\n }\n }\n\n get status(): SessionStatus {\n return this._status;\n }\n\n get pid(): number | undefined {\n return this.ptyProcess?.pid;\n }\n\n get startedAt(): Date | undefined {\n return this._startedAt ?? undefined;\n }\n\n get lastActivityAt(): Date | undefined {\n return this._lastActivityAt ?? undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Add an auto-response rule to this session.\n * Session rules are checked before adapter rules.\n */\n addAutoResponseRule(rule: AutoResponseRule): void {\n // Check for duplicate pattern\n const existingIndex = this.sessionRules.findIndex(\n (r) => r.pattern.source === rule.pattern.source && r.pattern.flags === rule.pattern.flags\n );\n\n if (existingIndex >= 0) {\n // Replace existing rule with same pattern\n this.sessionRules[existingIndex] = rule;\n this.logger.debug(\n { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },\n 'Replaced existing auto-response rule'\n );\n } else {\n this.sessionRules.push(rule);\n this.logger.debug(\n { sessionId: this.id, pattern: rule.pattern.source, type: rule.type },\n 'Added auto-response rule'\n );\n }\n }\n\n /**\n * Remove an auto-response rule by pattern.\n * Returns true if a rule was removed.\n */\n removeAutoResponseRule(pattern: RegExp): boolean {\n const initialLength = this.sessionRules.length;\n this.sessionRules = this.sessionRules.filter(\n (r) => !(r.pattern.source === pattern.source && r.pattern.flags === pattern.flags)\n );\n\n const removed = this.sessionRules.length < initialLength;\n if (removed) {\n this.logger.debug(\n { sessionId: this.id, pattern: pattern.source },\n 'Removed auto-response rule'\n );\n }\n return removed;\n }\n\n /**\n * Set all session auto-response rules, replacing existing ones.\n */\n setAutoResponseRules(rules: AutoResponseRule[]): void {\n this.sessionRules = [...rules];\n this.logger.debug(\n { sessionId: this.id, count: rules.length },\n 'Set auto-response rules'\n );\n }\n\n /**\n * Get all session auto-response rules.\n */\n getAutoResponseRules(): AutoResponseRule[] {\n return [...this.sessionRules];\n }\n\n /**\n * Clear all session auto-response rules.\n */\n clearAutoResponseRules(): void {\n this.sessionRules = [];\n this.logger.debug({ sessionId: this.id }, 'Cleared auto-response rules');\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Stall Detection\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Start or reset the stall detection timer.\n * Active when status is \"busy\" or \"authenticating\" and stall detection is enabled.\n *\n * Content-based: hashes the ANSI-stripped buffer tail and only resets the\n * timer when visible content actually changes. This prevents TUI spinners\n * (which produce new ANSI sequences but no new visible text) from endlessly\n * resetting the timer.\n */\n private resetStallTimer(): void {\n if (!this._stallDetectionEnabled || (this._status !== 'busy' && this._status !== 'authenticating')) {\n this.clearStallTimer();\n return;\n }\n\n // Strip the full buffer FIRST, then slice the tail of the normalized text.\n // Stripping before slicing ensures the 500-char window covers the same\n // visible content regardless of how many raw escape sequences surround it.\n // (Slicing raw first caused different cursor-positioning codes at the\n // truncation boundary to produce different stripped text each TUI redraw.)\n const stripped = this.stripAnsiForStall(this.outputBuffer).trim();\n const visible = this.stripAnsiForClassifier(this.outputBuffer).trim();\n const tail = stripped.slice(-500);\n const fallbackTail = visible.slice(-500);\n const hash = this.simpleHash(tail || fallbackTail);\n\n if (hash === this._lastContentHash) {\n // Content unchanged (e.g., spinner animation) — don't reset the timer\n return;\n }\n this._lastContentHash = hash;\n this._stallEmissionCount = 0;\n\n // Content changed — clear and restart the timer, reset backoff\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallStartedAt = Date.now();\n this._lastStallHash = null; // New content, reset dedup hash for emissions\n this._stallBackoffMs = this._stallTimeoutMs; // Reset backoff on new real content\n\n this._stallTimer = setTimeout(() => {\n this.onStallTimerFired();\n }, this._stallTimeoutMs);\n }\n\n /**\n * Clear the stall detection timer.\n */\n private clearStallTimer(): void {\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallStartedAt = null;\n this._lastContentHash = null;\n this._stallBackoffMs = this._stallTimeoutMs;\n this._stallEmissionCount = 0;\n }\n\n /**\n * Called when the stall timer fires (no output for stallTimeoutMs).\n */\n private onStallTimerFired(): void {\n if (this._status !== 'busy' && this._status !== 'authenticating') {\n return; // Status changed while timer was running\n }\n\n // Fast path: try adapter-level task completion detection first.\n // This must run BEFORE detectLoading because the buffer may contain\n // both stale loading patterns (e.g. \"esc to interrupt\" from the spinner)\n // and a completion signal (e.g. \"Baked for 2s\" + prompt). Task completion\n // is the more specific/certain signal and should take priority.\n if (this._status === 'busy' && this.adapter.detectTaskComplete?.(this.outputBuffer)) {\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('status_changed', 'ready');\n this.emit('task_complete');\n this.logger.info(\n { sessionId: this.id },\n 'Task complete (adapter fast-path) — agent returned to idle prompt'\n );\n return;\n }\n\n // Loading suppression: if the adapter detects an active loading indicator\n // (thinking spinner, \"esc to interrupt\", \"Reading N files\", etc.),\n // the agent is provably working — suppress stall detection and reschedule.\n if (this.adapter.detectLoading?.(this.outputBuffer)) {\n this.logger.debug(\n { sessionId: this.id },\n 'Loading pattern detected — suppressing stall emission'\n );\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n\n // Compute dedup hash from last 500 chars of outputBuffer\n const tail = this.outputBuffer.slice(-500);\n const hash = this.simpleHash(tail);\n\n if (hash === this._lastStallHash) {\n // Buffer tail unchanged since last stall emission — don't re-emit.\n // Schedule another check with current backoff.\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n this._lastStallHash = hash;\n\n this._stallEmissionCount++;\n if (this._stallEmissionCount > PTYSession.MAX_STALL_EMISSIONS) {\n this.logger.warn(\n { sessionId: this.id, count: this._stallEmissionCount },\n 'Max stall emissions reached — suspending stall detection for this task'\n );\n this.clearStallTimer();\n return;\n }\n\n // Compute recent output for classifier: last 2000 chars, ANSI-stripped\n // while preserving visible symbols/text used by TUI CLIs.\n const recentRaw = this.outputBuffer.slice(-2000);\n const recentOutput = this.stripAnsiForClassifier(recentRaw).trim();\n\n const stallDurationMs = this._stallStartedAt\n ? Date.now() - this._stallStartedAt\n : this._stallTimeoutMs;\n\n this.logger.debug(\n {\n sessionId: this.id,\n stallDurationMs,\n bufferTailLength: tail.length,\n recentOutputLength: recentOutput.length,\n recentOutputHash: this.simpleHash(recentOutput.slice(-500)),\n },\n 'Stall detected'\n );\n\n this.emit('stall_detected', recentOutput, stallDurationMs);\n\n // Schedule next check with current backoff\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n }\n\n /**\n * Promise-based delay helper.\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Simple string hash for deduplication.\n */\n private simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash |= 0;\n }\n return hash.toString(36);\n }\n\n private mapLoginTypeToAuthMethod(type: LoginDetection['type'] | undefined): AuthRequiredInfo['method'] {\n switch (type) {\n case 'api_key':\n return 'api_key';\n case 'device_code':\n return 'device_code';\n case 'oauth':\n case 'browser':\n return 'oauth_browser';\n default:\n return 'unknown';\n }\n }\n\n private extractDeviceCode(text: string): string | undefined {\n const stripped = this.stripAnsiForClassifier(text);\n const explicitMatch = stripped.match(\n /(?:one-time|one time|device)?\\s*code[:\\s]+([A-Z0-9]{3,}(?:-[A-Z0-9]{3,})+)/i\n );\n if (explicitMatch?.[1]) {\n return explicitMatch[1].toUpperCase();\n }\n\n if (!/code/i.test(stripped)) {\n return undefined;\n }\n const fallbackMatch = stripped.match(/\\b([A-Z0-9]{3,}(?:-[A-Z0-9]{3,})+)\\b/);\n return fallbackMatch?.[1]?.toUpperCase();\n }\n\n private getPromptSnippet(maxChars = 280): string | undefined {\n const normalized = this.stripAnsiForClassifier(this.outputBuffer)\n .replace(/\\s+/g, ' ')\n .trim();\n if (!normalized) {\n return undefined;\n }\n return normalized.length <= maxChars\n ? normalized\n : normalized.slice(-maxChars);\n }\n\n private emitAuthRequired(details: {\n type?: LoginDetection['type'];\n url?: string;\n deviceCode?: string;\n instructions?: string;\n }): void {\n const info: AuthRequiredInfo = {\n method: this.mapLoginTypeToAuthMethod(details.type),\n url: details.url,\n deviceCode: details.deviceCode ?? this.extractDeviceCode(this.outputBuffer),\n instructions: details.instructions,\n promptSnippet: this.getPromptSnippet(),\n };\n\n this.emit('auth_required', info);\n this.emit('login_required', info.instructions, info.url);\n }\n\n /**\n * Strip ANSI codes, cursor movement, box-drawing, and spinner characters.\n * Used for stall detection hashing and auto-response pattern matching.\n *\n * Cursor movement codes are replaced with spaces (not removed) to preserve\n * word boundaries — e.g. \"Do\\x1b[5Cyou\" becomes \"Do you\", not \"Doyou\".\n */\n private stripAnsiForStall(str: string): string {\n // Replace ALL cursor movement/positioning codes with a space to preserve word boundaries:\n // \\x1b[nC (forward), \\x1b[nD (back), \\x1b[nA (up), \\x1b[nB (down), \\x1b[nG (column)\n // \\x1b[n;mH and \\x1b[n;mf (absolute positioning)\n // \\x1b[nJ (erase display), \\x1b[nK (erase line) — also space to keep words apart\n // \\x1b[nd (vertical position), \\x1b[nE/nF (cursor next/prev line)\n let result = str.replace(/\\x1b\\[\\d*[CDABGdEF]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*(?:;\\d+)?[Hf]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*[JK]/g, ' ');\n\n // Strip OSC sequences (Operating System Command): \\x1b] ... BEL or \\x1b] ... ST\n // Used for hyperlinks, window titles, Kitty graphics. Payload text would pollute output.\n result = result.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n\n // Strip DCS sequences (Device Control String): \\x1bP ... ST\n result = result.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n\n // Strip remaining ANSI escape sequences (SGR, cursor show/hide, etc.)\n // eslint-disable-next-line no-control-regex\n result = result.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n\n // Strip bare control characters (backspace, bell, carriage return, etc.)\n // Preserves only \\x09 (tab) and \\x0a (newline).\n // eslint-disable-next-line no-control-regex\n result = result.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f]/g, '');\n\n // Normalize non-breaking spaces (NBSP \\xa0) to regular spaces\n result = result.replace(/\\xa0/g, ' ');\n\n // Strip TUI box-drawing, spinner, and decorative Unicode characters\n result = result.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆◇▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥]/g, ' ');\n\n // Normalize countdown/duration text (e.g., \"8m 17s\" → \"0s\") to prevent\n // TUI countdown timers from resetting the stall timer every second.\n result = result.replace(/\\d+[hms](?:\\s+\\d+[hms])*/g, '0s');\n\n // Collapse multiple spaces\n result = result.replace(/ {2,}/g, ' ');\n\n return result;\n }\n\n /**\n * Less-aggressive ANSI stripping for classifier context.\n * Preserves visible TUI symbols (e.g. ❯, ✻) and durations while removing\n * escape/control sequences so the classifier keeps useful evidence.\n */\n private stripAnsiForClassifier(str: string): string {\n let result = str.replace(/\\x1b\\[\\d*[CDABGdEF]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*(?:;\\d+)?[Hf]/g, ' ');\n result = result.replace(/\\x1b\\[\\d*[JK]/g, ' ');\n\n // Strip OSC and DCS payloads\n result = result.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n result = result.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n\n // Strip remaining ANSI escape sequences\n // eslint-disable-next-line no-control-regex\n result = result.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n\n // Strip bare control chars except tab/newline\n // eslint-disable-next-line no-control-regex\n result = result.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f]/g, '');\n\n // Normalize NBSP and collapse spaces\n result = result.replace(/\\xa0/g, ' ');\n result = result.replace(/ {2,}/g, ' ');\n return result;\n }\n\n /**\n * Handle external stall classification result.\n * Called by the manager after onStallClassify resolves.\n */\n handleStallClassification(classification: StallClassification | null): void {\n // Guard against async race — session may no longer be busy/authenticating\n if (this._status !== 'busy' && this._status !== 'authenticating') {\n return;\n }\n\n if (!classification || classification.state === 'still_working') {\n // Exponential backoff — double the check interval (capped at 30s).\n // This avoids hammering the LLM classifier every few seconds when\n // the agent is legitimately working on a long task.\n this._stallBackoffMs = Math.min(\n this._stallBackoffMs * 2,\n PTYSession.MAX_STALL_BACKOFF_MS,\n );\n this.logger.debug(\n { sessionId: this.id, nextCheckMs: this._stallBackoffMs },\n 'Still working — backing off stall check interval'\n );\n\n // Force timer restart with backed-off interval, even if buffer\n // content hasn't changed.\n this._lastContentHash = null;\n this._lastStallHash = null; // Reset dedup hash so next fire can re-emit\n if (this._stallTimer) {\n clearTimeout(this._stallTimer);\n this._stallTimer = null;\n }\n this._stallTimer = setTimeout(() => this.onStallTimerFired(), this._stallBackoffMs);\n return;\n }\n\n switch (classification.state) {\n case 'waiting_for_input': {\n const promptInfo: BlockingPromptInfo = {\n type: 'stall_classified',\n prompt: classification.prompt,\n canAutoRespond: !!classification.suggestedResponse,\n };\n\n if (classification.suggestedResponse) {\n this.logger.info(\n { sessionId: this.id, response: classification.suggestedResponse },\n 'Auto-responding to stall-classified prompt'\n );\n const resp = classification.suggestedResponse;\n if (resp.startsWith('keys:')) {\n const keys = resp.slice(5).split(',').map(k => k.trim());\n this.sendKeySequence(keys);\n } else {\n this.writeRaw(resp + '\\r');\n }\n this.emit('blocking_prompt', promptInfo, true);\n this.outputBuffer = ''; // Prevent stale text from triggering false detections\n } else {\n this.emit('blocking_prompt', promptInfo, false);\n }\n break;\n }\n\n case 'task_complete':\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Stall classified as task_complete, transitioning to ready');\n break;\n\n case 'error':\n this.clearStallTimer();\n this.emit('error', new Error(classification.prompt || 'Stall classified as error'));\n break;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Task Completion Detection\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Schedule a task_complete transition after a debounce period.\n * Uses a settle pattern: each call resets the debounce timer instead of\n * being a no-op when already scheduled. This allows TUI agents that\n * continue rendering decorative output (status bar, update notices) after\n * the prompt to eventually settle, rather than having the timer cancelled\n * by every new data chunk. The callback re-verifies the task-complete\n * signal before transitioning, so stale triggers are safe.\n */\n private scheduleTaskComplete(): void {\n const wasPending = this._taskCompletePending;\n this.traceTaskCompletion('debounce_schedule', {\n wasPending,\n debounceMs: PTYSession.TASK_COMPLETE_DEBOUNCE_MS,\n });\n\n if (this._taskCompleteTimer) {\n clearTimeout(this._taskCompleteTimer);\n }\n this._taskCompletePending = true;\n\n this._taskCompleteTimer = setTimeout(() => {\n this._taskCompleteTimer = null;\n this._taskCompletePending = false;\n\n const signal = this.isTaskCompleteSignal(this.outputBuffer);\n this.traceTaskCompletion('debounce_fire', { signal });\n\n // Re-check: still busy and task-complete signal still present?\n if (this._status !== 'busy') {\n this.traceTaskCompletion('debounce_reject_status', { signal });\n return;\n }\n if (!signal) {\n this.traceTaskCompletion('debounce_reject_signal', { signal });\n return;\n }\n\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('status_changed', 'ready');\n this.emit('task_complete');\n this.traceTaskCompletion('transition_ready', { signal: true });\n this.logger.info({ sessionId: this.id }, 'Task complete — agent returned to idle prompt');\n }, PTYSession.TASK_COMPLETE_DEBOUNCE_MS);\n }\n\n /**\n * Adapter-level task completion check with compatibility fallback.\n * Prefer detectTaskComplete() because detectReady() may be broad for TUIs.\n */\n private isTaskCompleteSignal(output: string): boolean {\n if (this.adapter.detectTaskComplete) {\n return this.adapter.detectTaskComplete(output);\n }\n return this.adapter.detectReady(output);\n }\n\n /**\n * Claude-oriented task completion traces for PTY debugging.\n * Disabled by default; enable via config.traceTaskCompletion.\n */\n private traceTaskCompletion(\n event: string,\n ctx: Partial<{\n signal: boolean;\n wasPending: boolean;\n debounceMs: number;\n }> = {},\n ): void {\n if (!this.shouldTraceTaskCompletion()) return;\n\n const output = this.outputBuffer;\n const detectTaskComplete = this.adapter.detectTaskComplete\n ? this.adapter.detectTaskComplete(output)\n : undefined;\n const detectReady = this.adapter.detectReady(output);\n const detectLoading = this.adapter.detectLoading\n ? this.adapter.detectLoading(output)\n : undefined;\n const normalizedTail = this.stripAnsiForStall(output.slice(-280));\n\n this.logger.debug(\n {\n sessionId: this.id,\n adapterType: this.adapter.adapterType,\n event,\n status: this._status,\n taskCompletePending: this._taskCompletePending,\n signal: ctx.signal,\n wasPending: ctx.wasPending,\n debounceMs: ctx.debounceMs,\n detectTaskComplete,\n detectReady,\n detectLoading,\n tailHash: this.simpleHash(normalizedTail),\n tailSnippet: normalizedTail.slice(-140),\n },\n 'Task completion trace'\n );\n }\n\n private shouldTraceTaskCompletion(): boolean {\n return this.config.traceTaskCompletion === true;\n }\n\n /**\n * Cancel a pending task_complete timer (new output arrived that\n * doesn't match the idle prompt, so the agent is still working).\n */\n private cancelTaskComplete(): void {\n if (this._taskCompleteTimer) {\n clearTimeout(this._taskCompleteTimer);\n this._taskCompleteTimer = null;\n }\n this._taskCompletePending = false;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Ready Detection Settle Delay\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Schedule or reset the ready-settle timer.\n * Defers emitting session_ready until output goes quiet for readySettleMs\n * after detectReady first matches. This prevents sending input while\n * TUI agents are still rendering (status bar, shortcuts, update notices).\n */\n private scheduleReadySettle(): void {\n this._readySettlePending = true;\n if (this._readySettleTimer) {\n clearTimeout(this._readySettleTimer);\n }\n const settleMs = this.config.readySettleMs ?? this.adapter.readySettleMs ?? 100;\n this._readySettleTimer = setTimeout(() => {\n this._readySettleTimer = null;\n this._readySettlePending = false;\n // Re-verify state and ready indicator\n if (this._status !== 'starting' && this._status !== 'authenticating') return;\n if (!this.adapter.detectReady(this.outputBuffer)) return;\n this._status = 'ready';\n this._lastBlockingPromptHash = null;\n this.outputBuffer = '';\n this.clearStallTimer();\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready (after settle)');\n }, settleMs);\n }\n\n /**\n * Cancel a pending ready-settle timer (ready indicator disappeared\n * or session status changed).\n */\n private cancelReadySettle(): void {\n if (this._readySettleTimer) {\n clearTimeout(this._readySettleTimer);\n this._readySettleTimer = null;\n }\n this._readySettlePending = false;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Start the PTY session\n */\n async start(): Promise<void> {\n if (this.ptyProcess) {\n throw new Error('Session already started');\n }\n\n const nodePty = loadPty();\n\n this._status = 'starting';\n this._startedAt = new Date();\n\n const command = this.adapter.getCommand();\n const args = this.adapter.getArgs(this.config);\n const adapterEnv = this.adapter.getEnv(this.config);\n\n const env = {\n ...process.env,\n ...adapterEnv,\n ...this.config.env,\n // Force terminal settings\n TERM: 'xterm-256color',\n COLORTERM: 'truecolor',\n };\n\n this.logger.info(\n { sessionId: this.id, command, args: args.join(' ') },\n 'Starting PTY session'\n );\n\n try {\n this.ptyProcess = nodePty.spawn(command, args, {\n name: 'xterm-256color',\n cols: this.config.cols || 120,\n rows: this.config.rows || 40,\n cwd: this.config.workdir || process.cwd(),\n env: env as Record<string, string>,\n });\n\n this.setupEventHandlers();\n\n this.logger.info(\n { sessionId: this.id, pid: this.ptyProcess.pid },\n 'PTY session started'\n );\n } catch (error) {\n this._status = 'error';\n this.logger.error(\n { sessionId: this.id, error },\n 'Failed to start PTY session'\n );\n throw error;\n }\n }\n\n /**\n * Set up event handlers for the PTY\n */\n private setupEventHandlers(): void {\n if (!this.ptyProcess) return;\n\n this.ptyProcess.onData((data) => {\n this._lastActivityAt = new Date();\n this.outputBuffer += data;\n\n // Cap the buffer to prevent unbounded growth during long tasks.\n // Detection only ever inspects the tail, so trimming is safe.\n if (this.outputBuffer.length > PTYSession.MAX_OUTPUT_BUFFER) {\n this.outputBuffer = this.outputBuffer.slice(-PTYSession.MAX_OUTPUT_BUFFER);\n }\n\n // Emit raw output immediately (callers may need it for real-time display)\n this.emit('output', data);\n\n // Defer all heavy detection work to the next event-loop tick.\n // node-pty delivers data synchronously from its native read loop;\n // running regex-heavy detection inline can starve the event loop\n // and prevent timers (stall detection, task_complete debounce)\n // from firing — especially on macOS ARM64 where the PTY read can\n // hold the libuv poll phase.\n if (!this._processScheduled) {\n this._processScheduled = true;\n setImmediate(() => {\n this._processScheduled = false;\n this.processOutputBuffer();\n });\n }\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\n this.clearStallTimer();\n this.logger.info(\n { sessionId: this.id, exitCode, signal },\n 'PTY session exited'\n );\n this.emit('exit', exitCode);\n });\n }\n\n /**\n * Process the accumulated output buffer.\n * Called via setImmediate() from the onData handler so that heavy regex\n * work runs in its own event-loop tick, not inside node-pty's native callback.\n */\n private processOutputBuffer(): void {\n // Reset stall timer on any new output while busy or authenticating\n if (this._status === 'busy' || this._status === 'authenticating') {\n this.resetStallTimer();\n }\n\n // If a ready-settle is pending, reset the timer on new data instead of\n // re-running all detection. If the ready indicator disappears, cancel.\n if (this._readySettlePending) {\n if (\n (this._status === 'starting' || this._status === 'authenticating') &&\n this.adapter.detectReady(this.outputBuffer)\n ) {\n this.scheduleReadySettle();\n } else {\n this.cancelReadySettle();\n }\n return;\n }\n\n // Ready detection — check FIRST, before blocking prompt detection.\n // After an auto-response (e.g. trust prompt), the buffer may contain\n // leftover prompt text that would falsely trigger detectBlockingPrompt\n // and block detectReady from ever running. Adapter detectReady\n // implementations have negative guards for trust/auth prompts, so\n // this is safe — it won't prematurely mark the session as ready.\n if (\n (this._status === 'starting' || this._status === 'authenticating') &&\n this.adapter.detectReady(this.outputBuffer)\n ) {\n this.scheduleReadySettle();\n return;\n }\n\n // Task completion detection — when busy and the agent returns to idle.\n // Uses a settle pattern: once triggered, the debounce timer resets on each\n // new data chunk instead of being cancelled. The callback re-verifies\n // the task-complete signal before transitioning, so stale triggers are safe.\n if (this._status === 'busy') {\n const signal = this.isTaskCompleteSignal(this.outputBuffer);\n if (this._taskCompletePending || signal) {\n this.traceTaskCompletion('busy_signal', { signal });\n this.scheduleTaskComplete();\n }\n // No else/cancel — timer self-validates on fire\n }\n\n // Auto-response / blocking prompt detection — runs after detectReady.\n // Handles trust confirmations, permission prompts, apply changes, etc.\n // throughout the entire session lifecycle.\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Login detection — only during startup/auth (not after ready/busy)\n if (this._status !== 'ready' && this._status !== 'busy') {\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.clearStallTimer();\n this.emitAuthRequired({\n type: loginDetection.type,\n url: loginDetection.url,\n deviceCode: loginDetection.deviceCode,\n instructions: loginDetection.instructions,\n });\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.clearStallTimer();\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message only when ready.\n // Parsing clears outputBuffer; doing this while busy can starve task-complete\n // and stall detection of evidence during heavy TUI rendering.\n if (this._status === 'ready') {\n this.tryParseOutput();\n }\n }\n\n /**\n * Detect blocking prompts and handle them with auto-responses or user notification.\n * Deduplicates emissions - won't re-emit the same blocking prompt repeatedly.\n */\n private detectAndHandleBlockingPrompt(): boolean {\n // First, check adapter's auto-response rules\n const autoHandled = this.tryAutoResponse();\n if (autoHandled) {\n return true;\n }\n\n // Then check the adapter's detectBlockingPrompt method\n if (this.adapter.detectBlockingPrompt) {\n const detection = this.adapter.detectBlockingPrompt(this.outputBuffer);\n\n if (detection.detected) {\n // Deduplicate: don't re-emit the same blocking prompt\n const promptHash = `${detection.type}:${detection.prompt || ''}`;\n if (promptHash === this._lastBlockingPromptHash) {\n // Still blocked by same prompt, but don't spam events\n return true;\n }\n this._lastBlockingPromptHash = promptHash;\n\n const promptInfo: BlockingPromptInfo = {\n type: detection.type || 'unknown',\n prompt: detection.prompt,\n options: detection.options,\n canAutoRespond: detection.canAutoRespond || false,\n instructions: detection.instructions,\n url: detection.url,\n };\n\n // If we can auto-respond and have a suggested response, do it\n if (detection.canAutoRespond && detection.suggestedResponse && !this.config.skipAdapterAutoResponse) {\n this.logger.info(\n {\n sessionId: this.id,\n promptType: detection.type,\n response: detection.suggestedResponse,\n },\n 'Auto-responding to blocking prompt'\n );\n\n const resp = detection.suggestedResponse;\n if (resp.startsWith('keys:')) {\n const keys = resp.slice(5).split(',').map(k => k.trim());\n this.sendKeySequence(keys);\n } else {\n this.writeRaw(resp + '\\r');\n }\n this._lastBlockingPromptHash = null; // Clear after auto-response\n this.outputBuffer = ''; // Prevent stale text from triggering false detections\n this.emit('blocking_prompt', promptInfo, true);\n return true;\n }\n\n // Otherwise, notify that user intervention is needed\n if (detection.type === 'login') {\n this._status = 'authenticating';\n // Surface login prompts through the dedicated auth event so callers\n // can open OAuth/device-code URLs without parsing blocking_prompt.\n const inferred = this.adapter.detectLogin(this.outputBuffer);\n this.emitAuthRequired({\n type: inferred.required ? inferred.type : undefined,\n url: detection.url ?? inferred.url,\n deviceCode: inferred.required ? inferred.deviceCode : undefined,\n instructions: detection.instructions ?? inferred.instructions,\n });\n }\n\n this.logger.warn(\n {\n sessionId: this.id,\n promptType: detection.type,\n prompt: detection.prompt,\n },\n 'Blocking prompt requires user intervention'\n );\n\n this.emit('blocking_prompt', promptInfo, false);\n return true;\n } else {\n // No blocking prompt detected - clear the hash\n this._lastBlockingPromptHash = null;\n }\n }\n\n return false;\n }\n\n /**\n * Try to match and apply auto-response rules.\n * Session rules are checked first, then adapter rules.\n */\n private tryAutoResponse(): boolean {\n // Combine session rules (higher priority) with adapter rules (filtered/merged by overrides)\n const adapterRules = (this.adapter.autoResponseRules || [])\n .filter(r => !this._disabledRulePatterns.has(r.pattern.source))\n .map(r => {\n const override = this._ruleOverrides.get(r.pattern.source);\n return override ? { ...r, ...override } : r;\n });\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n // Strip ANSI codes, cursor movement, box-drawing, and spinner chars\n // so regex patterns match the visible text, not raw terminal sequences.\n const stripped = this.stripAnsiForStall(this.outputBuffer);\n\n for (const rule of allRules) {\n // Skip once-rules that have already fired\n if (rule.once) {\n const ruleKey = `${rule.pattern.source}:${rule.pattern.flags}`;\n if (this._firedOnceRules.has(ruleKey)) {\n continue;\n }\n }\n\n if (rule.pattern.test(stripped)) {\n // Check if it's safe to auto-respond (default: true)\n const safe = rule.safe !== false;\n const isSessionRule = this.sessionRules.includes(rule);\n\n if (safe) {\n this.logger.info(\n {\n sessionId: this.id,\n promptType: rule.type,\n description: rule.description,\n response: rule.response,\n source: isSessionRule ? 'session' : 'adapter',\n },\n 'Applying auto-response rule'\n );\n\n // Determine how to send the response\n const useKeys = rule.keys && rule.keys.length > 0;\n const isTuiDefault = !rule.responseType && !rule.keys && this.adapter.usesTuiMenus;\n\n if (useKeys) {\n // Explicit key sequence\n this.sendKeySequence(rule.keys!);\n } else if (isTuiDefault) {\n // TUI adapter with no explicit responseType — default to Enter\n this.sendKeys('enter');\n } else {\n // Text response (backward compat)\n this.writeRaw(rule.response + '\\r');\n }\n\n // Track once-rules so they don't fire again on TUI re-renders\n if (rule.once) {\n const ruleKey = `${rule.pattern.source}:${rule.pattern.flags}`;\n this._firedOnceRules.add(ruleKey);\n }\n\n // Clear the entire buffer — the prompt has been handled and leftover\n // text (e.g. \"Press enter to continue\") would block detectReady().\n this.outputBuffer = '';\n\n const promptInfo: BlockingPromptInfo = {\n type: rule.type,\n prompt: rule.description,\n canAutoRespond: true,\n };\n\n this.emit('blocking_prompt', promptInfo, true);\n return true;\n } else {\n // Not safe to auto-respond, emit for user intervention\n const promptInfo: BlockingPromptInfo = {\n type: rule.type,\n prompt: rule.description,\n canAutoRespond: false,\n instructions: `Prompt matched but requires user confirmation: ${rule.description}`,\n };\n\n this.emit('blocking_prompt', promptInfo, false);\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Try to parse the output buffer into structured messages\n */\n private tryParseOutput(): void {\n const parsed = this.adapter.parseOutput(this.outputBuffer);\n\n if (parsed && parsed.isComplete) {\n // Clear the buffer for the parsed content\n this.outputBuffer = '';\n\n const message: SessionMessage = {\n id: `${this.id}-msg-${++this.messageCounter}`,\n sessionId: this.id,\n direction: 'outbound',\n type: parsed.type,\n content: parsed.content,\n metadata: parsed.metadata,\n timestamp: new Date(),\n };\n\n this.emit('message', message);\n\n // Also emit specific event for questions\n if (parsed.isQuestion) {\n this.emit('question', parsed.content);\n }\n }\n }\n\n /**\n * Write data to the PTY (formatted by adapter)\n */\n write(data: string): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n const formatted = this.adapter.formatInput(data);\n this.ptyProcess.write(formatted + '\\r');\n\n this.logger.debug({ sessionId: this.id, input: data }, 'Sent input to session');\n }\n\n /**\n * Write raw data directly to the PTY (no formatting)\n */\n writeRaw(data: string): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n this.ptyProcess.write(data);\n }\n\n /**\n * Send a task/message to the session\n *\n * Text and Enter are sent as separate writes with a small delay.\n * This is required for TUI-based CLIs (Gemini CLI, ink/React-based tools)\n * which drop the trailing \\r if it arrives in the same write buffer\n * during a render cycle.\n */\n send(message: string): SessionMessage {\n this._status = 'busy';\n this.outputBuffer = ''; // Clear stale startup/previous-task text so detectReady guards don't false-negative\n this.emit('status_changed', 'busy');\n this._stallEmissionCount = 0;\n this.resetStallTimer();\n\n const msg: SessionMessage = {\n id: `${this.id}-msg-${++this.messageCounter}`,\n sessionId: this.id,\n direction: 'inbound',\n type: 'task',\n content: message,\n timestamp: new Date(),\n };\n\n // Write formatted text without Enter\n const formatted = this.adapter.formatInput(message);\n this.writeRaw(formatted);\n\n // Send Enter separately after a brief delay\n // TUI-based CLIs need this as a discrete event to register the submission\n setTimeout(() => this.sendKeys('enter'), 50);\n\n this.logger.debug({ sessionId: this.id, input: message }, 'Sent input to session');\n\n return msg;\n }\n\n /**\n * Resize the PTY terminal\n */\n resize(cols: number, rows: number): void {\n this.ptyProcess?.resize(cols, rows);\n }\n\n /**\n * Send special keys to the PTY\n *\n * Supported keys:\n * - Control: ctrl+c, ctrl+d, ctrl+z, ctrl+l, ctrl+a, ctrl+e, ctrl+k, ctrl+u, ctrl+w, ctrl+r\n * - Navigation: up, down, left, right, home, end, pageup, pagedown\n * - Editing: enter, tab, backspace, delete, insert, escape\n * - Function: f1-f12\n *\n * @param keys - Key name(s) to send, e.g. \"ctrl+c\" or [\"up\", \"up\", \"enter\"]\n */\n sendKeys(keys: string | string[]): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n const keyList = Array.isArray(keys) ? keys : [keys];\n this._stallEmissionCount = 0;\n this.resetStallTimer();\n\n for (const key of keyList) {\n const normalizedKey = key.toLowerCase().trim();\n const sequence = SPECIAL_KEYS[normalizedKey];\n\n if (sequence) {\n this._lastActivityAt = new Date();\n this.ptyProcess.write(sequence);\n this.logger.debug({ sessionId: this.id, key: normalizedKey }, 'Sent special key');\n } else {\n this.logger.warn(\n { sessionId: this.id, key: normalizedKey },\n 'Unknown special key, sending as literal'\n );\n this.ptyProcess.write(key);\n }\n }\n }\n\n /**\n * Select a TUI menu option by index (0-based).\n * Sends Down arrow `optionIndex` times, then Enter, with 50ms delays.\n */\n async selectMenuOption(optionIndex: number): Promise<void> {\n for (let i = 0; i < optionIndex; i++) {\n this.sendKeys('down');\n await this.delay(50);\n }\n this.sendKeys('enter');\n }\n\n /**\n * Send a sequence of keys with staggered timing.\n * Each key is sent 50ms apart using setTimeout to keep the caller synchronous.\n */\n private sendKeySequence(keys: string[]): void {\n keys.forEach((key, i) => {\n setTimeout(() => this.sendKeys(key), i * 50);\n });\n }\n\n /**\n * Paste text using bracketed paste mode\n *\n * Bracketed paste mode wraps the pasted text in escape sequences\n * that tell the terminal this is pasted content, not typed input.\n * This prevents issues with pasting text that contains special characters\n * or looks like commands.\n *\n * @param text - Text to paste\n * @param useBracketedPaste - Whether to use bracketed paste mode (default: true)\n */\n paste(text: string, useBracketedPaste: boolean = true): void {\n if (!this.ptyProcess) {\n throw new Error('Session not started');\n }\n\n this._lastActivityAt = new Date();\n\n if (useBracketedPaste) {\n this.ptyProcess.write(BRACKETED_PASTE_START + text + BRACKETED_PASTE_END);\n this.logger.debug(\n { sessionId: this.id, length: text.length },\n 'Pasted text with bracketed paste mode'\n );\n } else {\n this.ptyProcess.write(text);\n this.logger.debug(\n { sessionId: this.id, length: text.length },\n 'Pasted text without bracketed paste'\n );\n }\n }\n\n /**\n * Kill the PTY process\n */\n kill(signal?: string): void {\n if (this.ptyProcess) {\n this._status = 'stopping';\n this.clearStallTimer();\n this.cancelTaskComplete();\n this.cancelReadySettle();\n this.ptyProcess.kill(signal);\n this.logger.info({ sessionId: this.id, signal }, 'Killing PTY session');\n }\n }\n\n /**\n * Get current output buffer\n */\n getOutputBuffer(): string {\n return this.outputBuffer;\n }\n\n /**\n * Clear output buffer\n */\n clearOutputBuffer(): void {\n this.outputBuffer = '';\n }\n\n /**\n * Convert to SessionHandle\n */\n toHandle(): SessionHandle {\n return {\n id: this.id,\n name: this.config.name,\n type: this.config.type,\n status: this._status,\n pid: this.pid,\n startedAt: this._startedAt ?? undefined,\n lastActivityAt: this._lastActivityAt ?? undefined,\n };\n }\n}\n","/**\n * Console-based logger fallback.\n *\n * Shared between PTYManager and PTYSession to avoid duplication.\n * Supports both pino-style (context, message) and printf-style (message, context) calls.\n */\n\nimport type { Logger } from './types';\n\nexport const consoleLogger: Logger = {\n debug: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.debug(args[0], args[1]);\n } else {\n console.debug(args[1], args[0]);\n }\n },\n info: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.info(args[0], args[1]);\n } else {\n console.info(args[1], args[0]);\n }\n },\n warn: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.warn(args[0], args[1]);\n } else {\n console.warn(args[1], args[0]);\n }\n },\n error: (...args: unknown[]) => {\n if (typeof args[0] === 'string') {\n console.error(args[0], args[1]);\n } else {\n console.error(args[1], args[0]);\n }\n },\n};\n","/**\n * Task completion trace analysis helpers.\n *\n * Parses structured \"Task completion trace\" logs and builds a compact\n * per-turn confidence timeline useful for debugging idle/completion detection.\n */\n\nexport interface TaskCompletionTraceRecord {\n sessionId?: string;\n adapterType?: string;\n event: string;\n status?: string;\n taskCompletePending?: boolean;\n signal?: boolean;\n wasPending?: boolean;\n debounceMs?: number;\n detectTaskComplete?: boolean;\n detectReady?: boolean;\n detectLoading?: boolean;\n tailHash?: string;\n tailSnippet?: string;\n timestamp?: string | number | Date;\n}\n\nexport interface TaskCompletionTimelineStep {\n event: string;\n atIndex: number;\n status: 'active' | 'active_loading' | 'likely_complete' | 'completed' | 'rejected';\n confidence: number;\n signal?: boolean;\n detectTaskComplete?: boolean;\n detectReady?: boolean;\n detectLoading?: boolean;\n}\n\nexport interface TaskCompletionTurnTimeline {\n turn: number;\n startIndex: number;\n endIndex: number;\n completed: boolean;\n maxConfidence: number;\n finalConfidence: number;\n events: TaskCompletionTimelineStep[];\n}\n\nexport interface TaskCompletionTimelineResult {\n turns: TaskCompletionTurnTimeline[];\n totalRecords: number;\n ignoredRecords: number;\n}\n\nexport interface BuildTimelineOptions {\n adapterType?: string;\n}\n\n/**\n * Extract trace records from mixed log inputs.\n * Accepts structured objects and JSON lines.\n */\nexport function extractTaskCompletionTraceRecords(\n entries: Array<string | Record<string, unknown>>,\n): TaskCompletionTraceRecord[] {\n const out: TaskCompletionTraceRecord[] = [];\n\n for (const entry of entries) {\n let obj: Record<string, unknown> | null = null;\n\n if (typeof entry === 'string') {\n const line = entry.trim();\n if (!line.startsWith('{') || !line.endsWith('}')) continue;\n try {\n obj = JSON.parse(line) as Record<string, unknown>;\n } catch {\n continue;\n }\n } else if (entry && typeof entry === 'object') {\n obj = entry;\n }\n\n if (!obj) continue;\n if (obj.msg !== 'Task completion trace') continue;\n if (typeof obj.event !== 'string') continue;\n\n out.push({\n sessionId: asString(obj.sessionId),\n adapterType: asString(obj.adapterType),\n event: obj.event,\n status: asString(obj.status),\n taskCompletePending: asBool(obj.taskCompletePending),\n signal: asBool(obj.signal),\n wasPending: asBool(obj.wasPending),\n debounceMs: asNumber(obj.debounceMs),\n detectTaskComplete: asBool(obj.detectTaskComplete),\n detectReady: asBool(obj.detectReady),\n detectLoading: asBool(obj.detectLoading),\n tailHash: asString(obj.tailHash),\n tailSnippet: asString(obj.tailSnippet),\n timestamp: asTimestamp(obj.time) ?? asTimestamp(obj.timestamp),\n });\n }\n\n return out;\n}\n\n/**\n * Build a per-turn confidence timeline from task-completion traces.\n */\nexport function buildTaskCompletionTimeline(\n records: TaskCompletionTraceRecord[],\n options: BuildTimelineOptions = {},\n): TaskCompletionTimelineResult {\n const filtered = records.filter((r) => {\n if (!options.adapterType) return true;\n return r.adapterType === options.adapterType;\n });\n\n const turns: TaskCompletionTurnTimeline[] = [];\n let current: TaskCompletionTurnTimeline | null = null;\n let ignored = 0;\n\n filtered.forEach((record, index) => {\n if (record.event === 'busy_signal' && current && current.completed) {\n current = null;\n }\n\n if (!current) {\n current = {\n turn: turns.length + 1,\n startIndex: index,\n endIndex: index,\n completed: false,\n maxConfidence: 0,\n finalConfidence: 0,\n events: [],\n };\n turns.push(current);\n }\n\n const step = toStep(record, index);\n if (!step) {\n ignored++;\n return;\n }\n\n current.events.push(step);\n current.endIndex = index;\n current.maxConfidence = Math.max(current.maxConfidence, step.confidence);\n current.finalConfidence = step.confidence;\n\n if (step.status === 'completed') {\n current.completed = true;\n }\n });\n\n return {\n turns,\n totalRecords: filtered.length,\n ignoredRecords: ignored,\n };\n}\n\nfunction toStep(record: TaskCompletionTraceRecord, atIndex: number): TaskCompletionTimelineStep | null {\n const event = record.event;\n const confidence = scoreConfidence(record);\n\n if (event === 'transition_ready') {\n return withCommon(record, {\n event,\n atIndex,\n status: 'completed',\n confidence: 100,\n });\n }\n\n if (event === 'debounce_reject_signal' || event === 'debounce_reject_status') {\n return withCommon(record, {\n event,\n atIndex,\n status: 'rejected',\n confidence,\n });\n }\n\n if (record.detectLoading) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'active_loading',\n confidence,\n });\n }\n\n if (event === 'debounce_fire' && record.signal) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'likely_complete',\n confidence,\n });\n }\n\n if (\n event === 'busy_signal' ||\n event === 'debounce_schedule' ||\n event === 'debounce_fire'\n ) {\n return withCommon(record, {\n event,\n atIndex,\n status: 'active',\n confidence,\n });\n }\n\n return null;\n}\n\nfunction scoreConfidence(record: TaskCompletionTraceRecord): number {\n let score = 10;\n\n if (record.detectLoading) score -= 40;\n if (record.detectReady) score += 20;\n if (record.detectTaskComplete) score += 45;\n if (record.signal) score += 20;\n if (record.event === 'debounce_reject_signal' || record.event === 'debounce_reject_status') {\n score -= 30;\n }\n if (record.event === 'transition_ready') score = 100;\n\n if (score < 0) return 0;\n if (score > 100) return 100;\n return score;\n}\n\nfunction withCommon(\n record: TaskCompletionTraceRecord,\n step: Omit<TaskCompletionTimelineStep, 'signal' | 'detectTaskComplete' | 'detectReady' | 'detectLoading'>,\n): TaskCompletionTimelineStep {\n return {\n ...step,\n signal: record.signal,\n detectTaskComplete: record.detectTaskComplete,\n detectReady: record.detectReady,\n detectLoading: record.detectLoading,\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asBool(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nfunction asTimestamp(value: unknown): string | number | Date | undefined {\n if (typeof value === 'string' || typeof value === 'number' || value instanceof Date) {\n return value;\n }\n return undefined;\n}\n\n","/**\n * Base CLI Adapter\n *\n * Abstract base class with common functionality for CLI adapters.\n */\n\nimport { spawn } from 'child_process';\nimport type { CLIAdapter } from './adapter-interface';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n} from '../types';\n\n/**\n * Abstract base class for CLI adapters with common functionality\n */\nexport abstract class BaseCLIAdapter implements CLIAdapter {\n abstract readonly adapterType: string;\n abstract readonly displayName: string;\n\n /**\n * Auto-response rules for handling known blocking prompts.\n * Subclasses should override this to add CLI-specific rules.\n */\n readonly autoResponseRules: AutoResponseRule[] = [];\n\n /**\n * Whether this CLI uses TUI menus requiring arrow-key navigation.\n * Defaults to false; coding agent adapters override to true.\n */\n readonly usesTuiMenus: boolean = false;\n\n abstract getCommand(): string;\n abstract getArgs(config: SpawnConfig): string[];\n abstract getEnv(config: SpawnConfig): Record<string, string>;\n abstract detectLogin(output: string): LoginDetection;\n abstract detectReady(output: string): boolean;\n abstract parseOutput(output: string): ParsedOutput | null;\n abstract getPromptPattern(): RegExp;\n\n /**\n * Default exit detection - look for common exit patterns\n */\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n // Check for common exit/error patterns\n if (output.includes('Process exited with code')) {\n const match = output.match(/Process exited with code (\\d+)/);\n return {\n exited: true,\n code: match ? parseInt(match[1], 10) : 1,\n };\n }\n\n if (output.includes('Command not found') || output.includes('command not found')) {\n return {\n exited: true,\n code: 127,\n error: 'Command not found',\n };\n }\n\n return { exited: false };\n }\n\n /**\n * Default blocking prompt detection - looks for common prompt patterns.\n * Subclasses should override for CLI-specific detection.\n */\n detectBlockingPrompt(output: string): BlockingPromptDetection {\n let stripped = this.stripAnsi(output);\n\n // Strip TUI box-drawing/chrome characters so patterns work for ink/React CLIs\n // (Gemini CLI, Claude Code TUI mode, etc.)\n stripped = stripped.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⏺←→↑↓]/g, ' ');\n stripped = stripped.replace(/ {2,}/g, ' ');\n\n // Check for login/auth first (highest priority)\n const loginDetection = this.detectLogin(output);\n if (loginDetection.required) {\n return {\n detected: true,\n type: 'login',\n prompt: loginDetection.instructions,\n url: loginDetection.url,\n canAutoRespond: false,\n instructions: loginDetection.instructions,\n };\n }\n\n // Check for common update prompts\n if (/update (available|now|ready)/i.test(stripped) && /\\[y\\/n\\]/i.test(stripped)) {\n return {\n detected: true,\n type: 'update',\n prompt: 'Update available',\n options: ['y', 'n'],\n suggestedResponse: 'n',\n canAutoRespond: true,\n instructions: 'CLI update available - auto-declining to continue',\n };\n }\n\n // Check for terms of service / license acceptance\n if (/accept.*(terms|license|agreement)/i.test(stripped) && /\\[y\\/n\\]/i.test(stripped)) {\n return {\n detected: true,\n type: 'tos',\n prompt: 'Terms/license acceptance required',\n options: ['y', 'n'],\n canAutoRespond: false,\n instructions: 'Please accept the terms of service manually',\n };\n }\n\n // Check for model/version selection\n if (/choose.*model|select.*model|which model/i.test(stripped)) {\n return {\n detected: true,\n type: 'model_select',\n prompt: 'Model selection required',\n canAutoRespond: false,\n instructions: 'Please select a model',\n };\n }\n\n // Check for project/workspace selection\n if (/choose.*(project|workspace)|select.*(project|workspace)/i.test(stripped)) {\n return {\n detected: true,\n type: 'project_select',\n prompt: 'Project/workspace selection required',\n canAutoRespond: false,\n instructions: 'Please select a project or workspace',\n };\n }\n\n // Check for generic y/n prompts - multiple formats\n // [y/n], (y/n), [Y/n], [y/N], (Y)es/(N)o, Yes/No\n if (/\\[y\\/n\\]|\\(y\\/n\\)|\\[Y\\/n\\]|\\[y\\/N\\]|\\(Y\\)es\\/\\(N\\)o|Yes\\/No\\??/i.test(stripped)) {\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-200), // Last 200 chars for context\n options: ['y', 'n'],\n canAutoRespond: false,\n instructions: 'Confirmation prompt detected',\n };\n }\n\n // Check for numbered menu prompts (1. Yes / 2. No, or › 1. Yes)\n if (/^\\s*[›>]?\\s*[1-9]\\.\\s+\\w+/m.test(stripped) && /\\?\\s*$/m.test(stripped)) {\n // Extract numbered options\n const optionMatches = stripped.match(/[›>]?\\s*([1-9])\\.\\s+([^\\n]+)/g);\n const options = optionMatches\n ? optionMatches.map((m) => m.replace(/^[›>\\s]*/, '').trim())\n : [];\n\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-300),\n options: options.length > 0 ? options : undefined,\n canAutoRespond: false,\n instructions: 'Menu selection prompt detected',\n };\n }\n\n // Check for \"Enter to confirm\" / \"Press enter to continue\" style prompts\n if (/press enter|hit enter|enter to (confirm|continue|proceed)|press return/i.test(stripped)) {\n return {\n detected: true,\n type: 'unknown',\n prompt: stripped.slice(-200),\n suggestedResponse: '\\n',\n canAutoRespond: false,\n instructions: 'Enter/confirm prompt detected',\n };\n }\n\n // Check for trust/permission prompts (Claude Code style)\n if (/trust|allow|permission|grant access/i.test(stripped) && /\\?\\s*$/m.test(stripped)) {\n return {\n detected: true,\n type: 'permission',\n prompt: stripped.slice(-200),\n canAutoRespond: false,\n instructions: 'Permission/trust prompt detected',\n };\n }\n\n // Fallback: any line ending with ? that wasn't caught above\n // Only trigger if it looks like a standalone prompt (short, ends with ?)\n const lines = stripped.split('\\n').filter((l) => l.trim());\n const lastLine = lines[lines.length - 1] || '';\n if (/\\?\\s*$/.test(lastLine) && lastLine.length < 200) {\n return {\n detected: true,\n type: 'unknown',\n prompt: lastLine.trim(),\n canAutoRespond: false,\n instructions: 'Question prompt detected',\n };\n }\n\n return { detected: false };\n }\n\n /**\n * Default task completion detection — delegates to detectReady().\n * Subclasses should override to match high-confidence completion patterns\n * (e.g. duration summaries) that short-circuit the LLM stall classifier.\n */\n detectTaskComplete(output: string): boolean {\n return this.detectReady(output);\n }\n\n /**\n * Default input formatting - just return as-is\n */\n formatInput(message: string): string {\n return message;\n }\n\n /**\n * Validate CLI installation by running --version or --help\n */\n async validateInstallation(): Promise<{ installed: boolean; version?: string; error?: string }> {\n return new Promise((resolve) => {\n const command = this.getCommand();\n\n try {\n const proc = spawn(command, ['--version'], {\n shell: true,\n timeout: 5000,\n });\n\n let output = '';\n\n proc.stdout?.on('data', (data) => {\n output += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n output += data.toString();\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n // Try to extract version from output\n const versionMatch = output.match(/(\\d+\\.\\d+\\.\\d+)/);\n resolve({\n installed: true,\n version: versionMatch ? versionMatch[1] : undefined,\n });\n } else {\n resolve({\n installed: false,\n error: `Command exited with code ${code}`,\n });\n }\n });\n\n proc.on('error', (err) => {\n resolve({\n installed: false,\n error: err.message,\n });\n });\n } catch (err) {\n resolve({\n installed: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n });\n }\n });\n }\n\n /**\n * Helper to check if output contains a question\n */\n protected containsQuestion(output: string): boolean {\n const questionPatterns = [\n /\\?$/m, // Ends with ?\n /would you like/i,\n /do you want/i,\n /should I/i,\n /shall I/i,\n /please (choose|select|confirm)/i,\n /\\(y\\/n\\)/i,\n /\\[y\\/N\\]/i,\n /\\[Y\\/n\\]/i,\n ];\n\n return questionPatterns.some((pattern) => pattern.test(output));\n }\n\n /**\n * Helper to strip ANSI escape codes from output\n */\n protected stripAnsi(str: string): string {\n // Replace cursor-forward sequences (\\x1b[<n>C) with spaces before stripping.\n // TUI CLIs use these instead of literal spaces for word positioning.\n const withSpaces = str.replace(/\\x1b\\[\\d*C/g, ' ');\n // Strip OSC sequences: \\x1b] ... BEL or \\x1b] ... ST\n const withoutOsc = withSpaces.replace(/\\x1b\\](?:[^\\x07\\x1b]|\\x1b[^\\\\])*(?:\\x07|\\x1b\\\\)/g, '');\n // Strip DCS sequences: \\x1bP ... ST\n const withoutDcs = withoutOsc.replace(/\\x1bP(?:[^\\x1b]|\\x1b[^\\\\])*\\x1b\\\\/g, '');\n // eslint-disable-next-line no-control-regex\n return withoutDcs.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n }\n}\n","/**\n * Adapter Factory\n *\n * Factory function for creating CLI adapters from configuration.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\nimport { BaseCLIAdapter } from './base-adapter';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n AdapterFactoryConfig,\n} from '../types';\n\n/**\n * Creates a CLI adapter from configuration\n */\nexport function createAdapter(config: AdapterFactoryConfig): CLIAdapter {\n return new ConfiguredAdapter(config);\n}\n\n/**\n * Adapter implementation created from configuration\n */\nclass ConfiguredAdapter extends BaseCLIAdapter {\n readonly adapterType: string;\n readonly displayName: string;\n readonly autoResponseRules: AutoResponseRule[];\n\n constructor(private config: AdapterFactoryConfig) {\n super();\n this.adapterType = config.command.replace(/[^a-zA-Z0-9]/g, '-');\n this.displayName = config.command;\n this.autoResponseRules = this.buildAutoResponseRules();\n }\n\n private buildAutoResponseRules(): AutoResponseRule[] {\n if (!this.config.blockingPrompts) {\n return [];\n }\n\n return this.config.blockingPrompts\n .filter((p) => p.autoResponse !== undefined)\n .map((p) => ({\n pattern: p.pattern,\n type: p.type,\n response: p.autoResponse!,\n description: p.description || `Auto-respond to ${p.type} prompt`,\n safe: p.safe !== false,\n }));\n }\n\n getCommand(): string {\n return this.config.command;\n }\n\n getArgs(config: SpawnConfig): string[] {\n if (typeof this.config.args === 'function') {\n return this.config.args(config);\n }\n return this.config.args || [];\n }\n\n getEnv(config: SpawnConfig): Record<string, string> {\n if (typeof this.config.env === 'function') {\n return this.config.env(config);\n }\n return this.config.env || {};\n }\n\n detectLogin(output: string): LoginDetection {\n if (!this.config.loginDetection) {\n return { required: false };\n }\n\n const { patterns, extractUrl, extractInstructions } = this.config.loginDetection;\n const stripped = this.stripAnsi(output);\n\n for (const pattern of patterns) {\n if (pattern.test(stripped)) {\n return {\n required: true,\n type: 'browser',\n url: extractUrl?.(stripped) || undefined,\n instructions: extractInstructions?.(stripped) || 'Authentication required',\n };\n }\n }\n\n return { required: false };\n }\n\n detectBlockingPrompt(output: string): BlockingPromptDetection {\n // First check config-defined blocking prompts\n if (this.config.blockingPrompts) {\n const stripped = this.stripAnsi(output);\n\n for (const prompt of this.config.blockingPrompts) {\n if (prompt.pattern.test(stripped)) {\n return {\n detected: true,\n type: prompt.type,\n prompt: stripped.slice(-200),\n suggestedResponse: prompt.autoResponse,\n canAutoRespond: prompt.autoResponse !== undefined && prompt.safe !== false,\n instructions: prompt.description,\n };\n }\n }\n }\n\n // Fall back to base implementation\n return super.detectBlockingPrompt(output);\n }\n\n detectReady(output: string): boolean {\n if (!this.config.readyIndicators || this.config.readyIndicators.length === 0) {\n // Default: ready after any output\n return output.length > 10;\n }\n\n const stripped = this.stripAnsi(output);\n return this.config.readyIndicators.some((pattern) => pattern.test(stripped));\n }\n\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n if (this.config.exitIndicators) {\n for (const indicator of this.config.exitIndicators) {\n const match = output.match(indicator.pattern);\n if (match) {\n const code = indicator.codeExtractor?.(match) ?? 1;\n return { exited: true, code };\n }\n }\n }\n\n // Fall back to base implementation\n return super.detectExit(output);\n }\n\n parseOutput(output: string): ParsedOutput | null {\n if (this.config.parseOutput) {\n return this.config.parseOutput(output);\n }\n\n // Default parsing\n const cleaned = this.stripAnsi(output).trim();\n if (!cleaned) return null;\n\n return {\n type: 'response',\n content: cleaned,\n isComplete: true,\n isQuestion: this.containsQuestion(cleaned),\n };\n }\n\n formatInput(message: string): string {\n if (this.config.formatInput) {\n return this.config.formatInput(message);\n }\n return message;\n }\n\n getPromptPattern(): RegExp {\n return this.config.promptPattern || /[\\$#>]\\s*$/m;\n }\n}\n","/**\n * Shell Adapter\n *\n * Built-in adapter for bash/zsh shell sessions.\n */\n\nimport type { CLIAdapter } from './adapter-interface';\nimport type {\n SpawnConfig,\n ParsedOutput,\n LoginDetection,\n BlockingPromptDetection,\n AutoResponseRule,\n} from '../types';\n\n/**\n * Options for the shell adapter\n */\nexport interface ShellAdapterOptions {\n /** Shell to use (default: $SHELL or /bin/bash) */\n shell?: string;\n\n /** Custom prompt string (default: 'pty> ') */\n prompt?: string;\n}\n\n/**\n * Built-in adapter for shell sessions (bash/zsh)\n */\nexport class ShellAdapter implements CLIAdapter {\n readonly adapterType = 'shell';\n readonly displayName = 'Shell';\n readonly autoResponseRules: AutoResponseRule[] = [];\n\n private shell: string;\n private promptStr: string;\n\n constructor(options: ShellAdapterOptions = {}) {\n this.shell = options.shell || process.env.SHELL || '/bin/bash';\n this.promptStr = options.prompt || 'pty> ';\n }\n\n getCommand(): string {\n return this.shell;\n }\n\n getArgs(_config: SpawnConfig): string[] {\n return [];\n }\n\n getEnv(_config: SpawnConfig): Record<string, string> {\n return {\n PS1: this.promptStr,\n };\n }\n\n detectLogin(_output: string): LoginDetection {\n // Shell doesn't need login\n return { required: false };\n }\n\n detectBlockingPrompt(_output: string): BlockingPromptDetection {\n // Shell typically doesn't have blocking prompts\n return { detected: false };\n }\n\n detectReady(output: string): boolean {\n // Ready when we see the prompt or any meaningful output\n return output.includes(this.promptStr) || output.includes('$') || output.length > 10;\n }\n\n detectExit(output: string): { exited: boolean; code?: number; error?: string } {\n if (output.includes('exit')) {\n return { exited: true, code: 0 };\n }\n return { exited: false };\n }\n\n parseOutput(output: string): ParsedOutput | null {\n const cleaned = this.stripAnsi(output).trim();\n if (!cleaned) return null;\n\n return {\n type: 'response',\n content: cleaned,\n isComplete: true,\n isQuestion: false,\n };\n }\n\n formatInput(message: string): string {\n return message;\n }\n\n getPromptPattern(): RegExp {\n // Match our custom prompt or standard shell prompts\n const escaped = this.promptStr.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`(?:${escaped}|\\\\$|#|>)\\\\s*$`, 'm');\n }\n\n async validateInstallation(): Promise<{ installed: boolean; version?: string; error?: string }> {\n // Shell is always installed\n return { installed: true };\n }\n\n private stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])/g, '');\n }\n}\n","/**\n * Bun-Compatible PTY Manager\n *\n * A wrapper that spawns a Node.js worker process to handle PTY operations,\n * allowing pty-manager to work from Bun or other non-Node runtimes.\n */\n\nimport { spawn, ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport * as path from 'path';\nimport * as readline from 'readline';\nimport type { SpawnConfig, AutoResponseRule, BlockingPromptType, SessionStatus, StallClassification, AuthRequiredInfo } from './types';\n\n/**\n * Serialized auto-response rule for IPC (pattern as string instead of RegExp)\n */\nexport interface SerializedRule {\n pattern: string;\n flags?: string;\n type: BlockingPromptType;\n response: string;\n responseType?: 'text' | 'keys';\n keys?: string[];\n description: string;\n safe?: boolean;\n once?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: SessionStatus;\n pid: number | undefined;\n cols: number;\n rows: number;\n startedAt?: Date;\n lastActivityAt?: Date;\n error?: string;\n exitCode?: number;\n}\n\nexport interface BunPTYManagerOptions {\n /** Path to node executable (default: 'node') */\n nodePath?: string;\n /** Path to worker script (default: auto-detected) */\n workerPath?: string;\n /** Environment variables for worker process */\n env?: Record<string, string>;\n /**\n * Adapter modules to load in the worker process.\n * Each module should export a `createAllAdapters()` function that returns an array of adapters.\n * Example: ['coding-agent-adapters']\n */\n adapterModules?: string[];\n\n /** Enable stall detection (default: false) */\n stallDetectionEnabled?: boolean;\n /** Default stall timeout in ms (default: 8000) */\n stallTimeoutMs?: number;\n /**\n * External classification callback invoked when a stall is detected.\n * The worker emits stall_detected; this callback runs on the parent side.\n */\n onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number,\n ) => Promise<StallClassification | null>;\n}\n\ninterface PendingOperation {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeout: NodeJS.Timeout;\n}\n\n/**\n * PTY Manager that works with Bun and other non-Node runtimes\n * by spawning a Node.js worker process.\n */\nexport class BunCompatiblePTYManager extends EventEmitter {\n private worker: ChildProcess | null = null;\n private sessions: Map<string, WorkerSessionHandle> = new Map();\n private pending: Map<string, PendingOperation> = new Map();\n private ready = false;\n private readyPromise: Promise<void>;\n private readyResolve!: () => void;\n private nodePath: string;\n private workerPath: string;\n private env: Record<string, string>;\n private adapterModules: string[];\n private _stallDetectionEnabled: boolean;\n private _stallTimeoutMs: number;\n private _onStallClassify?: (\n sessionId: string,\n recentOutput: string,\n stallDurationMs: number,\n ) => Promise<StallClassification | null>;\n\n constructor(options: BunPTYManagerOptions = {}) {\n super();\n\n this.nodePath = options.nodePath || 'node';\n this.workerPath = options.workerPath || this.findWorkerPath();\n this.env = options.env || {};\n this.adapterModules = options.adapterModules || [];\n this._stallDetectionEnabled = options.stallDetectionEnabled ?? false;\n this._stallTimeoutMs = options.stallTimeoutMs ?? 8000;\n this._onStallClassify = options.onStallClassify;\n\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n this.startWorker();\n }\n\n private findWorkerPath(): string {\n // Try to find the worker script relative to this module\n const possiblePaths = [\n path.join(__dirname, 'pty-worker.js'),\n path.join(__dirname, '..', 'dist', 'pty-worker.js'),\n path.join(__dirname, '..', 'src', 'pty-worker.js'),\n ];\n\n // Return first path (we'll rely on Node to throw if it doesn't exist)\n return possiblePaths[0];\n }\n\n private startWorker(): void {\n this.worker = spawn(this.nodePath, [this.workerPath], {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env, ...this.env },\n });\n\n if (!this.worker.stdout || !this.worker.stdin) {\n throw new Error('Failed to create worker process pipes');\n }\n\n const rl = readline.createInterface({\n input: this.worker.stdout,\n terminal: false,\n });\n\n rl.on('line', (line) => this.handleWorkerMessage(line));\n\n this.worker.stderr?.on('data', (data) => {\n this.emit('worker_error', data.toString());\n });\n\n this.worker.on('exit', (code, signal) => {\n this.ready = false;\n this.worker = null;\n this.emit('worker_exit', { code, signal });\n\n // Reject all pending operations\n for (const [key, op] of this.pending) {\n clearTimeout(op.timeout);\n op.reject(new Error('Worker process exited'));\n this.pending.delete(key);\n }\n\n // Mark all sessions as stopped\n for (const session of this.sessions.values()) {\n session.status = 'stopped';\n }\n });\n\n this.worker.on('error', (err) => {\n this.emit('worker_error', err);\n });\n }\n\n private handleWorkerMessage(line: string): void {\n let event: Record<string, unknown>;\n\n try {\n event = JSON.parse(line);\n } catch {\n this.emit('worker_error', `Invalid JSON from worker: ${line}`);\n return;\n }\n\n const eventType = event.event as string;\n const id = event.id as string | undefined;\n\n switch (eventType) {\n case 'worker_ready':\n // Register adapter modules before marking as ready\n if (this.adapterModules.length > 0) {\n this.sendCommand({ cmd: 'registerAdapters', modules: this.adapterModules });\n }\n // Send stall detection config to worker\n if (this._stallDetectionEnabled) {\n this.sendCommand({\n cmd: 'configureStallDetection',\n enabled: true,\n timeoutMs: this._stallTimeoutMs,\n });\n }\n this.ready = true;\n this.readyResolve();\n this.emit('ready');\n break;\n\n case 'spawned': {\n // Get config from event (worker sends it back)\n const session: WorkerSessionHandle = {\n id: id!,\n name: (event.name as string) || id!,\n type: (event.type as string) || 'shell',\n status: 'starting',\n pid: event.pid as number,\n cols: (event.cols as number) || 80,\n rows: (event.rows as number) || 24,\n startedAt: new Date(),\n };\n this.sessions.set(id!, session);\n this.emit('session_started', session);\n break;\n }\n\n case 'output': {\n const session = this.sessions.get(id!);\n if (session) {\n session.lastActivityAt = new Date();\n }\n this.emit('data', { id, data: event.data });\n this.emit(`data:${id}`, event.data);\n break;\n }\n\n case 'ready': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'ready';\n session.lastActivityAt = new Date();\n this.emit('session_ready', session);\n }\n break;\n }\n\n case 'exit': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'stopped';\n session.exitCode = event.code as number;\n session.lastActivityAt = new Date();\n this.emit('session_stopped', session, event.code, event.signal);\n this.sessions.delete(id!);\n }\n break;\n }\n\n case 'error':\n if (id) {\n const session = this.sessions.get(id);\n if (session) {\n session.status = 'error';\n session.error = event.message as string;\n session.lastActivityAt = new Date();\n }\n this.emit('session_error', { id, error: event.message });\n } else {\n this.emit('worker_error', event.message);\n }\n break;\n\n case 'blocking_prompt': {\n const session = this.sessions.get(id!);\n if (session) {\n this.emit('blocking_prompt', session, event.promptInfo, event.autoResponded);\n }\n break;\n }\n\n case 'login_required': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'authenticating';\n this.emit('login_required', session, event.instructions, event.url);\n }\n break;\n }\n\n case 'auth_required': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'authenticating';\n this.emit('auth_required', session, event.info as AuthRequiredInfo);\n }\n break;\n }\n\n case 'message': {\n const msg = event.message as Record<string, unknown>;\n // Convert timestamp back to Date\n this.emit('message', {\n ...msg,\n timestamp: new Date(msg.timestamp as string),\n });\n break;\n }\n\n case 'question': {\n const session = this.sessions.get(id!);\n if (session) {\n this.emit('question', session, event.question);\n }\n break;\n }\n\n case 'status_changed': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = event.status as SessionStatus;\n session.lastActivityAt = new Date();\n this.emit('session_status_changed', session);\n }\n break;\n }\n\n case 'task_complete': {\n const session = this.sessions.get(id!);\n if (session) {\n session.status = 'ready';\n session.lastActivityAt = new Date();\n this.emit('task_complete', session);\n }\n break;\n }\n\n case 'stall_detected': {\n const session = this.sessions.get(id!);\n if (session) {\n const recentOutput = event.recentOutput as string;\n const stallDurationMs = event.stallDurationMs as number;\n this.emit('stall_detected', session, recentOutput, stallDurationMs);\n\n // Call external classifier on parent side, send result back to worker\n if (this._onStallClassify) {\n this._onStallClassify(id!, recentOutput, stallDurationMs)\n .then((classification) => {\n this.sendCommand({\n cmd: 'classifyStallResult',\n id: id!,\n classification,\n });\n })\n .catch(() => {\n // On error, send null to reset the timer\n this.sendCommand({\n cmd: 'classifyStallResult',\n id: id!,\n classification: null,\n });\n });\n }\n }\n break;\n }\n\n case 'list': {\n // Convert date strings back to Date objects\n const sessions = (event.sessions as Record<string, unknown>[]).map((s) => ({\n ...s,\n startedAt: s.startedAt ? new Date(s.startedAt as string) : undefined,\n lastActivityAt: s.lastActivityAt ? new Date(s.lastActivityAt as string) : undefined,\n })) as WorkerSessionHandle[];\n this.resolvePending('list', sessions);\n break;\n }\n\n case 'rules': {\n // Convert serialized rules back to AutoResponseRule objects\n const serializedRules = event.rules as SerializedRule[];\n const rules = serializedRules.map((r) => ({\n pattern: new RegExp(r.pattern, r.flags || ''),\n type: r.type,\n response: r.response,\n responseType: r.responseType,\n keys: r.keys,\n description: r.description,\n safe: r.safe,\n once: r.once,\n })) as AutoResponseRule[];\n this.resolvePending(`getRules:${id}`, rules);\n break;\n }\n\n case 'ack': {\n const cmd = event.cmd as string;\n const success = event.success as boolean;\n const pendingKey = id ? `${cmd}:${id}` : cmd;\n const pending = this.pending.get(pendingKey);\n\n if (pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(pendingKey);\n\n if (success) {\n pending.resolve(true);\n } else {\n pending.reject(new Error(event.error as string));\n }\n }\n break;\n }\n }\n }\n\n private sendCommand(cmd: Record<string, unknown>): void {\n if (!this.worker?.stdin) {\n throw new Error('Worker not available');\n }\n\n this.worker.stdin.write(JSON.stringify(cmd) + '\\n');\n }\n\n private createPending(key: string, timeoutMs = 30000): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(key);\n reject(new Error(`Operation ${key} timed out`));\n }, timeoutMs);\n\n this.pending.set(key, { resolve, reject, timeout });\n });\n }\n\n private resolvePending(key: string, value: unknown): void {\n const pending = this.pending.get(key);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pending.delete(key);\n pending.resolve(value);\n }\n }\n\n /**\n * Wait for the worker to be ready\n */\n async waitForReady(): Promise<void> {\n return this.readyPromise;\n }\n\n /**\n * Check if worker is ready\n */\n isReady(): boolean {\n return this.ready;\n }\n\n /**\n * Spawn a new PTY session\n */\n async spawn(config: SpawnConfig & { id: string }): Promise<WorkerSessionHandle> {\n await this.waitForReady();\n\n const { id } = config;\n\n this.sendCommand({ cmd: 'spawn', id, config });\n\n await this.createPending(`spawn:${id}`);\n\n return this.sessions.get(id)!;\n }\n\n /**\n * Send data to a session\n */\n async send(id: string, data: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'send', id, data });\n\n await this.createPending(`send:${id}`);\n }\n\n /**\n * Send special keys to a session\n */\n async sendKeys(id: string, keys: string | string[]): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'sendKeys', id, keys });\n\n await this.createPending(`sendKeys:${id}`);\n }\n\n /**\n * Paste text to a session\n */\n async paste(id: string, text: string, bracketed = true): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'paste', id, text, bracketed });\n\n await this.createPending(`paste:${id}`);\n }\n\n /**\n * Resize a session\n */\n async resize(id: string, cols: number, rows: number): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'resize', id, cols, rows });\n\n const session = this.sessions.get(id);\n if (session) {\n session.cols = cols;\n session.rows = rows;\n }\n\n await this.createPending(`resize:${id}`);\n }\n\n /**\n * Kill a session\n */\n async kill(id: string, signal?: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'kill', id, signal });\n\n await this.createPending(`kill:${id}`);\n }\n\n /**\n * Get a session by ID\n */\n get(id: string): WorkerSessionHandle | undefined {\n return this.sessions.get(id);\n }\n\n /**\n * List all sessions\n */\n async list(): Promise<WorkerSessionHandle[]> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'list' });\n\n const sessions = (await this.createPending('list')) as WorkerSessionHandle[];\n return sessions;\n }\n\n /**\n * Check if a session exists\n */\n has(id: string): boolean {\n return this.sessions.has(id);\n }\n\n /**\n * Subscribe to output from a specific session\n */\n onSessionData(id: string, callback: (data: string) => void): () => void {\n const handler = (data: string) => callback(data);\n this.on(`data:${id}`, handler);\n return () => this.off(`data:${id}`, handler);\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Runtime Auto-Response Rules API\n // ─────────────────────────────────────────────────────────────────────────────\n\n private serializeRule(rule: AutoResponseRule): SerializedRule {\n return {\n pattern: rule.pattern.source,\n flags: rule.pattern.flags || undefined,\n type: rule.type,\n response: rule.response,\n responseType: rule.responseType,\n keys: rule.keys,\n description: rule.description,\n safe: rule.safe,\n once: rule.once,\n };\n }\n\n /**\n * Add an auto-response rule to a session.\n * Session rules are checked before adapter rules.\n */\n async addAutoResponseRule(sessionId: string, rule: AutoResponseRule): Promise<void> {\n await this.waitForReady();\n\n const serialized = this.serializeRule(rule);\n this.sendCommand({ cmd: 'addRule', id: sessionId, rule: serialized });\n\n await this.createPending(`addRule:${sessionId}`);\n }\n\n /**\n * Remove an auto-response rule from a session by pattern.\n * Returns true if a rule was removed.\n */\n async removeAutoResponseRule(sessionId: string, pattern: RegExp): Promise<boolean> {\n await this.waitForReady();\n\n this.sendCommand({\n cmd: 'removeRule',\n id: sessionId,\n pattern: pattern.source,\n flags: pattern.flags || undefined,\n });\n\n try {\n await this.createPending(`removeRule:${sessionId}`);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Set all auto-response rules for a session, replacing existing ones.\n */\n async setAutoResponseRules(sessionId: string, rules: AutoResponseRule[]): Promise<void> {\n await this.waitForReady();\n\n const serialized = rules.map((r) => this.serializeRule(r));\n this.sendCommand({ cmd: 'setRules', id: sessionId, rules: serialized });\n\n await this.createPending(`setRules:${sessionId}`);\n }\n\n /**\n * Get all auto-response rules for a session.\n */\n async getAutoResponseRules(sessionId: string): Promise<AutoResponseRule[]> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'getRules', id: sessionId });\n\n const rules = (await this.createPending(`getRules:${sessionId}`)) as AutoResponseRule[];\n return rules;\n }\n\n /**\n * Select a TUI menu option by index (0-based) in a session.\n */\n async selectMenuOption(id: string, optionIndex: number): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'selectMenuOption', id, optionIndex });\n\n await this.createPending(`selectMenuOption:${id}`);\n }\n\n /**\n * Clear all auto-response rules for a session.\n */\n async clearAutoResponseRules(sessionId: string): Promise<void> {\n await this.waitForReady();\n\n this.sendCommand({ cmd: 'clearRules', id: sessionId });\n\n await this.createPending(`clearRules:${sessionId}`);\n }\n\n /**\n * Shutdown the worker and all sessions\n */\n async shutdown(): Promise<void> {\n if (!this.worker) return;\n\n this.sendCommand({ cmd: 'shutdown' });\n\n await this.createPending('shutdown', 10000).catch(() => {\n // Force kill if shutdown times out\n this.worker?.kill('SIGKILL');\n });\n }\n\n /**\n * Restart the worker process\n */\n async restart(): Promise<void> {\n await this.shutdown();\n\n this.sessions.clear();\n this.ready = false;\n this.readyPromise = new Promise((resolve) => {\n this.readyResolve = resolve;\n });\n\n this.startWorker();\n await this.waitForReady();\n }\n}\n\n/**\n * Detect if running in Bun\n */\nexport function isBun(): boolean {\n // Bun 1.1.24+ sets process.versions.bun (lowercase)\n return typeof process !== 'undefined' && 'bun' in process.versions;\n}\n\n/**\n * Create the appropriate PTY manager based on runtime\n */\nexport function createPTYManager(options?: BunPTYManagerOptions): BunCompatiblePTYManager {\n return new BunCompatiblePTYManager(options);\n}\n"],"mappings":"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","names":["import_events","import_child_process","import_events"]}
|