pty-manager 1.2.7 → 1.2.8
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 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -1
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +3 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -485,7 +485,9 @@ var PTYSession = class extends import_events.EventEmitter {
|
|
|
485
485
|
this._status = "stopped";
|
|
486
486
|
this.emit("exit", exitDetection.code || 0);
|
|
487
487
|
}
|
|
488
|
-
this.
|
|
488
|
+
if (this._status !== "starting" && this._status !== "authenticating") {
|
|
489
|
+
this.tryParseOutput();
|
|
490
|
+
}
|
|
489
491
|
});
|
|
490
492
|
this.ptyProcess.onExit(({ exitCode, signal }) => {
|
|
491
493
|
this._status = "stopped";
|
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/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';\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 BlockingPromptType,\n BlockingPromptDetection,\n AutoResponseRule,\n BlockingPromptInfo,\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';\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 type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AutoResponseRule,\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 blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n}\n\n/**\n * Console-based logger fallback\n */\nconst 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\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 constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\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(adapter, config, this.logger);\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('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\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 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 // 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 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 AutoResponseRule,\n Logger,\n} from './types';\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 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}\n\n/**\n * Console-based logger fallback\n */\nconst 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/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\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\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\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 // 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 // Emit raw output\n this.emit('output', data);\n\n // Check for blocking prompts\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Fallback: Check for login required (legacy support)\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.emit('login_required', loginDetection.instructions, loginDetection.url);\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n\n // Check for ready state\n if (this._status === 'starting' && this.adapter.detectReady(this.outputBuffer)) {\n this._status = 'ready';\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready');\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message\n this.tryParseOutput();\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\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 * Detect blocking prompts and handle them with auto-responses or user notification\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 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) {\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 this.writeRaw(detection.suggestedResponse + '\\r');\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 }\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 }\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\n const adapterRules = this.adapter.autoResponseRules || [];\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n for (const rule of allRules) {\n if (rule.pattern.test(this.outputBuffer)) {\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 this.writeRaw(rule.response + '\\r');\n\n // Clear the matched portion from buffer to prevent re-matching\n this.outputBuffer = this.outputBuffer.replace(rule.pattern, '');\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 send(message: string): SessionMessage {\n this._status = 'busy';\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 this.write(message);\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 * 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.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 * 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 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 const stripped = this.stripAnsi(output);\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 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 // eslint-disable-next-line no-control-regex\n return str.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 } 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 description: string;\n safe?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: 'starting' | 'ready' | 'stopped' | 'error';\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\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\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\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 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 this.emit('login_required', session, event.instructions, event.url);\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 '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 description: r.description,\n safe: r.safe,\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 description: rule.description,\n safe: rule.safe,\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 * 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","consoleLogger","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/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';\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 BlockingPromptType,\n BlockingPromptDetection,\n AutoResponseRule,\n BlockingPromptInfo,\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';\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 type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AutoResponseRule,\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 blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n}\n\n/**\n * Console-based logger fallback\n */\nconst 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\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 constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\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(adapter, config, this.logger);\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('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\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 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 // 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 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 AutoResponseRule,\n Logger,\n} from './types';\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 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}\n\n/**\n * Console-based logger fallback\n */\nconst 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/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\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\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\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 // 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 // Emit raw output\n this.emit('output', data);\n\n // Check for blocking prompts\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Fallback: Check for login required (legacy support)\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.emit('login_required', loginDetection.instructions, loginDetection.url);\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n\n // Check for ready state\n if (this._status === 'starting' && this.adapter.detectReady(this.outputBuffer)) {\n this._status = 'ready';\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready');\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message\n // Only parse once session is ready - during startup we need the buffer\n // to accumulate so detectReady can see the full startup output\n if (this._status !== 'starting' && this._status !== 'authenticating') {\n this.tryParseOutput();\n }\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\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 * Detect blocking prompts and handle them with auto-responses or user notification\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 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) {\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 this.writeRaw(detection.suggestedResponse + '\\r');\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 }\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 }\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\n const adapterRules = this.adapter.autoResponseRules || [];\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n for (const rule of allRules) {\n if (rule.pattern.test(this.outputBuffer)) {\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 this.writeRaw(rule.response + '\\r');\n\n // Clear the matched portion from buffer to prevent re-matching\n this.outputBuffer = this.outputBuffer.replace(rule.pattern, '');\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 send(message: string): SessionMessage {\n this._status = 'busy';\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 this.write(message);\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 * 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.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 * 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 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 const stripped = this.stripAnsi(output);\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 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 // eslint-disable-next-line no-control-regex\n return str.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 } 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 description: string;\n safe?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: 'starting' | 'ready' | 'stopped' | 'error';\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\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\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\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 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 this.emit('login_required', session, event.instructions, event.url);\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 '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 description: r.description,\n safe: r.safe,\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 description: rule.description,\n safe: rule.safe,\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 * 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","consoleLogger","import_child_process","import_events"]}
|
package/dist/index.mjs
CHANGED
|
@@ -447,7 +447,9 @@ var PTYSession = class extends EventEmitter {
|
|
|
447
447
|
this._status = "stopped";
|
|
448
448
|
this.emit("exit", exitDetection.code || 0);
|
|
449
449
|
}
|
|
450
|
-
this.
|
|
450
|
+
if (this._status !== "starting" && this._status !== "authenticating") {
|
|
451
|
+
this.tryParseOutput();
|
|
452
|
+
}
|
|
451
453
|
});
|
|
452
454
|
this.ptyProcess.onExit(({ exitCode, signal }) => {
|
|
453
455
|
this._status = "stopped";
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pty-manager.ts","../src/adapters/adapter-registry.ts","../src/pty-session.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 * 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 type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AutoResponseRule,\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 blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n}\n\n/**\n * Console-based logger fallback\n */\nconst 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\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 constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\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(adapter, config, this.logger);\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('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\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 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 // 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 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 AutoResponseRule,\n Logger,\n} from './types';\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 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}\n\n/**\n * Console-based logger fallback\n */\nconst 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/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\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\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\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 // 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 // Emit raw output\n this.emit('output', data);\n\n // Check for blocking prompts\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Fallback: Check for login required (legacy support)\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.emit('login_required', loginDetection.instructions, loginDetection.url);\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n\n // Check for ready state\n if (this._status === 'starting' && this.adapter.detectReady(this.outputBuffer)) {\n this._status = 'ready';\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready');\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message\n this.tryParseOutput();\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\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 * Detect blocking prompts and handle them with auto-responses or user notification\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 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) {\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 this.writeRaw(detection.suggestedResponse + '\\r');\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 }\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 }\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\n const adapterRules = this.adapter.autoResponseRules || [];\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n for (const rule of allRules) {\n if (rule.pattern.test(this.outputBuffer)) {\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 this.writeRaw(rule.response + '\\r');\n\n // Clear the matched portion from buffer to prevent re-matching\n this.outputBuffer = this.outputBuffer.replace(rule.pattern, '');\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 send(message: string): SessionMessage {\n this._status = 'busy';\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 this.write(message);\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 * 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.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 * 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 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 const stripped = this.stripAnsi(output);\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 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 // eslint-disable-next-line no-control-regex\n return str.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 } 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 description: string;\n safe?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: 'starting' | 'ready' | 'stopped' | 'error';\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\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\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\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 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 this.emit('login_required', session, event.instructions, event.url);\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 '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 description: r.description,\n safe: r.safe,\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 description: rule.description,\n safe: rule.safe,\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 * 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":["EventEmitter","consoleLogger","EventEmitter","spawn","EventEmitter"]}
|
|
1
|
+
{"version":3,"sources":["../src/pty-manager.ts","../src/adapters/adapter-registry.ts","../src/pty-session.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 * 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 type {\n SpawnConfig,\n SessionHandle,\n SessionMessage,\n SessionFilter,\n SessionStatus,\n BlockingPromptInfo,\n AutoResponseRule,\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 blocking_prompt: (session: SessionHandle, promptInfo: BlockingPromptInfo, autoResponded: boolean) => void;\n message: (message: SessionMessage) => void;\n question: (session: SessionHandle, question: string) => void;\n}\n\n/**\n * Console-based logger fallback\n */\nconst 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\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 constructor(config: PTYManagerConfig = {}) {\n super();\n this.adapters = new AdapterRegistry();\n this.logger = config.logger || consoleLogger;\n this.maxLogLines = config.maxLogLines || 1000;\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(adapter, config, this.logger);\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('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\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 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 // 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 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 AutoResponseRule,\n Logger,\n} from './types';\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 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}\n\n/**\n * Console-based logger fallback\n */\nconst 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/**\n * Generate a unique ID\n */\nfunction generateId(): string {\n return `pty-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\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\n public readonly id: string;\n public readonly config: SpawnConfig;\n\n constructor(\n private adapter: CLIAdapter,\n config: SpawnConfig,\n logger?: Logger\n ) {\n super();\n this.id = config.id || generateId();\n this.config = { ...config, id: this.id };\n this.logger = logger || consoleLogger;\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 // 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 // Emit raw output\n this.emit('output', data);\n\n // Check for blocking prompts\n const blockingPrompt = this.detectAndHandleBlockingPrompt();\n if (blockingPrompt) {\n return;\n }\n\n // Fallback: Check for login required (legacy support)\n const loginDetection = this.adapter.detectLogin(this.outputBuffer);\n if (loginDetection.required && this._status !== 'authenticating') {\n this._status = 'authenticating';\n this.emit('login_required', loginDetection.instructions, loginDetection.url);\n this.logger.warn(\n { sessionId: this.id, loginType: loginDetection.type },\n 'Login required'\n );\n return;\n }\n\n // Check for ready state\n if (this._status === 'starting' && this.adapter.detectReady(this.outputBuffer)) {\n this._status = 'ready';\n this.emit('ready');\n this.logger.info({ sessionId: this.id }, 'Session ready');\n }\n\n // Check for exit\n const exitDetection = this.adapter.detectExit(this.outputBuffer);\n if (exitDetection.exited) {\n this._status = 'stopped';\n this.emit('exit', exitDetection.code || 0);\n }\n\n // Try to parse output into structured message\n // Only parse once session is ready - during startup we need the buffer\n // to accumulate so detectReady can see the full startup output\n if (this._status !== 'starting' && this._status !== 'authenticating') {\n this.tryParseOutput();\n }\n });\n\n this.ptyProcess.onExit(({ exitCode, signal }) => {\n this._status = 'stopped';\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 * Detect blocking prompts and handle them with auto-responses or user notification\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 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) {\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 this.writeRaw(detection.suggestedResponse + '\\r');\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 }\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 }\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\n const adapterRules = this.adapter.autoResponseRules || [];\n const allRules = [...this.sessionRules, ...adapterRules];\n\n if (allRules.length === 0) {\n return false;\n }\n\n for (const rule of allRules) {\n if (rule.pattern.test(this.outputBuffer)) {\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 this.writeRaw(rule.response + '\\r');\n\n // Clear the matched portion from buffer to prevent re-matching\n this.outputBuffer = this.outputBuffer.replace(rule.pattern, '');\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 send(message: string): SessionMessage {\n this._status = 'busy';\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 this.write(message);\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 * 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.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 * 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 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 const stripped = this.stripAnsi(output);\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 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 // eslint-disable-next-line no-control-regex\n return str.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 } 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 description: string;\n safe?: boolean;\n}\n\nexport interface WorkerSessionHandle {\n id: string;\n name: string;\n type: string;\n status: 'starting' | 'ready' | 'stopped' | 'error';\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\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\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\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 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 this.emit('login_required', session, event.instructions, event.url);\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 '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 description: r.description,\n safe: r.safe,\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 description: rule.description,\n safe: rule.safe,\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 * 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":["EventEmitter","consoleLogger","EventEmitter","spawn","EventEmitter"]}
|
package/dist/pty-worker.js
CHANGED
|
@@ -468,7 +468,9 @@ var PTYSession = class extends import_events.EventEmitter {
|
|
|
468
468
|
this._status = "stopped";
|
|
469
469
|
this.emit("exit", exitDetection.code || 0);
|
|
470
470
|
}
|
|
471
|
-
this.
|
|
471
|
+
if (this._status !== "starting" && this._status !== "authenticating") {
|
|
472
|
+
this.tryParseOutput();
|
|
473
|
+
}
|
|
472
474
|
});
|
|
473
475
|
this.ptyProcess.onExit(({ exitCode, signal }) => {
|
|
474
476
|
this._status = "stopped";
|
package/package.json
CHANGED