handsoff 0.1.2-beta.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shared/pidfile.ts","../../src/shared/logger.ts","../../src/shared/session-logger.ts","../../src/core/agent/AgentRegistry.ts","../../src/core/session/SessionManager.ts","../../src/core/adapter/AgentAdapterRegistry.ts","../../src/core/session/Session.ts","../../src/shared/permissions.ts","../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/src/index.ts","../../node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/src/index.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/assert-valid-pattern.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/brace-expressions.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/unescape.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/ast.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/escape.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/index.ts","../../src/gateway/interaction-service.ts","../../src/gateway/index.ts","../../src/gateway/publisher.ts","../../src/core/agent/inbound-utils.ts","../../src/core/agent/BaseAgentAdapter.ts","../../src/core/agent/EventNormalizer.ts","../../src/core/agent/interaction-utils.ts","../../src/adapters/agent/claude/ClaudeHookAgentAdapter.ts","../../src/adapters/agent/claude/ClaudeRemoteAgentAdapter.ts","../../src/core/agent/TurnAggregator.ts","../../src/core/session-scanner/registry.ts","../../src/adapters/agent/claude/scanner.ts","../../src/adapters/agent/claude/sdk/query.ts","../../src/adapters/agent/claude/sdk/stream.ts","../../src/adapters/agent/claude/sdk/types.ts","../../src/adapters/agent/claude/hook-types.ts","../../src/adapters/agent/codex/CodexAppAgentAdapter.ts","../../src/adapters/agent/codex/codexAppServerClient.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/shared/credentials.ts","../../src/adapters/interaction/queue.ts","../../src/config.ts","../../src/core/bus/index.ts","../../src/core/channel/registry.ts","../../src/core/channel/manager.ts","../../src/core/binding/BindingService.ts","../../src/core/command/routing.ts","../../src/core/routing/InboundRouter.ts","../../src/core/command/parser.ts","../../src/core/command/executor.ts","../../src/core/command/builtin/bind.ts","../../src/core/command/builtin/help.ts","../../src/core/command/builtin/session.ts","../../src/core/command/builtin/start.ts","../../src/core/command/builtin/system.ts","../../src/core/command/builtin/index.ts","../../src/core/command/index.ts","../../src/gateway/handlers/command.ts","../../src/gateway/handlers/permission.ts","../../src/gateway/handlers/index.ts","../../src/gateway/notification-handler.ts","../../src/core/channel/base.ts","../../src/adapters/channels/telegram/bot.ts","../../src/i18n/index.ts","../../src/i18n/locales/en.ts","../../src/gateway/notification-context.ts","../../src/adapters/channels/telegram/formatter.ts","../../src/shared/channelInstance.ts","../../src/adapters/channels/telegram/index.ts","../../src/adapters/channels/logger/index.ts","../../src/adapters/channels/feishu/client.ts","../../src/adapters/channels/feishu/formatter.ts","../../src/adapters/channels/feishu/index.ts","../../src/adapters/channels/app/mapper.ts","../../src/adapters/channels/app/index.ts","../../src/adapters/channels/app/server.ts","../../src/adapters/channels/app/protocol.ts","../../src/adapters/channels/app/query-service.ts","../../src/core/session/SessionRecoveryService.ts","../../src/gateway/process.ts"],"sourcesContent":["import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { mkdirSync } from 'fs';\n\nexport interface PidFileData {\n pid: number;\n port: number;\n startedAt: string;\n version?: string;\n agents?: string[];\n channels?: string[];\n token?: string;\n}\n\nexport function writePidFile(pidFilePath: string, data: PidFileData): void {\n // Validate pid is a positive integer\n if (!Number.isInteger(data.pid) || data.pid <= 0) {\n throw new TypeError(`Invalid pid: ${data.pid}. Must be a positive integer.`);\n }\n\n // Validate port is a positive integer between 1-65535\n if (!Number.isInteger(data.port) || data.port < 1 || data.port > 65535) {\n throw new TypeError(`Invalid port: ${data.port}. Must be an integer between 1 and 65535.`);\n }\n\n mkdirSync(dirname(pidFilePath), { recursive: true });\n writeFileSync(pidFilePath, JSON.stringify(data, null, 2));\n}\n\nexport function readPidFile(pidFilePath: string): PidFileData | null {\n if (!existsSync(pidFilePath)) {\n return null;\n }\n try {\n const content = readFileSync(pidFilePath, 'utf-8');\n return JSON.parse(content) as PidFileData;\n } catch {\n return null;\n }\n}\n\nexport function removePidFile(pidFilePath: string): void {\n if (existsSync(pidFilePath)) {\n unlinkSync(pidFilePath);\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import pino from 'pino';\nimport { mkdirSync, existsSync, appendFileSync } from 'fs';\nimport { dirname } from 'path';\nimport { hostname } from 'os';\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\nlet fileLogger: pino.Logger | null = null;\nlet consoleLogger: pino.Logger | null = null;\nlet currentLogLevel: LogLevel = LogLevel.INFO;\n\nfunction createSyncLogger(logFilePath: string, minLevel: LogLevel = LogLevel.INFO): pino.Logger {\n const hostnameValue = hostname();\n\n const writeLog = (level: string, msg: string, obj?: object) => {\n try {\n const logDir = dirname(logFilePath);\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n const logEntry: Record<string, unknown> = {\n level,\n time: Date.now(),\n msg,\n pid: process.pid,\n hostname: hostnameValue,\n ...obj,\n };\n const line = JSON.stringify(logEntry) + '\\n';\n appendFileSync(logFilePath, line);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`[Logger] Failed to write to ${logFilePath}:`, err);\n }\n };\n\n const log = (logLevel: string) => {\n const minLevelNum = LOG_LEVEL_MAP[minLevel] ?? LOG_LEVEL_MAP.info;\n const callLevelNum = LOG_LEVEL_MAP[logLevel] ?? LOG_LEVEL_MAP.info;\n return (obj: object | string, msg?: string) => {\n if (callLevelNum < minLevelNum) return;\n if (typeof obj === 'string') {\n writeLog(logLevel, obj);\n } else {\n writeLog(logLevel, msg || '', obj);\n }\n };\n };\n\n const createChild = (_bindings: object): pino.Logger => {\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n };\n\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n\nexport function setupFileLogging(logFilePath: string, level: LogLevel = LogLevel.INFO): pino.Logger {\n currentLogLevel = level;\n fileLogger = createSyncLogger(logFilePath, level);\n return fileLogger;\n}\n\nexport function getFileLogger(): pino.Logger | null {\n return fileLogger;\n}\n\nexport function createChannelLogger(channelName: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/channels/${channelName}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createAgentLogger(agentType: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/agents/${agentType}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createSessionLogger(sessionId: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const date = new Date().toISOString().split('T')[0];\n const logFile = `${homedir}/.handsoff/logs/sessions/${date}/${sessionId}.jsonl`;\n\n // Session logs are always written (NDJSON timeline), ignore currentLogLevel\n return createSyncLogger(logFile, LogLevel.DEBUG);\n}\n\nexport function getLogger(_level?: LogLevel): pino.Logger {\n if (!consoleLogger) {\n // Prefer fileLogger's level if set, otherwise use provided level or default to INFO\n const effectiveLevel = _level ?? (fileLogger ? (fileLogger as unknown as { level: string }).level as LogLevel : LogLevel.INFO);\n consoleLogger = pino({\n level: effectiveLevel,\n });\n }\n\n const delegate = (method: 'info' | 'warn' | 'error' | 'debug') => {\n return (obj: object | string, msg?: string) => {\n const target = fileLogger || consoleLogger;\n if (target) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (target as any)[method](obj, msg);\n }\n };\n };\n\n return {\n info: delegate('info'),\n warn: delegate('warn'),\n error: delegate('error'),\n debug: delegate('debug'),\n child: () => getLogger(_level),\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n","import type { EventBus } from '../core/bus/index.js';\nimport { createSessionLogger } from './logger.js';\n\nexport class SessionLogger {\n private bus: EventBus;\n private unsubscribeFns: Array<() => void> = [];\n private requestIdToSessionId = new Map<string, string>();\n private sessionLoggers = new Map<string, ReturnType<typeof createSessionLogger>>();\n\n constructor(bus: EventBus) {\n this.bus = bus;\n }\n\n start(): void {\n this.unsubscribeFns.push(\n this.bus.onInbound((e) => {\n if (!e.targetAgent) {\n return;\n }\n\n const sessionId = `${e.targetAgent}-${e.chatId}`;\n this.write(sessionId, 'inbound:message', 'inbound', {\n channel: e.channel,\n channelInstanceId: e.channelInstanceId,\n chatId: e.chatId,\n messageId: e.messageId,\n targetAgent: e.targetAgent,\n agentCommand: e.agentCommand,\n systemCommand: e.systemCommand,\n textPreview: e.text.slice(0, 240),\n });\n })\n );\n this.unsubscribeFns.push(\n this.bus.onSessionStart((e) => this.write(e.sessionId, 'session:start', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionEnd((e) => this.write(e.sessionId, 'session:end', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onTurnFinished((e) => this.write(e.sessionId, 'turn:finished', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolExecuted((e) => this.write(e.sessionId, 'tool:executed', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionRequest((e) => {\n this.requestIdToSessionId.set(e.requestId, e.sessionId);\n this.write(e.sessionId, 'interaction:request', 'inbound', e);\n })\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionResponse((e) => {\n const sessionId = this.requestIdToSessionId.get(e.requestId);\n if (sessionId) {\n this.write(sessionId, 'interaction:response', 'inbound', e);\n this.requestIdToSessionId.delete(e.requestId);\n }\n })\n );\n this.unsubscribeFns.push(\n this.bus.onTurnFinished((e) => this.write(e.sessionId, 'turn:finished', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onOutbound((e) => {\n const sessionId = (e.context as any)?.sessionId;\n if (sessionId) {\n this.write(sessionId, 'outbound:message', 'outbound', e);\n }\n })\n );\n }\n\n stop(): void {\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n }\n\n private write(\n sessionId: string,\n event: string,\n direction: 'inbound' | 'outbound' | 'agent' | 'system',\n payload: unknown\n ): void {\n let logger = this.sessionLoggers.get(sessionId);\n if (!logger) {\n logger = createSessionLogger(sessionId);\n this.sessionLoggers.set(sessionId, logger);\n }\n logger.info({ ts: new Date().toISOString(), event, direction, payload });\n }\n}\n","import { randomBytes } from 'crypto';\n\n/**\n * AgentRegistry - handles token-based agent registration and authorization\n * Maintains the token -> agentType mapping\n */\nexport class AgentRegistry {\n private registrations = new Map<string, string>();\n\n registerAgent(agentType: string, customToken?: string): string {\n const token = customToken ?? this.generateToken();\n this.registrations.set(token, agentType);\n return token;\n }\n\n unregisterAgent(token: string): boolean {\n return this.registrations.delete(token);\n }\n\n isTokenRegistered(token: string): boolean {\n return this.registrations.has(token);\n }\n\n getAgentType(token: string): string | undefined {\n return this.registrations.get(token);\n }\n\n listRegisteredAgents(): { token: string; agentType: string }[] {\n return Array.from(this.registrations.entries()).map(([token, agentType]) => ({\n token,\n agentType,\n }));\n }\n\n private generateToken(): string {\n return randomBytes(16).toString('hex');\n }\n}\n","// src/core/session/SessionManager.ts\n\nimport { randomUUID } from 'crypto';\nimport { getLogger } from '../../shared/logger.js';\nimport { AgentAdapterRegistry } from '../adapter/AgentAdapterRegistry.js';\nimport type { AgentType, CreateSessionOptions } from '../adapter/types.js';\nimport type { SessionInfo } from './types.js';\nimport { Session } from './Session.js';\n\nexport class SessionManager {\n private sessions = new Map<string, Session>();\n private logger = getLogger();\n\n async createSession(\n agentType: AgentType,\n options?: CreateSessionOptions & { token?: string }\n ): Promise<Session> {\n const adapter = AgentAdapterRegistry.getInstance().getAdapter(agentType);\n if (!adapter) {\n throw new Error(`No adapter found for agent type: ${agentType}`);\n }\n\n const sessionId = options?.sessionId ?? randomUUID();\n const transportState = await adapter.createTransportState({\n ...options,\n });\n\n const transportCwd = transportState.cwd as string | undefined;\n const cwd = options?.cwd || transportCwd || undefined;\n this.logger.debug({ sessionId, optionsCwd: options?.cwd, transportCwd, resolvedCwd: cwd }, '[SessionManager] Resolved cwd for session');\n\n const session = new Session({\n id: sessionId,\n agentType,\n adapter,\n transportState,\n token: options?.token,\n metadata: options?.metadata,\n cwd,\n });\n\n this.sessions.set(sessionId, session);\n this.logger.info({ sessionId, agentType, cwd, token: options?.token?.slice(0, 8) }, '[Session] Created');\n\n return session;\n }\n\n async closeSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n await session.close();\n this.sessions.delete(sessionId);\n this.logger.info({ sessionId }, '[Session] Closed');\n }\n\n getSession(sessionId: string): Session | undefined {\n return this.sessions.get(sessionId);\n }\n\n getSessionInfo(sessionId: string): SessionInfo | undefined {\n return this.sessions.get(sessionId)?.toInfo();\n }\n\n listSessions(): SessionInfo[] {\n return Array.from(this.sessions.values()).map(s => s.toInfo());\n }\n\n listSessionsByAgent(agentType: AgentType): SessionInfo[] {\n return this.listSessions().filter(s => s.agentType === agentType);\n }\n\n getSessionCount(): number {\n return this.sessions.size;\n }\n}\n","import type { AgentAdapter } from './AgentAdapter.js';\nimport type { AgentType, TransportType } from './types.js';\n\n/**\n * Adapter Registry\n * Manages registration and discovery of all AgentAdapter instances\n */\nexport class AgentAdapterRegistry {\n private static instance: AgentAdapterRegistry | null = null;\n private adapters: Map<string, AgentAdapter> = new Map();\n\n private constructor() {}\n\n static getInstance(): AgentAdapterRegistry {\n if (!AgentAdapterRegistry.instance) {\n AgentAdapterRegistry.instance = new AgentAdapterRegistry();\n }\n return AgentAdapterRegistry.instance;\n }\n\n /**\n * Register adapter (uses agentType:transportType as key)\n */\n register(adapter: AgentAdapter): void {\n const key = this.makeKey(adapter.agentType, adapter.transportType);\n if (this.adapters.has(key)) {\n console.warn(`Adapter ${key} already registered, overwriting...`);\n }\n this.adapters.set(key, adapter);\n }\n\n /**\n * Get adapter\n */\n get(agentType: AgentType, transportType: TransportType): AgentAdapter | undefined {\n return this.adapters.get(this.makeKey(agentType, transportType));\n }\n\n /**\n * Get adapter by agent type (returns first available transport)\n */\n getAdapter(agentType: 'claude' | 'codex'): AgentAdapter | undefined {\n const adapters = this.getAllForAgent(agentType);\n return adapters.length > 0 ? adapters[0] : undefined;\n }\n\n /**\n * Get all adapters for a specific agent type\n */\n getAllForAgent(agentType: AgentType): AgentAdapter[] {\n return Array.from(this.adapters.values()).filter(\n (a) => a.agentType === agentType\n );\n }\n\n /**\n * List all available (agentType, transportType) combinations\n */\n listAvailable(): Array<{ agentType: AgentType; transportType: TransportType }> {\n return Array.from(this.adapters.values()).map((a) => ({\n agentType: a.agentType,\n transportType: a.transportType,\n }));\n }\n\n /**\n * Check if adapter exists\n */\n has(agentType: AgentType, transportType: TransportType): boolean {\n return this.adapters.has(this.makeKey(agentType, transportType));\n }\n\n /**\n * Reset (for testing)\n */\n reset(): void {\n this.adapters.clear();\n }\n\n private makeKey(agentType: AgentType, transportType: TransportType): string {\n return `${agentType}:${transportType}`;\n }\n}\n\n/**\n * Adapter decorator factory\n * Used for automatic adapter registration\n *\n * @note The setTimeout cannot be cancelled. This decorator should only be used\n * for adapters that are registered once at application startup.\n */\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function registerAdapter(agentType: AgentType, transportType: TransportType): (target: Function) => Function {\n return function (target: Function): Function {\n const registry = AgentAdapterRegistry.getInstance();\n // Delay instantiation until all modules are loaded\n setTimeout(() => {\n const instance = new (target as new (...args: unknown[]) => AgentAdapter)();\n if (instance.agentType === agentType && instance.transportType === transportType) {\n registry.register(instance);\n }\n }, 0);\n return target;\n };\n}\n","// src/core/session/Session.ts\n\nimport type { AgentAdapter, TransportState } from '../adapter/AgentAdapter.js';\nimport type { AgentCommand, AgentType } from '../adapter/types.js';\nimport type { SessionInfo } from './types.js';\n\nexport class Session {\n readonly id: string;\n readonly agentType: AgentType;\n readonly token?: string;\n readonly metadata: Record<string, unknown>;\n readonly adapter: AgentAdapter;\n readonly createdAt: number;\n readonly cwd?: string;\n\n private status: 'active' | 'closed' | 'archived' = 'active';\n private transportState: TransportState;\n\n constructor(options: {\n id: string;\n agentType: 'claude' | 'codex';\n adapter: AgentAdapter;\n transportState: TransportState;\n token?: string;\n metadata?: Record<string, unknown>;\n cwd?: string;\n }) {\n this.id = options.id;\n this.agentType = options.agentType;\n this.token = options.token;\n this.metadata = options.metadata ?? {};\n this.adapter = options.adapter;\n this.transportState = options.transportState;\n this.createdAt = Date.now();\n this.cwd = options.cwd;\n }\n\n async sendCommand(command: AgentCommand): Promise<void> {\n if (this.status !== 'active') {\n throw new Error(`Cannot send command to closed session: ${this.id}`);\n }\n return this.adapter.sendCommand(this.transportState, command);\n }\n\n async close(): Promise<void> {\n if (this.status !== 'active') {\n return;\n }\n await this.adapter.closeTransportState(this.transportState);\n this.status = 'closed';\n }\n\n getStatus(): 'active' | 'closed' | 'archived' {\n return this.status;\n }\n\n toInfo(): SessionInfo {\n return {\n id: this.id,\n agentType: this.agentType,\n status: this.status,\n createdAt: this.createdAt,\n updatedAt: Date.now(),\n token: this.token,\n startedAt: new Date(this.createdAt),\n cwd: this.cwd,\n };\n }\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { getLogger } from './logger.js';\nimport { minimatch } from 'minimatch';\n\nexport interface PermissionRule {\n tool: string;\n pattern?: string;\n raw: string;\n}\n\nexport interface PermissionsConfig {\n allow: PermissionRule[];\n deny: PermissionRule[];\n ask: PermissionRule[];\n defaultMode: 'acceptEdits' | 'prompt' | 'auto' | 'default';\n}\n\nconst logger = getLogger();\n\n/**\n * Parse a permission rule like \"Bash(rm *)\" or \"Edit(./src/**)\"\n */\nfunction parseRule(rule: string): PermissionRule {\n const match = rule.match(/^([^(]+)(?:\\((.+)\\))?$/);\n if (!match) {\n return { tool: rule, raw: rule };\n }\n return {\n tool: match[1].trim(),\n pattern: match[2]?.trim(),\n raw: rule,\n };\n}\n\n/**\n * Load permissions config from project's .claude/settings.local.json\n */\nexport function loadPermissionsConfig(cwd: string): PermissionsConfig | null {\n const configPath = join(cwd, '.claude', 'settings.local.json');\n\n if (!existsSync(configPath)) {\n logger.debug(`[Permissions] No config found at ${configPath}`);\n return null;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content);\n\n const permissions = config.permissions || {};\n\n return {\n allow: (permissions.allow || []).map(parseRule),\n deny: (permissions.deny || []).map(parseRule),\n ask: (permissions.ask || []).map(parseRule),\n defaultMode: permissions.defaultMode || 'default',\n };\n } catch (error) {\n logger.warn(`[Permissions] Failed to load config from ${configPath}:`, error);\n return null;\n }\n}\n\n/**\n * Check if a tool input matches a pattern\n * Examples:\n * \"rm a.txt\" matches \"rm *\"\n * \"./src/config.ts\" matches \"./src/**\"\n */\nfunction matchesPattern(input: string, pattern: string): boolean {\n // Handle glob patterns\n if (pattern.includes('*') || pattern.includes('?')) {\n return minimatch(input, pattern, { matchBase: true });\n }\n // Exact match\n return input === pattern;\n}\n\n/**\n * Check if a tool matches a permission rule\n */\nfunction matchesRule(toolName: string, toolInput: Record<string, unknown>, rule: PermissionRule): boolean {\n // Tool name must match\n if (rule.tool !== toolName) {\n return false;\n }\n\n // If no pattern, match any usage of this tool\n const pattern = rule.pattern;\n if (!pattern) {\n return true;\n }\n\n // For Bash / codex_exec_command with string command\n if ((toolName === 'Bash' || toolName === 'codex_exec_command') && typeof toolInput.command === 'string') {\n const command = toolInput.command;\n // Extract the first word (the actual command)\n const firstWord = command.trim().split(/\\s+/)[0];\n return matchesPattern(command, pattern) || matchesPattern(firstWord, pattern);\n }\n\n // For codex_exec_command with string[] command\n if (toolName === 'codex_exec_command' && Array.isArray(toolInput.command)) {\n const command = (toolInput.command as string[]).join(' ');\n const firstWord = command.trim().split(/\\s+/)[0];\n return matchesPattern(command, pattern) || matchesPattern(firstWord, pattern);\n }\n\n // For file operations (Read, Edit, Write, etc.), match against file_path\n if (typeof toolInput.file_path === 'string') {\n return matchesPattern(toolInput.file_path, pattern);\n }\n\n // For codex_patch_apply with fileChanges object\n if (toolName === 'codex_patch_apply' && toolInput.fileChanges && typeof toolInput.fileChanges === 'object') {\n const paths = Object.keys(toolInput.fileChanges as Record<string, unknown>);\n return paths.some((path) => matchesPattern(path, pattern));\n }\n\n return false;\n}\n\nexport type PermissionDecision = 'allow' | 'deny' | 'ask';\n\n/**\n * Determine permission decision based on config and tool usage\n */\nexport function checkPermission(\n toolName: string,\n toolInput: Record<string, unknown>,\n config: PermissionsConfig | null\n): { decision: PermissionDecision; reason: string } {\n // No config - default to ask\n if (!config) {\n return { decision: 'ask', reason: 'No permissions config found' };\n }\n\n // Check deny list first (highest priority)\n for (const rule of config.deny) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'deny', reason: `Matches deny rule: ${rule.raw}` };\n }\n }\n\n // Check allow list\n for (const rule of config.allow) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'allow', reason: `Matches allow rule: ${rule.raw}` };\n }\n }\n\n // Check ask list\n for (const rule of config.ask) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'ask', reason: `Matches ask rule: ${rule.raw}` };\n }\n }\n\n // Default based on defaultMode\n if (config.defaultMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit', 'codex_patch_apply'].includes(toolName)) {\n return { decision: 'allow', reason: 'defaultMode is acceptEdits' };\n }\n\n return { decision: 'ask', reason: 'No matching rule, default to ask' };\n}\n\n/**\n * Check if we need to intercept based on permission_mode\n */\nexport function shouldIntercept(permissionMode: string): boolean {\n // Only intercept modes that would show permission dialogs\n return permissionMode === 'prompt' || permissionMode === 'default';\n}\n\n/**\n * Check only deny rules\n * @param toolName The name of the tool to check\n * @param toolInput The tool input/arguments\n * @param config The permissions configuration\n * @returns Decision object with 'deny' or 'allow' and reason\n */\nexport function checkDenyOnly(\n toolName: string,\n toolInput: Record<string, unknown>,\n config: PermissionsConfig | null\n): { decision: PermissionDecision; reason: string } {\n if (!config) {\n return { decision: 'allow', reason: 'No config, allow low-risk tool' };\n }\n\n for (const rule of config.deny) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'deny', reason: `Matches deny rule: ${rule.raw}` };\n }\n }\n\n return { decision: 'allow', reason: 'Low-risk tool, no deny match' };\n}\n","export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n","import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\nfunction expand_(str: string, max: number, isTop: boolean): string[] {\n /** @type {string[]} */\n const expansions: string[] = []\n\n const m = balanced('{', '}', str)\n if (!m) return [str]\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n const post: string[] = m.post.length ? expand_(m.post, max, false) : ['']\n\n if (/\\$$/.test(m.pre)) {\n for (let k = 0; k < post.length && k < max; k++) {\n const expansion = pre + '{' + m.body + '}' + post[k]\n expansions.push(expansion)\n }\n } else {\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n return expand_(str, max, true)\n }\n return [str]\n }\n\n let n: string[]\n if (isSequence) {\n n = m.body.split(/\\.\\./)\n } else {\n n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n return post.map(p => m.pre + n[0] + p)\n }\n /* c8 ignore stop */\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n let N: string[]\n\n if (isSequence && n[0] !== undefined && n[1] !== undefined) {\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ?\n Math.max(Math.abs(numeric(n[2])), 1)\n : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n N = []\n\n for (let i = x; test(i, y); i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n N.push(c)\n }\n } else {\n N = []\n\n for (let j = 0; j < n.length; j++) {\n N.push.apply(N, expand_(n[j] as string, max, false))\n }\n }\n\n for (let j = 0; j < N.length; j++) {\n for (let k = 0; k < post.length && expansions.length < max; k++) {\n const expansion = pre + N[j] + post[k]\n if (!isTop || isSequence || expansion) {\n expansions.push(expansion)\n }\n }\n }\n }\n\n return expansions\n}\n","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: unknown) => void = (\n pattern: unknown,\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } =\n {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n }\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean,\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number,\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'\n : ranges.length ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then\n * square-bracket escapes are removed, but not backslash escapes.\n *\n * For example, it will turn the string `'[*]'` into `*`, but it will not\n * turn `'\\\\*'` into `'*'`, because `\\` is a path separator in\n * `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both square-bracket escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n *\n * When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be\n * unescaped.\n */\n\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = true,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\])\\]/g, '$1$2')\n .replace(/\\\\([^/])/g, '$1')\n }\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\{}])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\{}])\\]/g, '$1$2')\n .replace(/\\\\([^/{}])/g, '$1')\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport type { MinimatchOptions, MMRegExp } from './index.js'\nimport { unescape } from './unescape.js'\n\n// classes [] are handled by the parseClass method\n// for positive extglobs, we sub-parse the contents, and combine,\n// with the appropriate regexp close.\n// for negative extglobs, we sub-parse the contents, but then\n// have to include the rest of the pattern, then the parent, etc.,\n// as the thing that cannot be because RegExp negative lookaheads\n// are different from globs.\n//\n// So for example:\n// a@(i|w!(x|y)z|j)b => ^a(i|w((!?(x|y)zb).*)z|j)b$\n// 1 2 3 4 5 6 1 2 3 46 5 6\n//\n// Assembling the extglob requires not just the negated patterns themselves,\n// but also anything following the negative patterns up to the boundary\n// of the current pattern, plus anything following in the parent pattern.\n//\n//\n// So, first, we parse the string into an AST of extglobs, without turning\n// anything into regexps yet.\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y']}, 'z'], ['j']]}, 'b']\n//\n// Then, for all the negative extglobs, we append whatever comes after in\n// each parent as their tail\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y'], 'z', 'b'}, 'z'], ['j']]}, 'b']\n//\n// Lastly, we turn each of these pieces into a regexp, and join\n//\n// v----- .* because there's more following,\n// v v otherwise, .+ because it must be\n// v v *something* there.\n// ['^a', {@ ['i', 'w(?:(!?(?:x|y).*zb$).*)z', 'j' ]}, 'b$']\n// copy what follows into here--^^^^^\n// ['^a', '(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)', 'b$']\n// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']\n\nexport type ExtglobType = '!' | '?' | '+' | '*' | '@'\nconst types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])\nconst isExtglobType = (c: string | null): c is ExtglobType =>\n types.has(c as ExtglobType)\nconst isExtglobAST = (c: AST): c is AST & { type: ExtglobType } =>\n isExtglobType(c.type)\n\n// Map of which extglob types can adopt the children of a nested extglob\n//\n// anything but ! can adopt a matching type:\n// +(a|+(b|c)|d) => +(a|b|c|d)\n// *(a|*(b|c)|d) => *(a|b|c|d)\n// @(a|@(b|c)|d) => @(a|b|c|d)\n// ?(a|?(b|c)|d) => ?(a|b|c|d)\n//\n// * can adopt anything, because 0 or repetition is allowed\n// *(a|?(b|c)|d) => *(a|b|c|d)\n// *(a|+(b|c)|d) => *(a|b|c|d)\n// *(a|@(b|c)|d) => *(a|b|c|d)\n//\n// + can adopt @, because 1 or repetition is allowed\n// +(a|@(b|c)|d) => +(a|b|c|d)\n//\n// + and @ CANNOT adopt *, because 0 would be allowed\n// +(a|*(b|c)|d) => would match \"\", on *(b|c)\n// @(a|*(b|c)|d) => would match \"\", on *(b|c)\n//\n// + and @ CANNOT adopt ?, because 0 would be allowed\n// +(a|?(b|c)|d) => would match \"\", on ?(b|c)\n// @(a|?(b|c)|d) => would match \"\", on ?(b|c)\n//\n// ? can adopt @, because 0 or 1 is allowed\n// ?(a|@(b|c)|d) => ?(a|b|c|d)\n//\n// ? and @ CANNOT adopt * or +, because >1 would be allowed\n// ?(a|*(b|c)|d) => would match bbb on *(b|c)\n// @(a|*(b|c)|d) => would match bbb on *(b|c)\n// ?(a|+(b|c)|d) => would match bbb on +(b|c)\n// @(a|+(b|c)|d) => would match bbb on +(b|c)\n//\n// ! CANNOT adopt ! (nothing else can either)\n// !(a|!(b|c)|d) => !(a|b|c|d) would fail to match on b (not not b|c)\n//\n// ! can adopt @\n// !(a|@(b|c)|d) => !(a|b|c|d)\n//\n// ! CANNOT adopt *\n// !(a|*(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt +\n// !(a|+(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt ?\n// x!(a|?(b|c)|d) => x!(a|b|c|d) would fail to match \"x\"\nconst adoptionMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['@']],\n ['?', ['?', '@']],\n ['@', ['@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@']],\n])\n\n// nested extglobs that can be adopted in, but with the addition of\n// a blank '' element.\nconst adoptionWithSpaceMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?']],\n ['@', ['?']],\n ['+', ['?', '*']],\n])\n\n// union of the previous two maps\nconst adoptionAnyMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?', '@']],\n ['?', ['?', '@']],\n ['@', ['?', '@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@', '?', '*']],\n])\n\n// Extglobs that can take over their parent if they are the only child\n// the key is parent, value maps child to resulting extglob parent type\n// '@' is omitted because it's a special case. An `@` extglob with a single\n// member can always be usurped by that subpattern.\nconst usurpMap = new Map<\n ExtglobType,\n Map<ExtglobType | null, ExtglobType | null>\n>([\n ['!', new Map([['!', '@']])],\n [\n '?',\n new Map([\n ['*', '*'],\n ['+', '*'],\n ]),\n ],\n [\n '@',\n new Map([\n ['!', '!'],\n ['?', '?'],\n ['@', '@'],\n ['*', '*'],\n ['+', '+'],\n ]),\n ],\n [\n '+',\n new Map([\n ['?', '*'],\n ['*', '*'],\n ]),\n ],\n])\n\n// Patterns that get prepended to bind to the start of either the\n// entire string, or just a single path portion, to prevent dots\n// and/or traversal patterns, when needed.\n// Exts don't need the ^ or / bit, because the root binds that already.\nconst startNoTraversal = '(?!(?:^|/)\\\\.\\\\.?(?:$|/))'\nconst startNoDot = '(?!\\\\.)'\n\n// characters that indicate a start of pattern needs the \"no dots\" bit,\n// because a dot *might* be matched. ( is not in the list, because in\n// the case of a child extglob, it will handle the prevention itself.\nconst addPatternStart = new Set(['[', '.'])\n// cases where traversal is A-OK, no dot prevention needed\nconst justDots = new Set(['..', '.'])\nconst reSpecials = new Set('().*{}+?[]^$\\\\!')\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// any single thing other than /\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n// use + when we need to ensure that *something* matches, because the * is\n// the only thing in the path portion.\nconst starNoEmpty = qmark + '+?'\n\n// remove the \\ chars that we added if we end up doing a nonmagic compare\n// const deslash = (s: string) => s.replace(/\\\\(.)/g, '$1')\n\nlet ID = 0\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n #parent?: AST\n #parentIndex: number\n #negs: AST[]\n #filledNegs: boolean = false\n #options: MinimatchOptions\n #toString?: string\n // set to true if it's an extglob with no children\n // (which really means one child of '')\n #emptyExt: boolean = false\n id = ++ID\n\n get depth(): number {\n return (this.#parent?.depth ?? -1) + 1\n }\n\n [Symbol.for('nodejs.util.inspect.custom')]() {\n return {\n '@@type': 'AST',\n id: this.id,\n type: this.type,\n root: this.#root.id,\n parent: this.#parent?.id,\n depth: this.depth,\n partsLength: this.#parts.length,\n parts: this.#parts,\n }\n }\n\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n this.type = type\n // extglobs are inherently magical\n if (type) this.#hasMagic = true\n this.#parent = parent\n this.#root = this.#parent ? this.#parent.#root : this\n this.#options = this.#root === this ? options : this.#root.#options\n this.#negs = this.#root === this ? [] : this.#root.#negs\n if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)\n this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0\n }\n\n get hasMagic(): boolean | undefined {\n /* c8 ignore start */\n if (this.#hasMagic !== undefined) return this.#hasMagic\n /* c8 ignore stop */\n for (const p of this.#parts) {\n if (typeof p === 'string') continue\n if (p.type || p.hasMagic) return (this.#hasMagic = true)\n }\n // note: will be undefined until we generate the regexp src and find out\n return this.#hasMagic\n }\n\n // reconstructs the pattern\n toString(): string {\n return (\n this.#toString !== undefined ? this.#toString\n : !this.type ?\n (this.#toString = this.#parts.map(p => String(p)).join(''))\n : (this.#toString =\n this.type +\n '(' +\n this.#parts.map(p => String(p)).join('|') +\n ')')\n )\n }\n\n #fillNegs() {\n /* c8 ignore start */\n if (this !== this.#root) throw new Error('should only call on root')\n if (this.#filledNegs) return this\n /* c8 ignore stop */\n\n // call toString() once to fill this out\n this.toString()\n this.#filledNegs = true\n let n: AST | undefined\n while ((n = this.#negs.pop())) {\n if (n.type !== '!') continue\n // walk up the tree, appending everthing that comes AFTER parentIndex\n let p: AST | undefined = n\n let pp = p.#parent\n while (pp) {\n for (\n let i = p.#parentIndex + 1;\n !pp.type && i < pp.#parts.length;\n i++\n ) {\n for (const part of n.#parts) {\n /* c8 ignore start */\n if (typeof part === 'string') {\n throw new Error('string part in extglob AST??')\n }\n /* c8 ignore stop */\n part.copyIn(pp.#parts[i])\n }\n }\n p = pp\n pp = p.#parent\n }\n }\n return this\n }\n\n push(...parts: (string | AST)[]) {\n for (const p of parts) {\n if (p === '') continue\n /* c8 ignore start */\n if (\n typeof p !== 'string' &&\n !(p instanceof AST && p.#parent === this)\n ) {\n throw new Error('invalid part: ' + p)\n }\n /* c8 ignore stop */\n this.#parts.push(p)\n }\n }\n\n toJSON() {\n const ret: unknown[] =\n this.type === null ?\n this.#parts\n .slice()\n .map(p => (typeof p === 'string' ? p : p.toJSON()))\n : [this.type, ...this.#parts.map(p => (p as AST).toJSON())]\n if (this.isStart() && !this.type) ret.unshift([])\n if (\n this.isEnd() &&\n (this === this.#root ||\n (this.#root.#filledNegs && this.#parent?.type === '!'))\n ) {\n ret.push({})\n }\n return ret\n }\n\n isStart(): boolean {\n if (this.#root === this) return true\n // if (this.type) return !!this.#parent?.isStart()\n if (!this.#parent?.isStart()) return false\n if (this.#parentIndex === 0) return true\n // if everything AHEAD of this is a negation, then it's still the \"start\"\n const p = this.#parent\n for (let i = 0; i < this.#parentIndex; i++) {\n const pp = p.#parts[i]\n if (!(pp instanceof AST && pp.type === '!')) {\n return false\n }\n }\n return true\n }\n\n isEnd(): boolean {\n if (this.#root === this) return true\n if (this.#parent?.type === '!') return true\n if (!this.#parent?.isEnd()) return false\n if (!this.type) return this.#parent?.isEnd()\n // if not root, it'll always have a parent\n /* c8 ignore start */\n const pl = this.#parent ? this.#parent.#parts.length : 0\n /* c8 ignore stop */\n return this.#parentIndex === pl - 1\n }\n\n copyIn(part: AST | string) {\n if (typeof part === 'string') this.push(part)\n else this.push(part.clone(this))\n }\n\n clone(parent: AST) {\n const c = new AST(this.type, parent)\n for (const p of this.#parts) {\n c.copyIn(p)\n }\n return c\n }\n\n static #parseAST(\n str: string,\n ast: AST,\n pos: number,\n opt: MinimatchOptions,\n extDepth: number,\n ): number {\n const maxDepth = opt.maxExtglobRecursion ?? 2\n let escaping = false\n let inBrace = false\n let braceStart = -1\n let braceNeg = false\n if (ast.type === null) {\n // outside of a extglob, append until we find a start\n let i = pos\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n // we don't have to check for adoption here, because that's\n // done at the other recursion point.\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n extDepth <= maxDepth\n if (doRecurse) {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt, extDepth + 1)\n ast.push(ext)\n continue\n }\n acc += c\n }\n ast.push(acc)\n return i\n }\n\n // some kind of extglob, pos is at the (\n // find the next | or )\n let i = pos + 1\n let part = new AST(null, ast)\n const parts: AST[] = []\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n /* c8 ignore start - the maxDepth is sufficient here */\n (extDepth <= maxDepth || (ast && ast.#canAdoptType(c)))\n /* c8 ignore stop */\n if (doRecurse) {\n const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1\n part.push(acc)\n acc = ''\n const ext = new AST(c, part)\n part.push(ext)\n i = AST.#parseAST(str, ext, i, opt, extDepth + depthAdd)\n continue\n }\n if (c === '|') {\n part.push(acc)\n acc = ''\n parts.push(part)\n part = new AST(null, ast)\n continue\n }\n if (c === ')') {\n if (acc === '' && ast.#parts.length === 0) {\n ast.#emptyExt = true\n }\n part.push(acc)\n acc = ''\n ast.push(...parts, part)\n return i\n }\n acc += c\n }\n\n // unfinished extglob\n // if we got here, it was a malformed extglob! not an extglob, but\n // maybe something else in there.\n ast.type = null\n ast.#hasMagic = undefined\n ast.#parts = [str.substring(pos - 1)]\n return i\n }\n\n #canAdoptWithSpace(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n return this.#canAdopt(child, adoptionWithSpaceMap)\n }\n\n #canAdopt(\n child?: AST | string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionMap,\n ): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canAdoptType(\n gc.type,\n map,\n )\n }\n #canAdoptType(\n c: string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionAnyMap,\n ): c is ExtglobType {\n return !!map.get(this.type as ExtglobType)?.includes(c as ExtglobType)\n }\n\n #adoptWithSpace(\n this: AST & { type: ExtglobType },\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const blank = new AST(null, gc, this.options)\n blank.#parts.push('')\n gc.push(blank)\n this.#adopt(child, index)\n }\n\n #adopt(\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n this.#parts.splice(index, 1, ...gc.#parts)\n for (const p of gc.#parts) {\n if (typeof p === 'object') p.#parent = this\n }\n this.#toString = undefined\n }\n\n #canUsurpType(c: string): boolean {\n const m = usurpMap.get(this.type as ExtglobType)\n return !!m?.has(c as ExtglobType)\n }\n\n #canUsurp(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null ||\n this.#parts.length !== 1\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canUsurpType(gc.type)\n }\n\n #usurp(this: AST & { type: ExtglobType }, child: AST & { type: null }) {\n const m = usurpMap.get(this.type as ExtglobType)\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const nt = m?.get(gc.type)\n /* c8 ignore start - impossible */\n if (!nt) return false\n /* c8 ignore stop */\n this.#parts = gc.#parts\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#parent = this\n }\n }\n this.type = nt\n this.#toString = undefined\n this.#emptyExt = false\n }\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options, 0)\n return ast\n }\n\n // returns the regular expression if there's magic, or the unescaped\n // string if not.\n toMMPattern(): MMRegExp | string {\n // should only be called on root\n /* c8 ignore start */\n if (this !== this.#root) return this.#root.toMMPattern()\n /* c8 ignore stop */\n const glob = this.toString()\n const [re, body, hasMagic, uflag] = this.toRegExpSource()\n // if we're in nocase mode, and not nocaseMagicOnly, then we do\n // still need a regular expression if we have to case-insensitively\n // match capital/lowercase characters.\n const anyMagic =\n hasMagic ||\n this.#hasMagic ||\n (this.#options.nocase &&\n !this.#options.nocaseMagicOnly &&\n glob.toUpperCase() !== glob.toLowerCase())\n if (!anyMagic) {\n return body\n }\n\n const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')\n return Object.assign(new RegExp(`^${re}$`, flags), {\n _src: re,\n _glob: glob,\n })\n }\n\n get options() {\n return this.#options\n }\n\n // returns the string match, the regexp source, whether there's magic\n // in the regexp (so a regular expression is required) and whether or\n // not the uflag is needed for the regular expression (for posix classes)\n // TODO: instead of injecting the start/end at this point, just return\n // the BODY of the regexp, along with the start/end portions suitable\n // for binding the start/end in either a joined full-path makeRe context\n // (where we bind to (^|/), or a standalone matchPart context (where\n // we bind to ^, and not /). Otherwise slashes get duped!\n //\n // In part-matching mode, the start is:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: ^(?!\\.\\.?$)\n // - if dots allowed or not possible: ^\n // - if dots possible and not allowed: ^(?!\\.)\n // end is:\n // - if not isEnd(): nothing\n // - else: $\n //\n // In full-path matching mode, we put the slash at the START of the\n // pattern, so start is:\n // - if first pattern: same as part-matching mode\n // - if not isStart(): nothing\n // - if traversal possible, but not allowed: /(?!\\.\\.?(?:$|/))\n // - if dots allowed or not possible: /\n // - if dots possible and not allowed: /(?!\\.)\n // end is:\n // - if last pattern, same as part-matching mode\n // - else nothing\n //\n // Always put the (?:$|/) on negated tails, though, because that has to be\n // there to bind the end of the negated pattern portion, and it's easier to\n // just stick it in now rather than try to inject it later in the middle of\n // the pattern.\n //\n // We can just always return the same end, and leave it up to the caller\n // to know whether it's going to be used joined or in parts.\n // And, if the start is adjusted slightly, can do the same there:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: (?:/|^)(?!\\.\\.?$)\n // - if dots allowed or not possible: (?:/|^)\n // - if dots possible and not allowed: (?:/|^)(?!\\.)\n //\n // But it's better to have a simpler binding without a conditional, for\n // performance, so probably better to return both start options.\n //\n // Then the caller just ignores the end if it's not the first pattern,\n // and the start always gets applied.\n //\n // But that's always going to be $ if it's the ending pattern, or nothing,\n // so the caller can just attach $ at the end of the pattern when building.\n //\n // So the todo is:\n // - better detect what kind of start is needed\n // - return both flavors of starting pattern\n // - attach $ at the end of the pattern when creating the actual RegExp\n //\n // Ah, but wait, no, that all only applies to the root when the first pattern\n // is not an extglob. If the first pattern IS an extglob, then we need all\n // that dot prevention biz to live in the extglob portions, because eg\n // +(*|.x*) can match .xy but not .yx.\n //\n // So, return the two flavors if it's #root and the first child is not an\n // AST, otherwise leave it to the child AST to handle it, and there,\n // use the (?:^|/) style of start binding.\n //\n // Even simplified further:\n // - Since the start for a join is eg /(?!\\.) and the start for a part\n // is ^(?!\\.), we can just prepend (?!\\.) to the pattern (either root\n // or start or whatever) and prepend ^ or / at the Regexp construction.\n toRegExpSource(\n allowDot?: boolean,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n const dot = allowDot ?? !!this.#options.dot\n if (this.#root === this) {\n this.#flatten()\n this.#fillNegs()\n }\n if (!isExtglobAST(this)) {\n const noEmpty =\n this.isStart() &&\n this.isEnd() &&\n !this.#parts.some(s => typeof s !== 'string')\n const src = this.#parts\n .map(p => {\n const [re, _, hasMagic, uflag] =\n typeof p === 'string' ?\n AST.#parseGlob(p, this.#hasMagic, noEmpty)\n : p.toRegExpSource(allowDot)\n this.#hasMagic = this.#hasMagic || hasMagic\n this.#uflag = this.#uflag || uflag\n return re\n })\n .join('')\n\n let start = ''\n if (this.isStart()) {\n if (typeof this.#parts[0] === 'string') {\n // this is the string that will match the start of the pattern,\n // so we need to protect against dots and such.\n\n // '.' and '..' cannot match unless the pattern is that exactly,\n // even if it starts with . or dot:true is set.\n const dotTravAllowed =\n this.#parts.length === 1 && justDots.has(this.#parts[0])\n if (!dotTravAllowed) {\n const aps = addPatternStart\n // check if we have a possibility of matching . or ..,\n // and prevent that.\n const needNoTrav =\n // dots are allowed, and the pattern starts with [ or .\n (dot && aps.has(src.charAt(0))) ||\n // the pattern starts with \\., and then [ or .\n (src.startsWith('\\\\.') && aps.has(src.charAt(2))) ||\n // the pattern starts with \\.\\., and then [ or .\n (src.startsWith('\\\\.\\\\.') && aps.has(src.charAt(4)))\n // no need to prevent dots if it can't match a dot, or if a\n // sub-pattern will be preventing it anyway.\n const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))\n\n start =\n needNoTrav ? startNoTraversal\n : needNoDot ? startNoDot\n : ''\n }\n }\n }\n\n // append the \"end of path portion\" pattern to negation tails\n let end = ''\n if (\n this.isEnd() &&\n this.#root.#filledNegs &&\n this.#parent?.type === '!'\n ) {\n end = '(?:$|\\\\/)'\n }\n const final = start + src + end\n return [\n final,\n unescape(src),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n // We need to calculate the body *twice* if it's a repeat pattern\n // at the start, once in nodot mode, then again in dot mode, so a\n // pattern like *(?) can match 'x.y'\n\n const repeated = this.type === '*' || this.type === '+'\n // some kind of extglob\n const start = this.type === '!' ? '(?:(?!(?:' : '(?:'\n let body = (this as AST & { type: ExtglobType }).#partsToRegExp(dot)\n\n if (this.isStart() && this.isEnd() && !body && this.type !== '!') {\n // invalid extglob, has to at least be *something* present, if it's\n // the entire path portion.\n const s = this.toString()\n const me = this as AST\n me.#parts = [s]\n me.type = null\n me.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n let bodyDotAllowed =\n !repeated || allowDot || dot || !startNoDot ?\n ''\n : this.#partsToRegExp(true)\n if (bodyDotAllowed === body) {\n bodyDotAllowed = ''\n }\n if (bodyDotAllowed) {\n body = `(?:${body})(?:${bodyDotAllowed})*?`\n }\n\n // an empty !() is exactly equivalent to a starNoEmpty\n let final = ''\n if (this.type === '!' && this.#emptyExt) {\n final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty\n } else {\n const close =\n this.type === '!' ?\n // !() must match something,but !(x) can match ''\n '))' +\n (this.isStart() && !dot && !allowDot ? startNoDot : '') +\n star +\n ')'\n : this.type === '@' ? ')'\n : this.type === '?' ? ')?'\n : this.type === '+' && bodyDotAllowed ? ')'\n : this.type === '*' && bodyDotAllowed ? `)?`\n : `)${this.type}`\n final = start + body + close\n }\n return [\n final,\n unescape(body),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n #flatten() {\n if (!isExtglobAST(this)) {\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#flatten()\n }\n }\n } else {\n // do up to 10 passes to flatten as much as possible\n let iterations = 0\n let done = false\n do {\n done = true\n for (let i = 0; i < this.#parts.length; i++) {\n const c = this.#parts[i]\n if (typeof c === 'object') {\n c.#flatten()\n if (this.#canAdopt(c)) {\n done = false\n this.#adopt(c, i)\n } else if (this.#canAdoptWithSpace(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#adoptWithSpace(c, i)\n } else if (this.#canUsurp(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#usurp(c)\n }\n }\n }\n } while (!done && ++iterations < 10)\n }\n this.#toString = undefined\n }\n\n #partsToRegExp(this: AST & { type: ExtglobType }, dot: boolean) {\n return this.#parts\n .map(p => {\n // extglob ASTs should only contain parent ASTs\n /* c8 ignore start */\n if (typeof p === 'string') {\n throw new Error('string type in extglob ast??')\n }\n /* c8 ignore stop */\n // can ignore hasMagic, because extglobs are already always magic\n const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot)\n this.#uflag = this.#uflag || uflag\n return re\n })\n .filter(p => !(this.isStart() && this.isEnd()) || !!p)\n .join('|')\n }\n\n static #parseGlob(\n glob: string,\n hasMagic: boolean | undefined,\n noEmpty: boolean = false,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n let escaping = false\n let re = ''\n let uflag = false\n // multiple stars that aren't globstars coalesce into one *\n let inStar = false\n for (let i = 0; i < glob.length; i++) {\n const c = glob.charAt(i)\n if (escaping) {\n escaping = false\n re += (reSpecials.has(c) ? '\\\\' : '') + c\n continue\n }\n if (c === '*') {\n if (inStar) continue\n inStar = true\n re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star\n hasMagic = true\n continue\n } else {\n inStar = false\n }\n if (c === '\\\\') {\n if (i === glob.length - 1) {\n re += '\\\\\\\\'\n } else {\n escaping = true\n }\n continue\n }\n if (c === '[') {\n const [src, needUflag, consumed, magic] = parseClass(glob, i)\n if (consumed) {\n re += src\n uflag = uflag || needUflag\n i += consumed - 1\n hasMagic = hasMagic || magic\n continue\n }\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import { expand } from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport type { ExtglobType } from './ast.js'\nimport { AST } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\nexport type Platform =\n | 'aix'\n | 'android'\n | 'darwin'\n | 'freebsd'\n | 'haiku'\n | 'linux'\n | 'openbsd'\n | 'sunos'\n | 'win32'\n | 'cygwin'\n | 'netbsd'\n\nexport interface MinimatchOptions {\n /** do not expand `{x,y}` style braces */\n nobrace?: boolean\n /** do not treat patterns starting with `#` as a comment */\n nocomment?: boolean\n /** do not treat patterns starting with `!` as a negation */\n nonegate?: boolean\n /** print LOTS of debugging output */\n debug?: boolean\n /** treat `**` the same as `*` */\n noglobstar?: boolean\n /** do not expand extglobs like `+(a|b)` */\n noext?: boolean\n /** return the pattern if nothing matches */\n nonull?: boolean\n /** treat `\\\\` as a path separator, not an escape character */\n windowsPathsNoEscape?: boolean\n /**\n * inverse of {@link MinimatchOptions.windowsPathsNoEscape}\n * @deprecated\n */\n allowWindowsEscape?: boolean\n /**\n * Compare a partial path to a pattern. As long as the parts\n * of the path that are present are not contradicted by the\n * pattern, it will be treated as a match. This is useful in\n * applications where you're walking through a folder structure,\n * and don't yet have the full path, but want to ensure that you\n * do not walk down paths that can never be a match.\n */\n partial?: boolean\n /** allow matches that start with `.` even if the pattern does not */\n dot?: boolean\n /** ignore case */\n nocase?: boolean\n /** ignore case only in wildcard patterns */\n nocaseMagicOnly?: boolean\n /** consider braces to be \"magic\" for the purpose of `hasMagic` */\n magicalBraces?: boolean\n /**\n * If set, then patterns without slashes will be matched\n * against the basename of the path if it contains slashes.\n * For example, `a?b` would match the path `/xyz/123/acb`, but\n * not `/xyz/acb/123`.\n */\n matchBase?: boolean\n /** invert the results of negated matches */\n flipNegate?: boolean\n /** do not collapse multiple `/` into a single `/` */\n preserveMultipleSlashes?: boolean\n /**\n * A number indicating the level of optimization that should be done\n * to the pattern prior to parsing and using it for matches.\n */\n optimizationLevel?: number\n /** operating system platform */\n platform?: Platform\n /**\n * When a pattern starts with a UNC path or drive letter, and in\n * `nocase:true` mode, do not convert the root portions of the\n * pattern into a case-insensitive regular expression, and instead\n * leave them as strings.\n *\n * This is the default when the platform is `win32` and\n * `nocase:true` is set.\n */\n windowsNoMagicRoot?: boolean\n /**\n * max number of `{...}` patterns to expand. Default 100_000.\n */\n braceExpandMax?: number\n /**\n * Max number of non-adjacent `**` patterns to recursively walk down.\n *\n * The default of 200 is almost certainly high enough for most purposes,\n * and can handle absurdly excessive patterns.\n */\n maxGlobstarRecursion?: number\n\n /**\n * Max depth to traverse for nested extglobs like `*(a|b|c)`\n *\n * Default is 2, which is quite low, but any higher value\n * swiftly results in punishing performance impacts. Note\n * that this is *not* relevant when the globstar types can\n * be safely coalesced into a single set.\n *\n * For example, `*(a|@(b|c)|d)` would be flattened into\n * `*(a|b|c|d)`. Thus, many common extglobs will retain good\n * performance and never hit this limit, even if they are\n * excessively deep and complicated.\n *\n * If the limit is hit, then the extglob characters are simply\n * not parsed, and the pattern effectively switches into\n * `noextglob: true` mode for the contents of that nested\n * sub-pattern. This will typically _not_ result in a match,\n * but is considered a valid trade-off for security and\n * performance.\n */\n maxExtglobRecursion?: number\n}\n\nexport const minimatch = (\n p: string,\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n return new Minimatch(pattern, options).match(p)\n}\n\n// Optimized checking for the most common glob patterns.\nconst starDotExtRE = /^\\*+([^+@!?*[(]*)$/\nconst starDotExtTest = (ext: string) => (f: string) =>\n !f.startsWith('.') && f.endsWith(ext)\nconst starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)\nconst starDotExtTestNocase = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => !f.startsWith('.') && f.toLowerCase().endsWith(ext)\n}\nconst starDotExtTestNocaseDot = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => f.toLowerCase().endsWith(ext)\n}\nconst starDotStarRE = /^\\*+\\.\\*+$/\nconst starDotStarTest = (f: string) =>\n !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) =>\n f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) =>\n f.length !== 0 && f !== '.' && f !== '..'\nconst qmarksRE = /^\\?+([^+@!?*[(]*)?$/\nconst qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTestNoExt = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && !f.startsWith('.')\n}\nconst qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && f !== '.' && f !== '..'\n}\n\n/* c8 ignore start */\nconst defaultPlatform: Platform = (\n typeof process === 'object' && process ?\n (typeof process.env === 'object' &&\n process.env &&\n process.env.__MINIMATCH_TESTING_PLATFORM__) ||\n process.platform\n : 'posix') as Platform\n\nexport type Sep = '\\\\' | '/'\n\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep =\n defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep\nminimatch.sep = sep\n\nexport const GLOBSTAR = Symbol('globstar **')\nminimatch.GLOBSTAR = GLOBSTAR\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nconst twoStarDot = '(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nconst twoStarNoDot = '(?:(?!(?:\\\\/|^)\\\\.).)*?'\n\nexport const filter =\n (pattern: string, options: MinimatchOptions = {}) =>\n (p: string) =>\n minimatch(p, pattern, options)\nminimatch.filter = filter\n\nconst ext = (a: MinimatchOptions, b: MinimatchOptions = {}) =>\n Object.assign({}, a, b)\n\nexport const defaults = (def: MinimatchOptions): typeof minimatch => {\n if (!def || typeof def !== 'object' || !Object.keys(def).length) {\n return minimatch\n }\n\n const orig = minimatch\n\n const m = (p: string, pattern: string, options: MinimatchOptions = {}) =>\n orig(p, pattern, ext(def, options))\n\n return Object.assign(m, {\n Minimatch: class Minimatch extends orig.Minimatch {\n constructor(pattern: string, options: MinimatchOptions = {}) {\n super(pattern, ext(def, options))\n }\n static defaults(options: MinimatchOptions) {\n return orig.defaults(ext(def, options)).Minimatch\n }\n },\n\n AST: class AST extends orig.AST {\n /* c8 ignore start */\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n super(type, parent, ext(def, options))\n }\n /* c8 ignore stop */\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n return orig.AST.fromGlob(pattern, ext(def, options))\n }\n },\n\n unescape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.escape(s, ext(def, options)),\n\n filter: (pattern: string, options: MinimatchOptions = {}) =>\n orig.filter(pattern, ext(def, options)),\n\n defaults: (options: MinimatchOptions) =>\n orig.defaults(ext(def, options)),\n\n makeRe: (pattern: string, options: MinimatchOptions = {}) =>\n orig.makeRe(pattern, ext(def, options)),\n\n braceExpand: (pattern: string, options: MinimatchOptions = {}) =>\n orig.braceExpand(pattern, ext(def, options)),\n\n match: (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n ) => orig.match(list, pattern, ext(def, options)),\n\n sep: orig.sep,\n GLOBSTAR: GLOBSTAR as typeof GLOBSTAR,\n })\n}\nminimatch.defaults = defaults\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nexport const braceExpand = (\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // Thanks to Yeting Li <https://github.com/yetingli> for\n // improving this regexp to avoid a ReDOS vulnerability.\n if (options.nobrace || !/\\{(?:(?!\\{).)*\\}/.test(pattern)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern, { max: options.braceExpandMax })\n}\nminimatch.braceExpand = braceExpand\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\n\nexport const makeRe = (pattern: string, options: MinimatchOptions = {}) =>\n new Minimatch(pattern, options).makeRe()\nminimatch.makeRe = makeRe\n\nexport const match = (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n const mm = new Minimatch(pattern, options)\n list = list.filter(f => mm.match(f))\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\nminimatch.match = match\n\n// replace stuff like \\* with *\nconst globMagic = /[?*]|[+@!]\\(.*?\\)|\\[|\\]/\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\nexport type MMRegExp = RegExp & {\n _src?: string\n _glob?: string\n}\n\nexport type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR\nexport type ParseReturn = ParseReturnFiltered | false\n\nexport class Minimatch {\n options: MinimatchOptions\n set: ParseReturnFiltered[][]\n pattern: string\n\n windowsPathsNoEscape: boolean\n nonegate: boolean\n negate: boolean\n comment: boolean\n empty: boolean\n preserveMultipleSlashes: boolean\n partial: boolean\n globSet: string[]\n globParts: string[][]\n nocase: boolean\n\n isWindows: boolean\n platform: Platform\n windowsNoMagicRoot: boolean\n maxGlobstarRecursion: number\n\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n // avoid the annoying deprecation flag lol\n const awe = ('allowWindow' + 'sEscape') as keyof MinimatchOptions\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options[awe] === false\n if (this.windowsPathsNoEscape) {\n this.pattern = this.pattern.replace(/\\\\/g, '/')\n }\n this.preserveMultipleSlashes = !!options.preserveMultipleSlashes\n this.regexp = null\n this.negate = false\n this.nonegate = !!options.nonegate\n this.comment = false\n this.empty = false\n this.partial = !!options.partial\n this.nocase = !!this.options.nocase\n this.windowsNoMagicRoot =\n options.windowsNoMagicRoot !== undefined ?\n options.windowsNoMagicRoot\n : !!(this.isWindows && this.nocase)\n\n this.globSet = []\n this.globParts = []\n this.set = []\n\n // make the set of regexps etc.\n this.make()\n }\n\n hasMagic(): boolean {\n if (this.options.magicalBraces && this.set.length > 1) {\n return true\n }\n for (const pattern of this.set) {\n for (const part of pattern) {\n if (typeof part !== 'string') return true\n }\n }\n return false\n }\n\n debug(..._: unknown[]) {}\n\n make() {\n const pattern = this.pattern\n const options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n this.globSet = [...new Set(this.braceExpand())]\n\n if (options.debug) {\n //oxlint-disable-next-line no-console\n this.debug = (...args: unknown[]) => console.error(...args)\n }\n\n this.debug(this.pattern, this.globSet)\n\n // step 3: now we have a set, so turn each one into a series of\n // path-portion matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n //\n // First, we preprocess to make the glob pattern sets a bit simpler\n // and deduped. There are some perf-killing patterns that can cause\n // problems with a glob walk, but we can simplify them down a bit.\n const rawGlobParts = this.globSet.map(s => this.slashSplit(s))\n this.globParts = this.preprocess(rawGlobParts)\n this.debug(this.pattern, this.globParts)\n\n // glob --> regexps\n let set = this.globParts.map((s, _, __) => {\n if (this.isWindows && this.windowsNoMagicRoot) {\n // check if it's a drive or unc path.\n const isUNC =\n s[0] === '' &&\n s[1] === '' &&\n (s[2] === '?' || !globMagic.test(s[2])) &&\n !globMagic.test(s[3])\n const isDrive = /^[a-z]:/i.test(s[0])\n if (isUNC) {\n return [\n ...s.slice(0, 4),\n ...s.slice(4).map(ss => this.parse(ss)),\n ]\n } else if (isDrive) {\n return [s[0], ...s.slice(1).map(ss => this.parse(ss))]\n }\n }\n return s.map(ss => this.parse(ss))\n })\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n this.set = set.filter(\n s => s.indexOf(false) === -1,\n ) as ParseReturnFiltered[][]\n\n // do not treat the ? in UNC paths as magic\n if (this.isWindows) {\n for (let i = 0; i < this.set.length; i++) {\n const p = this.set[i]\n if (\n p[0] === '' &&\n p[1] === '' &&\n this.globParts[i][2] === '?' &&\n typeof p[3] === 'string' &&\n /^[a-z]:$/i.test(p[3])\n ) {\n p[2] = '?'\n }\n }\n }\n\n this.debug(this.pattern, this.set)\n }\n\n // various transforms to equivalent pattern sets that are\n // faster to process in a filesystem walk. The goal is to\n // eliminate what we can, and push all ** patterns as far\n // to the right as possible, even if it increases the number\n // of patterns that we have to process.\n preprocess(globParts: string[][]) {\n // if we're not in globstar mode, then turn ** into *\n if (this.options.noglobstar) {\n for (const partset of globParts) {\n for (let j = 0; j < partset.length; j++) {\n if (partset[j] === '**') {\n partset[j] = '*'\n }\n }\n }\n }\n\n const { optimizationLevel = 1 } = this.options\n\n if (optimizationLevel >= 2) {\n // aggressive optimization for the purpose of fs walking\n globParts = this.firstPhasePreProcess(globParts)\n globParts = this.secondPhasePreProcess(globParts)\n } else if (optimizationLevel >= 1) {\n // just basic optimizations to remove some .. parts\n globParts = this.levelOneOptimize(globParts)\n } else {\n // just collapse multiple ** portions into one\n globParts = this.adjascentGlobstarOptimize(globParts)\n }\n\n return globParts\n }\n\n // just get rid of adjascent ** portions\n adjascentGlobstarOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let i = gs\n while (parts[i + 1] === '**') {\n i++\n }\n if (i !== gs) {\n parts.splice(gs, i - gs)\n }\n }\n return parts\n })\n }\n\n // get rid of adjascent ** and resolve .. portions\n levelOneOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n parts = parts.reduce((set: string[], part) => {\n const prev = set[set.length - 1]\n if (part === '**' && prev === '**') {\n return set\n }\n if (part === '..') {\n if (prev && prev !== '..' && prev !== '.' && prev !== '**') {\n set.pop()\n return set\n }\n }\n set.push(part)\n return set\n }, [])\n return parts.length === 0 ? [''] : parts\n })\n }\n\n levelTwoFileOptimize(parts: string | string[]) {\n if (!Array.isArray(parts)) {\n parts = this.slashSplit(parts)\n }\n let didSomething: boolean = false\n\n do {\n didSomething = false\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (\n p &&\n p !== '.' &&\n p !== '..' &&\n p !== '**' &&\n !(this.isWindows && /^[a-z]:$/i.test(p))\n ) {\n didSomething = true\n parts.splice(dd - 1, 2)\n dd -= 2\n }\n }\n } while (didSomething)\n return parts.length === 0 ? [''] : parts\n }\n\n // First phase: single-pattern processing\n // <pre> is 1 or more portions\n // <rest> is 1 or more portions\n // <p> is any portion other than ., .., '', or **\n // <e> is . or ''\n //\n // **/.. is *brutal* for filesystem walking performance, because\n // it effectively resets the recursive walk each time it occurs,\n // and ** cannot be reduced out by a .. pattern part like a regexp\n // or most strings (other than .., ., and '') can be.\n //\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n // <pre>/<e>/<rest> -> <pre>/<rest>\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n // **/**/<rest> -> **/<rest>\n //\n // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow\n // this WOULD be allowed if ** did follow symlinks, or * didn't\n firstPhasePreProcess(globParts: string[][]) {\n let didSomething = false\n do {\n didSomething = false\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n for (let parts of globParts) {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let gss: number = gs\n while (parts[gss + 1] === '**') {\n // <pre>/**/**/<rest> -> <pre>/**/<rest>\n gss++\n }\n // eg, if gs is 2 and gss is 4, that means we have 3 **\n // parts, and can remove 2 of them.\n if (gss > gs) {\n parts.splice(gs + 1, gss - gs)\n }\n\n let next = parts[gs + 1]\n const p = parts[gs + 2]\n const p2 = parts[gs + 3]\n if (next !== '..') continue\n if (\n !p ||\n p === '.' ||\n p === '..' ||\n !p2 ||\n p2 === '.' ||\n p2 === '..'\n ) {\n continue\n }\n didSomething = true\n // edit parts in place, and push the new one\n parts.splice(gs, 1)\n const other = parts.slice(0)\n other[gs] = '**'\n globParts.push(other)\n gs--\n }\n\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n const needDot = dd === 1 && parts[dd + 1] === '**'\n const splin = needDot ? ['.'] : []\n parts.splice(dd - 1, 2, ...splin)\n if (parts.length === 0) parts.push('')\n dd -= 2\n }\n }\n }\n } while (didSomething)\n\n return globParts\n }\n\n // second phase: multi-pattern dedupes\n // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>\n // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>\n // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>\n //\n // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>\n // ^-- not valid because ** doens't follow symlinks\n secondPhasePreProcess(globParts: string[][]): string[][] {\n for (let i = 0; i < globParts.length - 1; i++) {\n for (let j = i + 1; j < globParts.length; j++) {\n const matched = this.partsMatch(\n globParts[i],\n globParts[j],\n !this.preserveMultipleSlashes,\n )\n if (matched) {\n globParts[i] = []\n globParts[j] = matched\n break\n }\n }\n }\n return globParts.filter(gs => gs.length)\n }\n\n partsMatch(\n a: string[],\n b: string[],\n emptyGSMatch: boolean = false,\n ): false | string[] {\n let ai = 0\n let bi = 0\n let result: string[] = []\n let which: string = ''\n while (ai < a.length && bi < b.length) {\n if (a[ai] === b[bi]) {\n result.push(which === 'b' ? b[bi] : a[ai])\n ai++\n bi++\n } else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {\n result.push(a[ai])\n ai++\n } else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {\n result.push(b[bi])\n bi++\n } else if (\n a[ai] === '*' &&\n b[bi] &&\n (this.options.dot || !b[bi].startsWith('.')) &&\n b[bi] !== '**'\n ) {\n if (which === 'b') return false\n which = 'a'\n result.push(a[ai])\n ai++\n bi++\n } else if (\n b[bi] === '*' &&\n a[ai] &&\n (this.options.dot || !a[ai].startsWith('.')) &&\n a[ai] !== '**'\n ) {\n if (which === 'a') return false\n which = 'b'\n result.push(b[bi])\n ai++\n bi++\n } else {\n return false\n }\n }\n // if we fall out of the loop, it means they two are identical\n // as long as their lengths match\n return a.length === b.length && result\n }\n\n parseNegate() {\n if (this.nonegate) return\n\n const pattern = this.pattern\n let negate = false\n let negateOffset = 0\n\n for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.slice(negateOffset)\n this.negate = negate\n }\n\n // set partial to true to test if, for example,\n // \"/a/b\" matches the start of \"/*/b/*/d\"\n // Partial means, if you run out of file before you run\n // out of pattern, then that's fine, as long as all\n // the parts match.\n matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean = false,\n ) {\n let fileStartIndex = 0\n let patternStartIndex = 0\n\n // UNC paths like //?/X:/... can match X:/... and vice versa\n // Drive letters in absolute drive or unc paths are always compared\n // case-insensitively.\n if (this.isWindows) {\n const fileDrive =\n typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0])\n const fileUNC =\n !fileDrive &&\n file[0] === '' &&\n file[1] === '' &&\n file[2] === '?' &&\n /^[a-z]:$/i.test(file[3])\n\n const patternDrive =\n typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0])\n const patternUNC =\n !patternDrive &&\n pattern[0] === '' &&\n pattern[1] === '' &&\n pattern[2] === '?' &&\n typeof pattern[3] === 'string' &&\n /^[a-z]:$/i.test(pattern[3])\n\n const fdi =\n fileUNC ? 3\n : fileDrive ? 0\n : undefined\n const pdi =\n patternUNC ? 3\n : patternDrive ? 0\n : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [\n file[fdi],\n pattern[pdi] as string,\n ]\n // start matching at the drive letter index of each\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n patternStartIndex = pdi\n fileStartIndex = fdi\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // don't need to do the second phase, because it's only one string[]\n const { optimizationLevel = 1 } = this.options\n if (optimizationLevel >= 2) {\n file = this.levelTwoFileOptimize(file)\n }\n\n if (pattern.includes(GLOBSTAR)) {\n return this.#matchGlobstar(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n return this.#matchOne(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n #matchGlobstar(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n // split the pattern into head, tail, and middle of ** delimited parts\n const firstgs = pattern.indexOf(GLOBSTAR, patternIndex)\n const lastgs = pattern.lastIndexOf(GLOBSTAR)\n\n // split the pattern up into globstar-delimited sections\n // the tail has to be at the end, and the others just have\n // to be found in order from the head.\n const [head, body, tail] =\n partial ?\n [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1),\n [],\n ]\n : [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1, lastgs),\n pattern.slice(lastgs + 1),\n ]\n\n // check the head, from the current file/pattern index.\n if (head.length) {\n const fileHead = file.slice(fileIndex, fileIndex + head.length)\n if (!this.#matchOne(fileHead, head, partial, 0, 0)) {\n return false\n }\n fileIndex += head.length\n patternIndex += head.length\n }\n // now we know the head matches!\n\n // if the last portion is not empty, it MUST match the end\n // check the tail\n let fileTailMatch: number = 0\n if (tail.length) {\n // if head + tail > file, then we cannot possibly match\n if (tail.length + fileIndex > file.length) return false\n\n // try to match the tail\n let tailStart = file.length - tail.length\n if (this.#matchOne(file, tail, partial, tailStart, 0)) {\n fileTailMatch = tail.length\n } else {\n // affordance for stuff like a/**/* matching a/b/\n // if the last file portion is '', and there's more to the pattern\n // then try without the '' bit.\n if (\n file[file.length - 1] !== '' ||\n fileIndex + tail.length === file.length\n ) {\n return false\n }\n tailStart--\n if (!this.#matchOne(file, tail, partial, tailStart, 0)) {\n return false\n }\n fileTailMatch = tail.length + 1\n }\n }\n\n // now we know the tail matches!\n\n // the middle is zero or more portions wrapped in **, possibly\n // containing more ** sections.\n // so a/**/b/**/c/**/d has become **/b/**/c/**\n // if it's empty, it means a/**/b, just verify we have no bad dots\n // if there's no tail, so it ends on /**, then we must have *something*\n // after the head, or it's not a matc\n if (!body.length) {\n let sawSome = !!fileTailMatch\n for (let i = fileIndex; i < file.length - fileTailMatch; i++) {\n const f = String(file[i])\n sawSome = true\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n // in partial mode, we just need to get past all file parts\n return partial || sawSome\n }\n\n // now we know that there's one or more body sections, which can\n // be matched anywhere from the 0 index (because the head was pruned)\n // through to the length-fileTailMatch index.\n // split the body up into sections, and note the minimum index it can\n // be found at (start with the length of all previous segments)\n // [section, before, after]\n const bodySegments: [ParseReturn[], number][] = [[[], 0]]\n let currentBody: [ParseReturn[], number] = bodySegments[0]\n let nonGsParts = 0\n const nonGsPartsSums: number[] = [0]\n for (const b of body) {\n if (b === GLOBSTAR) {\n nonGsPartsSums.push(nonGsParts)\n currentBody = [[], 0]\n bodySegments.push(currentBody)\n } else {\n currentBody[0].push(b)\n nonGsParts++\n }\n }\n let i = bodySegments.length - 1\n const fileLength = file.length - fileTailMatch\n for (const b of bodySegments) {\n b[1] = fileLength - ((nonGsPartsSums[i--] as number) + b[0].length)\n }\n\n return !!this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex,\n 0,\n partial,\n 0,\n !!fileTailMatch,\n )\n }\n\n // return false for \"nope, not matching\"\n // return null for \"not matching, cannot keep trying\"\n #matchGlobStarBodySections(\n file: string[],\n // pattern section, last possible position for it\n bodySegments: [ParseReturn[], number][],\n fileIndex: number,\n bodyIndex: number,\n partial: boolean,\n globStarDepth: number,\n sawTail: boolean,\n ): boolean | null {\n // take the first body segment, and walk from fileIndex to its \"after\"\n // value at the end\n // If it doesn't match at that position, we increment, until we hit\n // that final possible position, and give up.\n // If it does match, then advance and try to rest.\n // If any of them fail we keep walking forward.\n // this is still a bit recursively painful, but it's more constrained\n // than previous implementations, because we never test something that\n // can't possibly be a valid matching condition.\n const bs = bodySegments[bodyIndex]\n if (!bs) {\n // just make sure that there's no bad dots\n for (let i = fileIndex; i < file.length; i++) {\n sawTail = true\n const f = file[i]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n return sawTail\n }\n\n // have a non-globstar body section to test\n const [body, after] = bs\n while (fileIndex <= after) {\n const m = this.#matchOne(\n file.slice(0, fileIndex + body.length),\n body,\n partial,\n fileIndex,\n 0,\n )\n // if limit exceeded, no match. intentional false negative,\n // acceptable break in correctness for security.\n if (m && globStarDepth < this.maxGlobstarRecursion) {\n // match! see if the rest match. if so, we're done!\n const sub = this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex + body.length,\n bodyIndex + 1,\n partial,\n globStarDepth + 1,\n sawTail,\n )\n if (sub !== false) {\n return sub\n }\n }\n const f = file[fileIndex]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n\n fileIndex++\n }\n // walked off. no point continuing\n return partial || null\n }\n\n #matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n let fi: number\n let pi: number\n let pl: number\n let fl: number\n for (\n fi = fileIndex,\n pi = patternIndex,\n fl = file.length,\n pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n let p = pattern[pi]\n let f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n /* c8 ignore start */\n if (p === false || p === GLOBSTAR) {\n return false\n }\n /* c8 ignore stop */\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n let hit: boolean\n if (typeof p === 'string') {\n hit = f === p\n this.debug('string match', p, f, hit)\n } else {\n hit = p.test(f)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n return fi === fl - 1 && file[fi] === ''\n\n /* c8 ignore start */\n } else {\n // should be unreachable.\n throw new Error('wtf?')\n }\n /* c8 ignore stop */\n }\n\n braceExpand() {\n return braceExpand(this.pattern, this.options)\n }\n\n parse(pattern: string): ParseReturn {\n assertValidPattern(pattern)\n\n const options = this.options\n\n // shortcuts\n if (pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n // far and away, the most common glob pattern parts are\n // *, *.*, and *.<ext> Add a fast check method for those.\n let m: RegExpMatchArray | null\n let fastTest: null | ((f: string) => boolean) = null\n if ((m = pattern.match(starRE))) {\n fastTest = options.dot ? starTestDot : starTest\n } else if ((m = pattern.match(starDotExtRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n starDotExtTestNocaseDot\n : starDotExtTestNocase\n : options.dot ? starDotExtTestDot\n : starDotExtTest)(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot ? qmarksTestDot\n : qmarksTest)(m)\n } else if ((m = pattern.match(starDotStarRE))) {\n fastTest = options.dot ? starDotStarTestDot : starDotStarTest\n } else if ((m = pattern.match(dotStarRE))) {\n fastTest = dotStarTest\n }\n\n const re = AST.fromGlob(pattern, this.options).toMMPattern()\n if (fastTest && typeof re === 'object') {\n // Avoids overriding in frozen environments\n Reflect.defineProperty(re, 'test', { value: fastTest })\n }\n return re\n }\n\n makeRe() {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n const set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n const options = this.options\n\n const twoStar =\n options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n const flags = new Set(options.nocase ? ['i'] : [])\n\n // regexpify non-globstar patterns\n // if ** is only item, then we just do one twoStar\n // if ** is first, and there are more, prepend (\\/|twoStar\\/)? to next\n // if ** is last, append (\\/twoStar|) to previous\n // if ** is in the middle, append (\\/|\\/twoStar\\/) to previous\n // then filter out GLOBSTAR symbols\n let re = set\n .map(pattern => {\n const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => {\n if (p instanceof RegExp) {\n for (const f of p.flags.split('')) flags.add(f)\n }\n return (\n typeof p === 'string' ? regExpEscape(p)\n : p === GLOBSTAR ? GLOBSTAR\n : p._src\n )\n }) as (string | typeof GLOBSTAR)[]\n pp.forEach((p, i) => {\n const next = pp[i + 1]\n const prev = pp[i - 1]\n if (p !== GLOBSTAR || prev === GLOBSTAR) {\n return\n }\n if (prev === undefined) {\n if (next !== undefined && next !== GLOBSTAR) {\n pp[i + 1] = '(?:\\\\/|' + twoStar + '\\\\/)?' + next\n } else {\n pp[i] = twoStar\n }\n } else if (next === undefined) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + ')?'\n } else if (next !== GLOBSTAR) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + '\\\\/)' + next\n pp[i + 1] = GLOBSTAR\n }\n })\n const filtered = pp.filter(p => p !== GLOBSTAR)\n\n // For partial matches, we need to make the pattern match\n // any prefix of the full path. We do this by generating\n // alternative patterns that match progressively longer prefixes.\n if (this.partial && filtered.length >= 1) {\n const prefixes: string[] = []\n for (let i = 1; i <= filtered.length; i++) {\n prefixes.push(filtered.slice(0, i).join('/'))\n }\n return '(?:' + prefixes.join('|') + ')'\n }\n\n return filtered.join('/')\n })\n .join('|')\n\n // need to wrap in parens if we had more than one thing with |,\n // otherwise only the first will be anchored to ^ and the last to $\n const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^' + open + re + close + '$'\n\n // In partial mode, '/' should always match as it's a valid prefix for any pattern\n if (this.partial) {\n re = '^(?:\\\\/|' + open + re.slice(1, -1) + close + ')$'\n }\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').+$'\n\n try {\n this.regexp = new RegExp(re, [...flags].join(''))\n /* c8 ignore start */\n } catch {\n // should be impossible\n this.regexp = false\n }\n /* c8 ignore stop */\n return this.regexp\n }\n\n slashSplit(p: string) {\n // if p starts with // on windows, we preserve that\n // so that UNC paths aren't broken. Otherwise, any number of\n // / characters are coalesced into one, unless\n // preserveMultipleSlashes is set to true.\n if (this.preserveMultipleSlashes) {\n return p.split('/')\n } else if (this.isWindows && /^\\/\\/[^/]+/.test(p)) {\n // add an extra '' for the one we lose\n return ['', ...p.split(/\\/+/)]\n } else {\n return p.split(/\\/+/)\n }\n }\n\n match(f: string, partial = this.partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) {\n return false\n }\n if (this.empty) {\n return f === ''\n }\n\n if (f === '/' && partial) {\n return true\n }\n\n const options = this.options\n\n // windows: need to use /, not \\\n if (this.isWindows) {\n f = f.split('\\\\').join('/')\n }\n\n // treat the test path as a set of pathparts.\n const ff = this.slashSplit(f)\n this.debug(this.pattern, 'split', ff)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n const set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n let filename: string = ff[ff.length - 1]\n if (!filename) {\n for (let i = ff.length - 2; !filename && i >= 0; i--) {\n filename = ff[i]\n }\n }\n\n for (const pattern of set) {\n let file = ff\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n const hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) {\n return true\n }\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) {\n return false\n }\n return this.negate\n }\n\n static defaults(def: MinimatchOptions) {\n return minimatch.defaults(def).Minimatch\n }\n}\n/* c8 ignore start */\nexport { AST } from './ast.js'\nexport { escape } from './escape.js'\nexport { unescape } from './unescape.js'\n/* c8 ignore stop */\nminimatch.AST = AST\nminimatch.Minimatch = Minimatch\nminimatch.escape = escape\nminimatch.unescape = unescape\n","import { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadPermissionsConfig, checkPermission, checkDenyOnly } from '../shared/permissions.js';\nimport { EventBus } from '../core/bus/index.js';\nimport { getLogger } from '../shared/logger.js';\nimport type { AgentEventEnvelope } from '../core/adapter/types.js';\nimport type { InteractionResponse, InteractionRequest } from '../core/interaction/types.js';\nimport type { InteractionContent } from '../core/interaction/types.js';\n\ninterface EvaluationResult {\n immediate: boolean;\n response?: InteractionResponse;\n reason?: string;\n}\n\nfunction evaluatePermission(\n agentType: string,\n toolName: string,\n toolInput: Record<string, unknown>,\n permissionMode: string,\n cwd: string\n): EvaluationResult {\n if (permissionMode === 'bypassPermissions') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'permissionMode is bypassPermissions' },\n };\n }\n\n const projectConfig = cwd ? loadPermissionsConfig(cwd) : null;\n\n if (permissionMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit', 'codex_patch_apply'].includes(toolName)) {\n const denyResult = checkDenyOnly(toolName, toolInput, projectConfig);\n if (denyResult.decision === 'deny') {\n return {\n immediate: true,\n response: { requestId: '', action: 'deny', message: denyResult.reason },\n };\n }\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'acceptEdits mode for Edit/Write' },\n };\n }\n\n const result = checkPermission(toolName, toolInput, projectConfig);\n\n if (result.decision === 'deny') {\n return {\n immediate: true,\n response: { requestId: '', action: 'deny', message: result.reason },\n };\n }\n if (result.decision === 'allow') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: result.reason },\n };\n }\n\n return { immediate: false };\n}\n\nexport class InteractionService {\n constructor(\n private interactionQueue: InteractionQueue,\n private bus: EventBus\n ) {}\n\n async evaluate(envelope: AgentEventEnvelope): Promise<InteractionResponse> {\n const logger = getLogger();\n const payload = envelope.payload as {\n sessionId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n };\n const sessionId = String(payload.sessionId || envelope.sessionId);\n const toolName = String(payload.toolName);\n const toolInput = payload.toolInput || {};\n const permissionMode = (envelope.metadata.permissionMode as string) || 'auto';\n const cwd = (envelope.payload.cwd as string) || '';\n const agentType = String(envelope.agentType || 'claude');\n\n logger.info({ sessionId, toolName, type: envelope.type }, '[Interaction] Request received');\n\n // Determine interaction type\n let interactionType: 'permission' | 'question' = envelope.type === 'question:request' ? 'question' : 'permission';\n\n // Special case: AskUserQuestion is a question tool masquerading as a permission request\n if (toolName === 'AskUserQuestion' && Array.isArray(toolInput.questions)) {\n interactionType = 'question';\n }\n\n // For permissions, check if immediate decision possible\n if (interactionType === 'permission') {\n const evaluation = evaluatePermission(agentType, toolName, toolInput, permissionMode, cwd);\n if (evaluation.immediate && evaluation.response) {\n logger.info({ toolName, action: evaluation.response.action }, '[Interaction] Immediate response');\n return { ...evaluation.response, requestId: '' };\n }\n }\n\n // Queue for user interaction\n const request: InteractionRequest = {\n requestId: '',\n sessionId,\n type: interactionType,\n toolName,\n toolInput,\n timestamp: Date.now(),\n };\n\n const startTime = Date.now();\n const { requestId, responsePromise } = this.interactionQueue.request(request);\n logger.info({ requestId, sessionId, type: interactionType, toolName }, '[Interaction] Blocking');\n\n // Build content based on type\n const content = this.buildContent(interactionType, toolName, toolInput, cwd);\n\n // Publish event\n this.bus.publishInteractionRequest({\n requestId,\n sessionId,\n interactionType,\n content,\n chatId: sessionId,\n messageId: '',\n cwd,\n });\n\n const response = await responsePromise;\n const elapsedMs = Date.now() - startTime;\n logger.info({ requestId, action: response.action, elapsedMs }, '[Interaction] Response sent');\n return response;\n }\n\n cancelBySession(sessionId: string, reason = 'session closed'): number {\n return this.interactionQueue.cancelBySession(sessionId, reason);\n }\n\n private buildContent(\n type: 'permission' | 'question',\n toolName: string,\n toolInput: Record<string, unknown>,\n cwd: string\n ): InteractionContent {\n if (type === 'question') {\n const questions = (toolInput.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string; value?: unknown }>;\n multiSelect?: boolean;\n }>) || [];\n const question = questions[0] || { question: 'Question', options: [] };\n\n return {\n title: question.header || 'Question',\n description: question.question,\n question: {\n text: question.question,\n header: question.header,\n options: (question.options || []).map((opt, idx) => ({\n id: String(idx),\n label: opt.label,\n value: opt.value ?? opt.label,\n description: opt.description,\n })),\n allowCustomInput: false, // TODO: make configurable\n multiSelect: question.multiSelect ?? false,\n },\n };\n }\n\n // Permission content\n return {\n title: `Permission Required: ${toolName}`,\n description: `${toolName} ${JSON.stringify(toolInput)}`,\n permission: {\n riskLevel: 'medium',\n args: toolInput,\n },\n };\n }\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../core/bus/index.js';\nimport type { AgentEventEnvelope, AgentType, CreateSessionOptions } from '../core/adapter/types.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport type { InteractionRequest, InteractionResponse } from '../core/interaction/types.js';\nimport { AgentRegistry } from '../core/agent/AgentRegistry.js';\nimport { SessionManager } from '../core/session/SessionManager.js';\nimport type { SessionInfo } from '../core/session/types.js';\nimport type { Session } from '../core/session/Session.js';\nimport type { AgentBridgePort, SessionSnapshot } from '../core/agent/AgentBridgePort.js';\n\n/** Backward compatible SessionFilter interface */\nexport interface SessionFilter {\n agentType?: string;\n includeEnded?: boolean;\n}\n\n/**\n * Gateway is the core domain aggregate root.\n * It orchestrates sessions, events, and agent management.\n *\n * Implements AgentBridgePort to serve as the bridge between agent adapters\n * and the gateway infrastructure (EventPublisher, SessionManager, etc.)\n */\nexport class Gateway implements AgentBridgePort {\n private sessionManager: SessionManager;\n private agentRegistry: AgentRegistry;\n private eventPublisher: EventPublisher;\n private interactionService: InteractionService;\n\n constructor(\n _eventBus: EventBus,\n interactionService: InteractionService,\n eventPublisher: EventPublisher,\n private logger?: Logger,\n ) {\n this.sessionManager = new SessionManager();\n this.agentRegistry = new AgentRegistry();\n this.eventPublisher = eventPublisher;\n this.interactionService = interactionService;\n }\n\n /**\n * Register a new agent type and get its token\n */\n registerAgent(agentType: string, token?: string): string {\n return this.agentRegistry.registerAgent(agentType, token);\n }\n\n /**\n * List all registered agents\n */\n listRegisteredAgents(): Array<{ token: string; agentType: string }> {\n return this.agentRegistry.listRegisteredAgents();\n }\n\n /**\n * Create a new session\n * @param skipPublishSessionStart - If true, do not publish session:start event (used for compensating creation)\n */\n async createSession(\n token: string,\n sessionId: string,\n options?: CreateSessionOptions,\n skipPublishSessionStart?: boolean\n ): Promise<Session> {\n const agentType = this.agentRegistry.getAgentType(token);\n if (!agentType) {\n throw new Error('Invalid token: no agent registered');\n }\n\n const session = await this.sessionManager.createSession(\n agentType as AgentType,\n { ...options, sessionId, token }\n );\n\n // Only publish session:start when not a compensating creation\n if (!skipPublishSessionStart) {\n this.logger?.debug({ sessionId: session.id, agentType: session.agentType }, '[Gateway] Publishing session:start for created session');\n this.eventPublisher.publish(\n {\n type: 'session:start',\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n agentType: session.agentType,\n payload: { ...(options?.metadata ?? {}), cwd: session.cwd },\n metadata: {\n transportType: session.adapter.transportType,\n },\n },\n session\n );\n }\n\n return session;\n }\n\n /**\n * Get a session by ID\n */\n getSession(sessionId: string): Session | undefined {\n return this.sessionManager.getSession(sessionId);\n }\n\n /**\n * Get agent type for a session (used by NotificationHandler for lazy sessionAgentMap population)\n */\n getSessionAgentType(sessionId: string): 'claude' | 'codex' | undefined {\n const session = this.sessionManager.getSession(sessionId);\n return session?.agentType;\n }\n\n /**\n * List all sessions\n */\n listSessions(filter?: SessionFilter): SessionInfo[] {\n let sessions = this.sessionManager.listSessions();\n\n if (filter?.agentType) {\n sessions = sessions.filter((s) => s.agentType === filter.agentType);\n }\n\n if (!filter?.includeEnded) {\n sessions = sessions.filter((s) => s.status !== 'closed');\n }\n\n return sessions;\n }\n\n /**\n * End a session\n */\n async endSession(sessionId: string): Promise<void> {\n // Cancel any pending interactions for this session before closing\n this.interactionService.cancelBySession(sessionId, 'session ended');\n await this.sessionManager.closeSession(sessionId);\n }\n\n /**\n * Get the session manager for advanced operations\n */\n getSessionManager(): SessionManager {\n return this.sessionManager;\n }\n\n /**\n * Get the agent registry for advanced operations\n */\n getAgentRegistry(): AgentRegistry {\n return this.agentRegistry;\n }\n\n // === AgentBridgePort Implementation ===\n\n /** Emit an event envelope directly */\n emitEvent(envelope: AgentEventEnvelope): void {\n const session = this.sessionManager.getSession(envelope.sessionId);\n if (!session) {\n this.logger?.debug({ sessionId: envelope.sessionId }, '[Gateway] Session not found for emitEvent');\n return;\n }\n this.eventPublisher.publish(envelope, session);\n }\n\n async ensureSession(\n sessionId: string,\n options: CreateSessionOptions,\n agentType?: AgentType\n ): Promise<SessionSnapshot> {\n const existing = this.sessionManager.getSession(sessionId);\n if (existing) {\n return {\n id: existing.id,\n agentType: existing.agentType,\n getStatus: () => existing.getStatus(),\n sendCommand: async (cmd) => existing.sendCommand(cmd),\n };\n }\n\n // Try to get token from options, or look up from registry\n let token = options.token;\n if (!token && agentType) {\n // Find a registered agent of this type\n const agents = this.agentRegistry.listRegisteredAgents();\n const match = agents.find((a) => a.agentType === agentType);\n token = match?.token;\n }\n if (!token) {\n throw new Error(\n `Cannot create session ${sessionId}: no token provided and no registered agent found${agentType ? ` for type ${agentType}` : ''}`\n );\n }\n\n const session = await this.createSession(token, sessionId, options);\n return {\n id: session.id,\n agentType: session.agentType,\n getStatus: () => session.getStatus(),\n sendCommand: async (cmd) => session.sendCommand(cmd),\n };\n }\n\n async evaluateInteraction(request: InteractionRequest): Promise<InteractionResponse> {\n const sessionId = request.sessionId;\n if (!sessionId) {\n return { requestId: request.requestId, action: 'deny', message: 'No session ID' };\n }\n\n const session = this.sessionManager.getSession(sessionId);\n if (!session) {\n return { requestId: request.requestId, action: 'deny', message: 'Session not found' };\n }\n\n // Convert InteractionRequest to envelope for InteractionService\n const envelope: AgentEventEnvelope = {\n type: request.type === 'permission' ? 'permission:request' : 'question:request',\n sessionId,\n timestamp: new Date(request.timestamp).toISOString(),\n agentType: session.agentType,\n payload: {\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n },\n metadata: { transportType: session.adapter.transportType },\n };\n\n return await this.interactionService.evaluate(envelope);\n }\n}\n\n// Re-export gateway types\nexport * from './events.js';\nexport * from './interaction-service.js';\n","import type { EventBus as CoreEventBus } from '../core/bus/index.js';\nimport type { AgentEventEnvelope } from '../core/adapter/types.js';\nimport type { EventFrame } from './events.js';\nimport type { Session } from '../core/session/Session.js';\nimport type { Persistence } from '../shared/persistence.js';\n\nexport interface BroadcastFn {\n (frame: EventFrame): void;\n}\n\nexport class EventPublisher {\n constructor(\n private bus: CoreEventBus,\n private broadcastFn?: BroadcastFn,\n private persistence?: Persistence\n ) {}\n\n publish(envelope: AgentEventEnvelope, session: Session): void {\n switch (envelope.type) {\n case 'session:start': {\n const resolvedCwd = (envelope.payload.cwd as string) || session.cwd || undefined;\n this.bus.publishSessionStart({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n agentType: session.agentType,\n cwd: resolvedCwd,\n });\n break;\n }\n case 'session:end':\n this.bus.publishSessionEnd({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n chatId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n });\n break;\n case 'turn:finished': {\n // payload.lastAssistantMessage 由上游统一提供 (hook/remote 各自转换)\n const lastAssistantMsg = (envelope.payload.lastAssistantMessage as string | undefined) ?? '';\n const thinkingMsg = (envelope.payload.thinking as string | undefined) ?? '';\n const durationVal = (envelope.payload.durationMs as number | undefined);\n const turnCwd = (envelope.payload.cwd as string) || session.cwd || undefined;\n this.bus.publishTurnFinished({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n chatId: session.token ?? 'unknown',\n agentType: session.agentType,\n lastAssistantMessage: lastAssistantMsg,\n thinking: thinkingMsg,\n durationMs: durationVal,\n // 透传其他 payload 字段\n ...envelope.payload,\n cwd: turnCwd,\n });\n break;\n }\n case 'permission:request':\n // PermissionRequest bus publishing is handled by InteractionService when queued.\n // We only broadcast the frame here for WebSocket clients.\n break;\n case 'tool:executed':\n this.bus.publishToolExecuted({\n sessionId: session.id,\n toolCallId: envelope.payload.toolCallId as string,\n toolName: envelope.payload.toolName as string,\n summary: envelope.payload.summary as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n output: envelope.payload.output as string | undefined,\n isTimeout: envelope.payload.isTimeout as boolean ?? false,\n });\n break;\n case 'tool:started':\n this.bus.publishToolPost({\n sessionId: session.id,\n toolCallId: envelope.payload.toolCallId as string,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n });\n break;\n case 'tool:failure':\n this.bus.publishToolFailure({\n sessionId: session.id,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n error: envelope.payload.error as string | undefined,\n });\n break;\n case 'turn:thinking':\n this.bus.publishTurnThinking(session.id, envelope.payload.thinking as string);\n break;\n }\n\n if (this.broadcastFn) {\n const frame: EventFrame = {\n type: 'event',\n event: envelope.type,\n payload: {\n agentType: session.agentType,\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n data: envelope.payload,\n },\n };\n this.broadcastFn(frame);\n }\n\n // Persist event to disk\n if (this.persistence) {\n this.persistence.write(session.id, session.agentType, {\n event: envelope.type,\n timestamp: new Date().toISOString(),\n data: envelope.payload,\n }).catch(() => {\n // Ignore persistence errors to avoid blocking event flow\n });\n }\n }\n}\n","export interface ParsedCommand {\n /** First keyword after the agent prefix (e.g. 'help', 'model', 'status') */\n keyword: string;\n /** Remaining arguments */\n args: string[];\n /** Full remaining text after the keyword (for prompt) */\n content: string;\n}\n\n/**\n * Parse an inbound command string.\n * Supports:\n * /agent help → { keyword: 'help', args: [], content: '' }\n * /agent model gpt-4 → { keyword: 'model', args: ['gpt-4'], content: 'gpt-4' }\n * /agent hello world → { keyword: 'hello', args: ['world'], content: 'hello world' }\n *\n * Returns null if the text does not start with the given prefix.\n */\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function parseInboundCommand(text: string, prefix: string): ParsedCommand | null {\n const explicit = text.match(new RegExp(`^${escapeRegExp(prefix)}(?:@[^\\\\s]+)?(?:\\\\s+(.*))?$`, 's'));\n if (!explicit) return null;\n\n const rest = explicit[1]?.trim() ?? '';\n if (!rest) return { keyword: '', args: [], content: '' };\n\n const [keyword, ...args] = rest.split(/\\s+/);\n return {\n keyword,\n args,\n content: rest,\n };\n}\n\nexport function buildHelpText(agentName: string, prefix: string): string {\n return [\n `${agentName} commands:`,\n `${prefix} help - show this help message`,\n `${prefix} status - show the current chat session state`,\n `${prefix} stop - stop the active session for this chat`,\n `${prefix} <prompt> - run a task in the current chat`,\n 'Any other text is sent to the agent as a prompt.',\n ].join('\\n');\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { InboundMessage } from '../bus/events.js';\nimport type { AgentBridgePort } from './AgentBridgePort.js';\nimport type { AgentAdapter, TransportState, TransportInfo } from '../adapter/AgentAdapter.js';\nimport type { AgentEventEnvelope, AgentCommand, CreateSessionOptions } from '../adapter/types.js';\nimport { parseInboundCommand } from './inbound-utils.js';\n\nexport interface BaseAgentAdapterConfig {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n}\n\nexport interface AgentCommandHandler {\n description: string;\n usage?: string;\n handler: (args: string[], message: InboundMessage) => Promise<string | void>;\n}\n\nexport abstract class BaseAgentAdapter implements AgentAdapter {\n protected readonly bus: EventBus;\n protected readonly bridge: AgentBridgePort;\n protected readonly logger: Logger;\n protected readonly transports = new Map<string, TransportState>();\n private readonly agentCommands = new Map<string, AgentCommandHandler>();\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private unsubscribeFns: Array<() => void> = [];\n\n abstract readonly agentType: 'claude' | 'codex';\n abstract readonly transportType: 'hook' | 'sdk' | 'stdio' | 'remote';\n abstract readonly version: string;\n\n constructor(config: BaseAgentAdapterConfig) {\n this.bus = config.bus;\n this.bridge = config.bridge;\n this.logger = config.logger;\n }\n\n async initialize(): Promise<void> {\n this.subscribeInbound();\n this.logger.info(`${this.agentType} adapter initializing`);\n }\n\n async shutdown(): Promise<void> {\n for (const [sessionId, state] of this.transports) {\n try {\n await this.closeTransportState(state);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Error closing transport during shutdown');\n }\n }\n this.transports.clear();\n this.unsubscribeFns.forEach(fn => fn());\n this.unsubscribeFns = [];\n this.logger.info(`${this.agentType} adapter shutdown complete`);\n }\n\n /**\n * Whether this adapter supports receiving plain text as user prompts.\n * Override to `false` for passive/listen-only adapters (e.g. hook).\n */\n protected get supportsInboundPrompt(): boolean { return true; }\n\n /**\n * Register an agent-specific command.\n * Subclasses call this in their constructor to add custom commands\n * (e.g. `/claude model gpt-4`).\n */\n protected registerCommand(keyword: string, handler: AgentCommandHandler): void {\n this.agentCommands.set(keyword.toLowerCase(), handler);\n }\n\n abstract createTransportState(opts: CreateSessionOptions): Promise<TransportState>;\n abstract closeTransportState(state: TransportState): Promise<void>;\n abstract sendCommand(state: TransportState, command: AgentCommand): Promise<void>;\n\n async listTransportStates(): Promise<TransportInfo[]> {\n return Array.from(this.transports.values()).map(s => ({\n sessionId: s.sessionId,\n agentType: s.agentType,\n transportType: s.transportType,\n createdAt: new Date(),\n }));\n }\n\n async getTransportState(sessionId: string): Promise<TransportInfo | undefined> {\n const state = this.transports.get(sessionId);\n if (!state) return undefined;\n return {\n sessionId: state.sessionId,\n agentType: state.agentType,\n transportType: state.transportType,\n createdAt: new Date(),\n };\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return { healthy: true, message: `${this.transports.size} active transports` };\n }\n\n protected emitEvent(envelope: AgentEventEnvelope): void {\n if (this.eventHandler) {\n this.eventHandler(envelope);\n }\n this.bridge.emitEvent(envelope);\n }\n\n protected getHelpText(): string {\n const lines = [\n `${this.agentType} commands:`,\n `${this.prefix} help - show this help message`,\n `${this.prefix} status - show the current chat session state`,\n `${this.prefix} stop - stop the active session for this chat`,\n ];\n for (const [keyword, handler] of this.agentCommands) {\n lines.push(`${this.prefix} ${keyword}${handler.usage ? ` ${handler.usage}` : ''} - ${handler.description}`);\n }\n if (this.supportsInboundPrompt) {\n lines.push('Send any text to interact with the agent.');\n } else {\n lines.push('Send text to interact with the agent from its native interface.');\n }\n return lines.join('\\n');\n }\n\n private get prefix(): string {\n return `/${this.agentType}`;\n }\n\n protected subscribeInbound(): void {\n if (this.unsubscribeFns.length) return;\n this.unsubscribeFns.push(\n this.bus.onInbound((msg: InboundMessage) => this.handleInboundMessage(msg))\n );\n }\n\n protected async handleInboundMessage(message: InboundMessage): Promise<void> {\n const text = message.text.trim();\n this.logger.debug({ channel: message.channel, chatId: message.chatId, targetAgent: message.targetAgent }, 'Inbound message received');\n\n if (message.systemCommand) return;\n if (message.targetAgent !== this.agentType) return;\n\n const parsed = parseInboundCommand(text, this.prefix);\n const sessionId = `${this.agentType}-${message.chatId}`;\n\n if (!parsed) {\n // Non-command text (e.g. \"hi\"): treat as prompt for agent-driven transports.\n if (!this.supportsInboundPrompt) {\n this.logger.debug({ sessionId, textPreview: text.slice(0, 60) }, 'Inbound prompt ignored: adapter does not support user input');\n return;\n }\n await this.handlePrompt(sessionId, message, text);\n return;\n }\n\n const keyword = parsed.keyword.toLowerCase();\n\n // Empty keyword (e.g. \"/claude\" with no args) → show help\n if (!keyword) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n }\n\n // 1. Agent-specific custom commands take priority\n const agentHandler = this.agentCommands.get(keyword);\n if (agentHandler) {\n try {\n const result = await agentHandler.handler(parsed.args, message);\n if (result) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: result });\n }\n } catch (err) {\n this.logger.error({ sessionId, keyword, error: err instanceof Error ? err.message : String(err) }, 'Agent command failed');\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `Command /${this.agentType} ${keyword} failed: ${err instanceof Error ? err.message : String(err)}` });\n }\n return;\n }\n\n // 2. Base generic commands as fallback\n switch (keyword) {\n case 'help':\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n case 'status': {\n const session = this.bridge.getSession(sessionId);\n const reply = session && session.getStatus() === 'active'\n ? `${this.agentType} session is active.\\nSession ID: ${sessionId}`\n : `No active ${this.agentType} session for this chat.`;\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: reply });\n return;\n }\n case 'stop': {\n const session = this.bridge.getSession(sessionId);\n if (!session) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `No active ${this.agentType} session to stop.` });\n return;\n }\n await session.sendCommand({ type: 'stop' });\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `${this.agentType} session stopped.` });\n return;\n }\n }\n\n // 3. Unknown keyword — treat as prompt if supported\n if (!this.supportsInboundPrompt) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `Unknown command /${this.agentType} ${keyword}. Run /${this.agentType} help for available commands.` });\n return;\n }\n await this.handlePrompt(sessionId, message, parsed.content);\n }\n\n protected async handlePrompt(sessionId: string, message: InboundMessage, content: string): Promise<void> {\n const session = await this.bridge.ensureSession(sessionId, {\n chatId: message.chatId,\n channel: message.channel,\n metadata: {\n messageId: message.messageId,\n senderId: message.sender?.id,\n },\n }, this.agentType);\n await session.sendCommand({ type: 'user:message', content });\n }\n}\n","import type { AgentEventEnvelope, AgentEventType, AgentType, TransportType } from '../adapter/types.js';\nimport type { InteractionRequest } from '../interaction/types.js';\nimport type { MergedTool, TurnResult } from './TurnAggregator.js';\n\nexport interface TurnFinishedExtra {\n durationMs?: number;\n usage?: { inputTokens: number; outputTokens: number };\n}\n\nexport class EventNormalizer {\n static sessionStart(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n payload?: Record<string, unknown>,\n extraMetadata?: Record<string, unknown>\n ): AgentEventEnvelope {\n return this.build('session:start', sessionId, agentType, transportType, {\n sessionId,\n ...payload,\n }, extraMetadata);\n }\n\n static sessionEnd(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n reason?: string\n ): AgentEventEnvelope {\n return this.build('session:end', sessionId, agentType, transportType, { sessionId, reason });\n }\n\n static turnStarted(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType\n ): AgentEventEnvelope {\n return this.build('turn:started', sessionId, agentType, transportType, { sessionId });\n }\n\n static turnThinking(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n thinking: string\n ): AgentEventEnvelope {\n return this.build('turn:thinking', sessionId, agentType, transportType, { sessionId, thinking });\n }\n\n static turnFinished(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n result: TurnResult,\n extra?: TurnFinishedExtra\n ): AgentEventEnvelope {\n return this.build('turn:finished', sessionId, agentType, transportType, {\n sessionId,\n lastAssistantMessage: result.lastAssistantMessage,\n thinking: result.thinking,\n tools: (result.tools ?? []).map(t => ({\n toolCallId: t.toolCallId,\n toolName: t.toolName,\n summary: t.summary,\n toolInput: t.toolInput,\n output: t.output,\n isTimeout: t.isTimeout,\n })),\n durationMs: extra?.durationMs,\n usage: extra?.usage,\n });\n }\n\n static toolExecuted(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n tool: MergedTool\n ): AgentEventEnvelope {\n return this.build('tool:executed', sessionId, agentType, transportType, {\n sessionId,\n toolCallId: tool.toolCallId,\n toolName: tool.toolName,\n summary: tool.summary,\n toolInput: tool.toolInput,\n output: tool.output,\n isTimeout: tool.isTimeout,\n });\n }\n\n static toolFailure(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n tool: MergedTool,\n error?: string\n ): AgentEventEnvelope {\n return this.build('tool:failure', sessionId, agentType, transportType, {\n sessionId,\n toolCallId: tool.toolCallId,\n toolName: tool.toolName,\n summary: tool.summary,\n toolInput: tool.toolInput,\n error,\n });\n }\n\n static permissionRequest(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n request: InteractionRequest\n ): AgentEventEnvelope {\n return this.build('permission:request', sessionId, agentType, transportType, {\n sessionId,\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n }, { permissionRequestId: request.requestId });\n }\n\n static questionRequest(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n request: InteractionRequest\n ): AgentEventEnvelope {\n return this.build('question:request', sessionId, agentType, transportType, {\n sessionId,\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n }, { questionRequestId: request.requestId });\n }\n\n static fromHookEvent(\n eventType: string,\n payload: Record<string, unknown>,\n agentType: AgentType = 'claude',\n transportType: TransportType = 'hook'\n ): AgentEventEnvelope | null {\n const mapping: Record<string, AgentEventType> = {\n SessionStart: 'session:start',\n SessionEnd: 'session:end',\n PreToolUse: 'permission:request',\n PermissionRequest: 'permission:request',\n PostToolUse: 'tool:executed',\n PostToolUseFailure: 'tool:failure',\n Stop: 'turn:finished',\n };\n\n const type = mapping[eventType];\n if (!type) return null;\n\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : '';\n if (!sessionId) return null;\n\n const common = {\n sessionId,\n cwd: typeof payload.cwd === 'string' ? payload.cwd : undefined,\n permissionMode: typeof payload.permission_mode === 'string' ? payload.permission_mode : undefined,\n };\n\n switch (type) {\n case 'session:start':\n return this.build(type, sessionId, agentType, transportType, { ...common, permissionMode: common.permissionMode }, {\n rawEventType: eventType, permissionMode: common.permissionMode,\n });\n case 'session:end':\n return this.build(type, sessionId, agentType, transportType, { ...common, reason: payload.reason as string | undefined }, {\n rawEventType: eventType, permissionMode: common.permissionMode,\n });\n case 'permission:request': {\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : '';\n const isQuestion = toolName === 'AskUserQuestion';\n const requestId = typeof payload.request_id === 'string' ? payload.request_id : sessionId;\n return this.build(\n isQuestion ? 'question:request' : 'permission:request',\n sessionId,\n agentType,\n transportType,\n { ...common, toolName, toolInput: (payload.tool_input as Record<string, unknown>) || {}, requestId },\n { rawEventType: eventType, [isQuestion ? 'questionRequestId' : 'permissionRequestId']: requestId }\n );\n }\n case 'tool:executed':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n toolCallId: payload.id as string | undefined,\n toolName: payload.tool_name as string | undefined,\n toolInput: payload.tool_input as Record<string, unknown> | undefined,\n output: payload.output as string | undefined,\n }, { rawEventType: eventType });\n case 'tool:failure':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n toolName: payload.tool_name as string | undefined,\n toolInput: payload.tool_input as Record<string, unknown> | undefined,\n error: payload.error as string | undefined,\n }, { rawEventType: eventType });\n case 'turn:finished':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n reason: payload.reason as string | undefined,\n lastAssistantMessage: payload.last_assistant_message as string | undefined,\n durationMs: typeof payload.duration === 'number' ? payload.duration : undefined,\n }, { rawEventType: eventType });\n default:\n return null;\n }\n }\n\n private static build(\n type: AgentEventType,\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n payload: Record<string, unknown>,\n extraMetadata?: Record<string, unknown>\n ): AgentEventEnvelope {\n return {\n type,\n sessionId,\n timestamp: new Date().toISOString(),\n agentType,\n payload,\n metadata: {\n transportType,\n ...extraMetadata,\n },\n };\n }\n}\n","import type { AgentBridgePort } from './AgentBridgePort.js';\nimport type { InteractionRequest, InteractionResponse } from '../interaction/types.js';\n\nexport async function evaluateInteraction(\n bridge: AgentBridgePort,\n request: InteractionRequest\n): Promise<InteractionResponse> {\n const originalResponse = await bridge.evaluateInteraction(request);\n\n if (\n request.toolName === 'AskUserQuestion' &&\n (originalResponse.action === 'select' || originalResponse.action === 'input')\n ) {\n const questions = request.toolInput?.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; value?: unknown }>;\n multiSelect?: boolean;\n }> | undefined;\n const question = questions?.[0];\n const questionText = question?.question ?? '';\n const answerValue = originalResponse.selectedValues?.[0] ?? originalResponse.customInput ?? '';\n\n return {\n ...originalResponse,\n updatedInput: {\n ...request.toolInput,\n answers: { [questionText]: answerValue },\n },\n };\n }\n\n return originalResponse;\n}\n","// src/adapters/agent/claude/ClaudeHookAgentAdapter.ts\n// Claude Hook Agent Adapter - processes hook events and permission requests\n\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { AgentCommand } from '../../../core/adapter/types.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport { evaluateInteraction } from '../../../core/agent/interaction-utils.js';\nimport type { ClaudeHookEventType } from './hook-types.js';\n\nexport interface ClaudeHookAgentAdapterConfig {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n token?: string;\n}\n\n/**\n * Claude Hook Agent Adapter\n *\n * Extends BaseAgentAdapter to process Claude hook events and permission requests.\n * - Emits events via EventNormalizer.fromHookEvent() + emitEvent()\n * - Handles permission requests via evaluateInteraction()\n */\nexport class ClaudeHookAgentAdapter extends BaseAgentAdapter {\n readonly agentType = 'claude' as const;\n readonly transportType = 'hook' as const;\n readonly version = '1.0.0';\n\n /** Hook mode is listen-only; Claude drives via HTTP hooks. */\n protected override get supportsInboundPrompt(): boolean { return false; }\n\n private token: string;\n\n constructor(config: ClaudeHookAgentAdapterConfig) {\n super(config);\n this.token = config.token ?? '';\n }\n\n // === Transport Lifecycle ===\n\n async createTransportState(opts: { sessionId?: string; cwd?: string }): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `hook-${Date.now()}`;\n const state: TransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n cwd: opts.cwd ?? process.cwd(),\n };\n\n this.transports.set(sessionId, state);\n return state;\n }\n\n async closeTransportState(state: TransportState): Promise<void> {\n this.transports.delete(state.sessionId);\n }\n\n async processHookEvent(eventType: ClaudeHookEventType, payload: Record<string, unknown>): Promise<void> {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n if (!sessionId) {\n this.logger.debug({ eventType }, 'processHookEvent: no session_id in payload, skipping');\n return;\n }\n\n // SessionStart must create the session first so subsequent events have a session to bind to.\n if (eventType === 'SessionStart') {\n await this.bridge.ensureSession(sessionId, {\n cwd: payload.cwd as string | undefined,\n chatId: payload.chat_id as string | undefined,\n channel: payload.channel as string | undefined,\n metadata: {\n rawEventType: eventType,\n },\n }, this.agentType).catch((err) => {\n this.logger.warn({ sessionId, error: err instanceof Error ? err.message : String(err) }, 'ensureSession failed during SessionStart');\n });\n // createSession already publishes session:start; skip duplicate emission\n return;\n }\n\n const envelope = EventNormalizer.fromHookEvent(\n eventType, payload, this.agentType, this.transportType\n );\n if (!envelope) return;\n\n this.emitEvent(envelope);\n }\n\n async processPermissionRequest(\n eventType: 'PreToolUse' | 'PermissionRequest',\n payload: Record<string, unknown>,\n requestId: string\n ): Promise<InteractionResponse> {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : 'unknown';\n\n if (!sessionId) {\n this.logger.warn({ eventType, requestId }, 'processPermissionRequest: no session_id in payload');\n return { requestId, action: 'deny', message: 'Missing session_id' };\n }\n\n const interactionRequest: InteractionRequest = {\n type: toolName === 'AskUserQuestion' ? 'question' : 'permission',\n requestId,\n sessionId,\n toolName,\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n timestamp: Date.now(),\n };\n\n try {\n return await evaluateInteraction(this.bridge, interactionRequest);\n } catch (err) {\n this.logger.error({ err, requestId }, 'Permission evaluation failed');\n return { requestId, action: 'deny', message: 'Evaluation error' };\n }\n }\n\n async sendCommand(_state: TransportState, command: AgentCommand): Promise<void> {\n switch (command.type) {\n case 'stop': {\n this.logger.info({ sessionId: _state.sessionId }, 'Stop command received for hook transport');\n await this.closeTransportState(_state);\n break;\n }\n case 'user:message':\n // Hook mode: Claude drives via HTTP hooks; user:message is a no-op\n this.logger.debug({ sessionId: _state.sessionId }, 'user:message command ignored in hook mode');\n break;\n case 'interrupt':\n this.logger.debug({ sessionId: _state.sessionId }, 'interrupt command ignored in hook mode');\n break;\n default:\n this.logger.debug({ sessionId: _state.sessionId, commandType: command.type }, 'Unhandled command in hook mode');\n }\n }\n\n}\n","import { randomUUID } from 'crypto';\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport { evaluateInteraction } from '../../../core/agent/interaction-utils.js';\nimport { TurnAggregator } from '../../../core/agent/TurnAggregator.js';\nimport type { MergedTool } from '../../../core/agent/TurnAggregator.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { AgentCommand, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { ClaudeSessionScanner } from './scanner.js';\nimport { query } from './sdk/query.js';\nimport type { SDKMessage, SDKUserMessage, PermissionResult, QuestionResult } from './sdk/types.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\n\ninterface RemoteTransportState extends TransportState {\n query: ReturnType<typeof query>;\n input: PushableAsyncIterable<SDKUserMessage>;\n aggregator: TurnAggregator;\n turnInProgress: boolean;\n chatId: string;\n channel: string;\n cwd: string;\n}\n\nclass PushableAsyncIterable<T> implements AsyncIterable<T> {\n private queue: T[] = [];\n private resolvers: Array<(value: IteratorResult<T>) => void> = [];\n private ended = false;\n\n push(value: T): void {\n if (this.ended) return;\n if (this.resolvers.length > 0) {\n const resolve = this.resolvers.shift()!;\n resolve({ done: false, value });\n } else {\n this.queue.push(value);\n }\n }\n\n end(): void {\n this.ended = true;\n while (this.resolvers.length > 0) {\n const resolve = this.resolvers.shift()!;\n resolve({ done: true, value: undefined });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: () => {\n if (this.queue.length > 0) {\n return Promise.resolve({ done: false, value: this.queue.shift()! });\n }\n if (this.ended) {\n return Promise.resolve({ done: true, value: undefined });\n }\n return new Promise((resolve) => {\n this.resolvers.push(resolve);\n });\n },\n return: () => {\n this.end();\n return Promise.resolve({ done: true, value: undefined });\n },\n };\n }\n}\n\nexport class ClaudeRemoteAgentAdapter extends BaseAgentAdapter {\n readonly agentType = 'claude' as const;\n readonly transportType = 'remote' as const;\n readonly version = '1.0.0';\n private static scanner: ClaudeSessionScanner | null = null;\n private static readonly CONTROL_REQUEST_TIMEOUT_MS = 300000;\n\n private token: string;\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n private defaultWorkDir?: string;\n private defaultModel?: string;\n private defaultPermissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n\n private static readonly VALID_PERMISSION_MODES = ['default', 'acceptEdits', 'bypassPermissions', 'plan'] as const;\n\n constructor(options: {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n token: string;\n command?: string[];\n cwd?: string;\n env?: Record<string, string>;\n defaultWorkDir?: string;\n defaultModel?: string;\n defaultPermissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n }) {\n super({ bus: options.bus, bridge: options.bridge, logger: options.logger });\n this.token = options.token;\n this.command = options.command?.length ? options.command : ['claude'];\n this.spawnCwd = options.cwd;\n this.envExtra = options.env ?? {};\n this.defaultWorkDir = options.defaultWorkDir;\n this.defaultModel = options.defaultModel;\n this.defaultPermissionMode = options.defaultPermissionMode;\n\n this.registerCommand('model', {\n description: 'Set default model for new sessions',\n usage: '<model-name>',\n handler: async (args) => {\n const model = args[0];\n if (!model) return 'Usage: /claude model <model-name> (e.g. sonnet, opus)';\n this.defaultModel = model;\n return `Default model set to ${model}. Will apply on next session.`;\n },\n });\n\n this.registerCommand('permission', {\n description: 'Set default permission mode',\n usage: '<default|acceptEdits|bypassPermissions|plan>',\n handler: async (args) => {\n const mode = args[0] as typeof this.defaultPermissionMode;\n const valid = ClaudeRemoteAgentAdapter.VALID_PERMISSION_MODES;\n if (!valid.includes(mode as (typeof valid)[number])) {\n return `Invalid mode \"${mode}\". Available: ${valid.join(', ')}`;\n }\n this.defaultPermissionMode = mode;\n return `Default permission mode set to ${mode}.`;\n },\n });\n }\n\n async initialize(): Promise<void> {\n await super.initialize();\n this.logger.info('ClaudeRemoteAgentAdapter initializing');\n try {\n const { execSync } = await import('child_process');\n execSync(`${this.command[0]} --version`, { encoding: 'utf8', windowsHide: true });\n this.logger.info('Claude CLI detected');\n } catch (err) {\n this.logger.warn('Claude CLI not found');\n throw err;\n }\n\n if (!ClaudeRemoteAgentAdapter.scanner) {\n ClaudeRemoteAgentAdapter.scanner = new ClaudeSessionScanner();\n SessionScannerRegistry.getInstance().register(ClaudeRemoteAgentAdapter.scanner);\n this.logger.info('Claude session scanner registered');\n }\n }\n\n async createTransportState(opts: CreateSessionOptions): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `claude-${randomUUID().slice(0, 8)}`;\n const chatId = opts.chatId ?? sessionId;\n const channel = opts.channel ?? 'broadcast';\n const cwd = opts.cwd || this.defaultWorkDir || process.cwd();\n this.logger.info({ sessionId, chatId, cwd, optsCwd: opts.cwd, defaultWorkDir: this.defaultWorkDir }, 'Creating Claude remote transport state');\n\n const input = new PushableAsyncIterable<SDKUserMessage>();\n const q = query({\n prompt: input,\n options: {\n cwd: this.spawnCwd,\n model: opts.model ?? this.defaultModel,\n permissionMode: this.defaultPermissionMode,\n env: this.envExtra,\n pathToClaudeCodeExecutable: this.command[0],\n bare: true,\n canCallTool: (toolName, toolInput, { signal }) => this.handleCanCallTool(sessionId, toolName, toolInput, signal),\n canAnswerQuestion: (question, { signal }) => this.handleCanAnswerQuestion(sessionId, question, signal),\n },\n });\n\n const aggregator = new TurnAggregator(this.logger, sessionId);\n aggregator.onThinkingChunk = (_chunk: string) => {\n // Noop: streaming not implemented yet.\n };\n\n const state: RemoteTransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n query: q,\n input,\n aggregator,\n turnInProgress: false,\n chatId,\n channel,\n cwd,\n };\n\n this.transports.set(sessionId, state);\n\n this.emitEvent(EventNormalizer.sessionStart(sessionId, this.agentType, this.transportType, {\n chatId,\n channel,\n cwd,\n ...opts.metadata,\n }));\n\n this.consumeQueryMessages(q, sessionId, state).catch((err) => {\n this.logger.error({ sessionId, error: err }, 'Query consumer error');\n });\n\n this.logger.info({ sessionId }, 'Claude remote transport state created');\n return state;\n }\n\n async closeTransportState(state: TransportState): Promise<void> {\n const remoteState = state as RemoteTransportState;\n const sessionId = remoteState.sessionId;\n this.logger.info({ sessionId }, 'Closing Claude remote transport state');\n\n remoteState.input.end();\n remoteState.query.kill('SIGTERM');\n remoteState.aggregator.reset();\n this.transports.delete(sessionId);\n\n this.emitEvent(EventNormalizer.sessionEnd(sessionId, this.agentType, this.transportType, 'close'));\n }\n\n async sendCommand(state: TransportState, command: AgentCommand): Promise<void> {\n const remoteState = state as RemoteTransportState;\n const sessionId = remoteState.sessionId;\n\n switch (command.type) {\n case 'user:message': {\n if (remoteState.turnInProgress) {\n this.logger.warn({ sessionId }, 'Concurrent turn rejected');\n this.bus.publishOutbound({\n channel: remoteState.channel,\n chatId: remoteState.chatId,\n text: 'Claude is still processing the previous message. Please wait.',\n });\n return;\n }\n remoteState.aggregator.startTurn();\n remoteState.turnInProgress = true;\n this.emitEvent(EventNormalizer.turnStarted(sessionId, this.agentType, this.transportType));\n remoteState.input.push({\n type: 'user',\n message: { role: 'user', content: command.content },\n });\n break;\n }\n case 'interrupt': {\n this.logger.info({ sessionId }, 'Interrupting turn');\n await remoteState.query.interrupt();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n await this.closeTransportState(remoteState);\n break;\n }\n default: {\n this.logger.warn({ sessionId, commandType: command.type }, 'Unsupported command');\n }\n }\n }\n\n // === Internal ===\n\n private async consumeQueryMessages(q: ReturnType<typeof query>, sessionId: string, state: RemoteTransportState): Promise<void> {\n try {\n for await (const msg of q) {\n await this.handleSdkMessage(msg, sessionId, state);\n }\n } catch (err) {\n this.logger.error({ sessionId, error: err }, 'Claude remote stream ended with error');\n this.bus.publishOutbound({\n channel: state.channel,\n chatId: state.chatId,\n text: 'Claude session ended unexpectedly.',\n });\n } finally {\n state.aggregator.reset();\n state.turnInProgress = false;\n this.transports.delete(sessionId);\n this.emitEvent(EventNormalizer.sessionEnd(sessionId, this.agentType, this.transportType, 'stream_ended'));\n }\n }\n\n private async handleSdkMessage(msg: SDKMessage, sessionId: string, state: RemoteTransportState): Promise<void> {\n switch (msg.type) {\n case 'system': {\n const system = msg as { session_id?: string; subtype?: string };\n if (system.subtype === 'init' && system.session_id) {\n this.logger.info({ sessionId, claudeSessionId: system.session_id }, 'Claude session initialized');\n }\n break;\n }\n\n case 'assistant': {\n const assistant = msg as { message?: { content?: Array<{ type: string; text?: string; thinking?: string; name?: string; input?: unknown; id?: string }> } };\n const blocks = Array.isArray(assistant.message?.content) ? assistant.message.content : [];\n for (const block of blocks) {\n if (block.type === 'text' && typeof block.text === 'string') {\n state.aggregator.addAssistantText(block.text);\n }\n if (block.type === 'thinking' && typeof block.thinking === 'string') {\n state.aggregator.addThinking(block.thinking);\n }\n if (block.type === 'tool_use') {\n const toolName = typeof block.name === 'string' ? block.name : 'unknown';\n const toolCallId = typeof block.id === 'string' ? block.id : Math.random().toString(36).substring(2);\n state.aggregator.addPendingTool(toolCallId, toolName, block.input ?? {}, () => {});\n }\n }\n break;\n }\n\n case 'user': {\n const user = msg as { message?: { content?: string | Array<{ type: string; text?: string; tool_use_id?: string }> } };\n const content = user.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {\n state.aggregator.resolveTool(block.tool_use_id, block.text ?? '', (merged: MergedTool) => {\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, merged));\n });\n }\n }\n }\n break;\n }\n\n case 'result': {\n const result = msg as { subtype?: string; result?: string; duration_ms?: number; usage?: { input_tokens: number; output_tokens: number } };\n this.logger.info({ sessionId, subtype: result.subtype }, 'Claude turn result');\n\n const thinking = state.aggregator.getThinking();\n const flushResult = state.aggregator.flushTurn((merged: MergedTool) => {\n const envelope = merged.isTimeout\n ? EventNormalizer.toolFailure(sessionId, this.agentType, this.transportType, merged)\n : EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, merged);\n this.emitEvent(envelope);\n });\n\n if (thinking) {\n this.emitEvent(EventNormalizer.turnThinking(sessionId, this.agentType, this.transportType, thinking));\n }\n\n this.emitEvent(\n EventNormalizer.turnFinished(sessionId, this.agentType, this.transportType, flushResult, {\n durationMs: result.duration_ms,\n usage: result.usage\n ? {\n inputTokens: result.usage.input_tokens,\n outputTokens: result.usage.output_tokens,\n }\n : undefined,\n })\n );\n state.turnInProgress = false;\n break;\n }\n\n case 'log': {\n const log = msg as { log?: { level?: string; message?: string } };\n const level = log.log?.level ?? 'debug';\n const message = log.log?.message ?? '';\n if (level === 'error') this.logger.error({ sessionId }, message);\n else if (level === 'warn') this.logger.warn({ sessionId }, message);\n else if (level === 'info') this.logger.info({ sessionId }, message);\n else this.logger.debug({ sessionId }, message);\n break;\n }\n }\n }\n\n private async handleCanCallTool(sessionId: string, toolName: string, toolInput: unknown, signal: AbortSignal): Promise<PermissionResult> {\n const state = this.transports.get(sessionId) as RemoteTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId, toolName }, 'Permission request but session not found, auto-denying');\n return { behavior: 'deny', message: 'Session not found' };\n }\n\n const requestId = `${sessionId}-${Math.random().toString(36).substring(2, 10)}`;\n this.logger.info({ sessionId, requestId, toolName }, 'Claude remote permission request');\n\n const interactionRequest: InteractionRequest = {\n requestId,\n sessionId,\n type: 'permission',\n toolName,\n toolInput: (toolInput ?? {}) as Record<string, unknown>,\n timestamp: Date.now(),\n };\n\n return new Promise<PermissionResult>((resolve) => {\n const timeout = setTimeout(() => {\n this.logger.warn({ sessionId, requestId }, 'Permission request timeout');\n resolve({ behavior: 'deny', message: 'Timeout' });\n }, ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve({ behavior: 'deny', message: 'Aborted' });\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n evaluateInteraction(this.bridge, interactionRequest).then((response) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n\n const decision: 'allow' | 'deny' = response.action === 'allow' ? 'allow' : 'deny';\n\n this.logger.info({ sessionId, requestId, toolName, decision }, 'Claude remote permission resolved');\n resolve({\n behavior: decision,\n updatedInput: response.updatedInput,\n ...(decision === 'deny' ? { message: 'User denied this tool call' } : {}),\n } as PermissionResult);\n }).catch((err) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n this.logger.error({ error: err, sessionId, requestId }, 'Claude remote permission handler error');\n resolve({ behavior: 'deny', message: 'Error' });\n });\n });\n }\n\n private async handleCanAnswerQuestion(sessionId: string, question: string, signal: AbortSignal): Promise<QuestionResult> {\n const state = this.transports.get(sessionId) as RemoteTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId }, 'Question request but session not found, auto-deny');\n return { action: 'deny', message: 'Session not found' };\n }\n\n const requestId = `${sessionId}-${Math.random().toString(36).substring(2, 10)}`;\n this.logger.info({ sessionId, requestId, question }, 'Claude remote question request');\n\n const interactionRequest: InteractionRequest = {\n requestId,\n sessionId,\n type: 'question',\n toolName: 'AskUserQuestion',\n toolInput: { questions: [{ question }] },\n timestamp: Date.now(),\n };\n\n return new Promise<QuestionResult>((resolve) => {\n const timeout = setTimeout(() => {\n this.logger.warn({ sessionId, requestId }, 'Question request timeout');\n resolve({ action: 'deny', message: 'Timeout' });\n }, ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve({ action: 'deny', message: 'Aborted' });\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n evaluateInteraction(this.bridge, interactionRequest).then((response) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n if (!response) {\n resolve({ action: 'deny', message: 'No response' });\n return;\n }\n if (response.action === 'allow' || response.action === 'select') {\n const answer = response.selectedValues?.[0] ?? response.customInput ?? '';\n resolve({ action: 'answer', answer: String(answer) });\n } else {\n resolve({ action: 'deny', message: response.message ?? 'User denied' });\n }\n }).catch((err) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n this.logger.error({ error: err, sessionId, requestId }, 'Claude remote question handler error');\n resolve({ action: 'deny', message: 'Error' });\n });\n });\n }\n}\n","import type { Logger } from 'pino';\n\ninterface ToolPending {\n toolCallId: string;\n toolName: string;\n toolInput: unknown;\n hasBeenResolved?: boolean;\n}\n\nexport interface MergedTool {\n toolCallId: string;\n toolName: string;\n summary: string;\n toolInput: unknown;\n output?: string;\n isTimeout: boolean;\n}\n\nexport interface TurnResult {\n lastAssistantMessage: string;\n thinking: string;\n tools: MergedTool[];\n}\n\nexport class TurnAggregator {\n private assistantParts: string[] = [];\n private thinkingParts: string[] = [];\n private pendingTools = new Map<string, ToolPending>();\n /** Track tool_call_ids whose result has already been emitted (out-of-order or orphaned tool_result) */\n private resolvedToolCallIds = new Set<string>();\n private turnInProgress = false;\n\n constructor(\n private logger: Logger,\n private sessionId: string,\n ) {}\n\n startTurn(): void {\n this.reset();\n this.turnInProgress = true;\n }\n\n addAssistantText(content: string): void {\n this.assistantParts.push(content);\n }\n\n addThinking(content: string): void {\n this.thinkingParts.push(content);\n // [Extension Point] Streaming thinking: onThinkingChunk fires here per chunk.\n // Currently noop; streaming upgrade activates it in ClaudeRemoteAdapter.startSession().\n this.onThinkingChunk?.(content);\n }\n\n /**\n * [Extension Point — Streaming Thinking]\n * Callback for streaming thinking events. Set by the owner to emit thinking chunks\n * as they arrive (real-time streaming to Feishu/Telegram).\n *\n * Current behavior: set to noop in ClaudeRemoteAdapter.startSession(). The complete\n * thinking is emitted as a single turn:thinking event in handleResult.\n *\n * Future streaming upgrade: replace the noop with a debounced emit that sends\n * accumulated thinking every N ms or per chunk, without waiting for turn end.\n * No changes needed in TurnAggregator, NotificationHandler, or Feishu formatter —\n * only this callback implementation changes.\n */\n onThinkingChunk?: (chunk: string) => void;\n\n addPendingTool(\n toolCallId: string,\n toolName: string,\n toolInput: unknown,\n _onMerged: (tool: MergedTool) => void,\n ): void {\n // If this tool_call_id was already resolved out-of-order, skip creating a pending\n if (this.resolvedToolCallIds.has(toolCallId)) {\n this.logger.debug({ sessionId: this.sessionId, toolCallId }, 'tool_use arrived after out-of-order tool_result, skipping duplicate pending');\n this.resolvedToolCallIds.delete(toolCallId);\n return;\n }\n\n this.pendingTools.set(toolCallId, { toolCallId, toolName, toolInput, hasBeenResolved: false });\n }\n\n resolveTool(\n toolCallId: string,\n output: string,\n onMerged: (tool: MergedTool) => void,\n ): void {\n const pending = this.pendingTools.get(toolCallId);\n if (!pending) {\n // Out-of-order: tool_result arrived before tool_use (or already timed out).\n // Record it so addPendingTool doesn't create a duplicate pending.\n if (this.resolvedToolCallIds.has(toolCallId)) {\n this.logger.debug({ sessionId: this.sessionId, toolCallId }, 'tool_result already processed, skipping duplicate');\n return;\n }\n this.resolvedToolCallIds.add(toolCallId);\n this.logger.warn({ sessionId: this.sessionId, toolCallId }, 'tool_result without matching tool_use');\n onMerged({\n toolCallId,\n toolName: 'unknown',\n summary: output.slice(0, 100),\n toolInput: {},\n output,\n isTimeout: false,\n });\n return;\n }\n\n pending.hasBeenResolved = true;\n this.pendingTools.delete(toolCallId);\n const merged = this.buildMergedTool(pending, output, false);\n onMerged(merged);\n }\n\n flushTurn(onTool: (tool: MergedTool) => void): TurnResult {\n this.turnInProgress = false;\n\n const flushedTools: MergedTool[] = [];\n for (const [toolCallId, pending] of this.pendingTools) {\n pending.hasBeenResolved = true;\n this.resolvedToolCallIds.add(toolCallId);\n const merged = this.buildMergedTool(pending, undefined, true);\n flushedTools.push(merged);\n onTool(merged);\n }\n this.pendingTools.clear();\n\n const lastAssistantMessage = this.assistantParts.join('\\n');\n const thinking = this.thinkingParts.join('\\n');\n this.assistantParts = [];\n this.thinkingParts = [];\n\n return { lastAssistantMessage, thinking, tools: flushedTools };\n }\n\n reset(): void {\n this.turnInProgress = false;\n this.pendingTools.clear();\n this.resolvedToolCallIds.clear();\n this.assistantParts = [];\n this.thinkingParts = [];\n }\n\n isTurnInProgress(): boolean {\n return this.turnInProgress;\n }\n\n /**\n * Get accumulated thinking content without flushing.\n *\n * [Extension Point] Used by ClaudeRemoteAdapter to read accumulated thinking before\n * calling flushTurn(), which resets thinkingParts. This allows the owner to emit a\n * complete turn:thinking event before the aggregator state is cleared.\n *\n * For streaming upgrades, this is not needed — onThinkingChunk already emits per-chunk.\n */\n getThinking(): string {\n return this.thinkingParts.join('\\n');\n }\n\n private buildMergedTool(pending: ToolPending, output: string | undefined, isTimeout: boolean): MergedTool {\n const summary = this.buildToolSummary(pending.toolName, pending.toolInput, output);\n return {\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n summary,\n toolInput: pending.toolInput,\n output,\n isTimeout,\n };\n }\n\n private buildToolSummary(toolName: string, input: unknown, output: string | undefined): string {\n const inputStr = this.truncate(JSON.stringify(input ?? {}), 200);\n const outputStr = output ? ` -> ${this.truncate(output, 200)}` : '';\n return `${toolName}: ${inputStr}${outputStr}`;\n }\n\n private truncate(str: string, max: number): string {\n return str.length > max ? `${str.slice(0, max)}...` : str;\n }\n}\n","// src/core/session-scanner/registry.ts\n\nimport type { AgentType } from '../adapter/types.js';\nimport type { SessionInfo } from '../adapter/types.js';\nimport type { SessionScanner } from './types.js';\n\n/**\n * Session Scanner 注册表\n * 管理所有 CLI 的 Scanner 实现\n */\nexport class SessionScannerRegistry {\n private scanners: Map<AgentType, SessionScanner> = new Map();\n\n /**\n * 注册 Scanner\n */\n register(scanner: SessionScanner): void {\n if (this.scanners.has(scanner.agentType)) {\n console.warn(`Scanner for ${scanner.agentType} already registered, overwriting`);\n }\n this.scanners.set(scanner.agentType, scanner);\n }\n\n /**\n * 注销 Scanner\n */\n unregister(agentType: AgentType): void {\n this.scanners.delete(agentType);\n }\n\n /**\n * 获取指定类型的 Scanner\n */\n getScanner(agentType: AgentType): SessionScanner | undefined {\n return this.scanners.get(agentType);\n }\n\n /**\n * 扫描所有 agent 的 session\n */\n async scanAll(): Promise<SessionInfo[]> {\n const results = await Promise.all(\n Array.from(this.scanners.values()).map((scanner) => scanner.scanSessions())\n );\n return results.flat();\n }\n\n /**\n * 按 agent 类型扫描\n */\n async scanByAgent(agentType: AgentType): Promise<SessionInfo[]> {\n const scanner = this.scanners.get(agentType);\n if (!scanner) {\n return [];\n }\n return scanner.scanSessions();\n }\n\n /**\n * 获取所有已注册的 agent 类型\n */\n listAgents(): AgentType[] {\n return Array.from(this.scanners.keys());\n }\n\n /**\n * 获取单例实例\n */\n static getInstance(): SessionScannerRegistry {\n if (!SessionScannerRegistry.instance) {\n SessionScannerRegistry.instance = new SessionScannerRegistry();\n }\n return SessionScannerRegistry.instance;\n }\n\n private static instance: SessionScannerRegistry | null = null;\n}","// src/adapters/agent/claude/scanner.ts\n\nimport { readdir, readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport type { SessionInfo } from '../../../core/adapter/types.js';\nimport type { SessionScanner } from '../../../core/session-scanner/types.js';\n\n/**\n * Claude Code Session Scanner\n * 扫描 ~/.claude/sessions/ 目录\n */\nexport class ClaudeSessionScanner implements SessionScanner {\n readonly agentType = 'claude' as const;\n private readonly sessionDir: string;\n\n constructor() {\n this.sessionDir = resolve(process.env.HOME || '', '.claude/sessions');\n }\n\n getSessionDir(): string {\n return this.sessionDir;\n }\n\n async scanSessions(): Promise<SessionInfo[]> {\n const sessions: SessionInfo[] = [];\n\n try {\n const files = await readdir(this.sessionDir);\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\n\n for (const file of jsonFiles) {\n try {\n const filePath = join(this.sessionDir, file);\n const content = await readFile(filePath, 'utf-8');\n const meta = JSON.parse(content) as {\n pid?: number;\n sessionId?: string;\n cwd?: string;\n startedAt?: number;\n };\n\n if (!meta.sessionId) {\n continue;\n }\n\n const isActive = meta.pid ? await this.checkProcessAlive(meta.pid) : false;\n\n sessions.push({\n id: meta.sessionId,\n agentType: this.agentType,\n transportType: 'hook',\n status: isActive ? 'active' : 'ended',\n startedAt: meta.startedAt ? new Date(meta.startedAt) : new Date(),\n cwd: meta.cwd,\n });\n } catch {\n // 忽略解析错误的文件\n }\n }\n } catch {\n // 目录不存在或无权限\n }\n\n return sessions;\n }\n\n private async checkProcessAlive(pid: number): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n process.kill(pid, 0);\n resolve(true);\n } catch {\n resolve(false);\n }\n });\n }\n}","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';\nimport { createInterface } from 'node:readline';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { Stream } from './stream.js';\nimport type {\n QueryOptions,\n QueryPrompt,\n SDKMessage,\n SDKControlResponse,\n CanUseToolControlRequest,\n CanUseToolControlResponse,\n ControlCancelRequest,\n PermissionResult,\n QuestionResult,\n} from './types.js';\nimport { AbortError } from './types.js';\nimport type { Writable } from 'node:stream';\n\nfunction getCleanEnv(): NodeJS.ProcessEnv {\n const env = { ...process.env };\n const cwd = process.cwd();\n const pathSep = process.platform === 'win32' ? ';' : ':';\n const pathKey = process.platform === 'win32' ? 'Path' : 'PATH';\n const actualPathKey = Object.keys(env).find((k) => k.toLowerCase() === 'path') || pathKey;\n if (env[actualPathKey]) {\n env[actualPathKey] = env[actualPathKey]!\n .split(pathSep)\n .filter((p) => {\n const normalizedP = p.replace(/\\\\/g, '/').toLowerCase();\n const normalizedCwd = cwd.replace(/\\\\/g, '/').toLowerCase();\n return !normalizedP.startsWith(normalizedCwd);\n })\n .join(pathSep);\n }\n return env;\n}\n\nexport function buildClaudeArgs(options: QueryOptions): string[] {\n const args = ['--output-format', 'stream-json', '--verbose'];\n if (options.customSystemPrompt) args.push('--system-prompt', options.customSystemPrompt);\n if (options.appendSystemPrompt) args.push('--append-system-prompt', options.appendSystemPrompt);\n if (options.maxTurns !== undefined) args.push('--max-turns', String(options.maxTurns));\n if (options.model) args.push('--model', options.model);\n if (options.canCallTool) {\n args.push('--permission-prompt-tool', 'stdio');\n }\n if (options.continue) args.push('--continue');\n if (options.resume) args.push('--resume', options.resume);\n if (options.allowedTools && options.allowedTools.length > 0) {\n args.push('--allowedTools', options.allowedTools.join(','));\n }\n if (options.disallowedTools && options.disallowedTools.length > 0) {\n args.push('--disallowedTools', options.disallowedTools.join(','));\n }\n if (options.mcpServers && Object.keys(options.mcpServers).length > 0) {\n args.push('--mcp-config', JSON.stringify({ mcpServers: options.mcpServers }));\n }\n if (options.strictMcpConfig) args.push('--strict-mcp-config');\n if (options.permissionMode) args.push('--permission-mode', options.permissionMode);\n if (options.settingsPath) args.push('--settings', options.settingsPath);\n if (options.bare) args.push('--bare');\n if (options.fallbackModel) {\n if (options.model && options.fallbackModel === options.model) {\n throw new Error('Fallback model cannot be the same as the main model. Please specify a different model for fallbackModel option.');\n }\n args.push('--fallback-model', options.fallbackModel);\n }\n return args;\n}\n\nclass Query implements AsyncIterableIterator<SDKMessage> {\n private pendingControlResponses = new Map<string, (response: SDKControlResponse['response']) => void>();\n private cancelControllers = new Map<string, AbortController>();\n private inputStream = new Stream<SDKMessage>();\n private sdkMessages: AsyncIterableIterator<SDKMessage>;\n private child?: ChildProcessWithoutNullStreams;\n\n constructor(\n private childStdin: Writable | null,\n private childStdout: NodeJS.ReadableStream,\n private processExitPromise: Promise<void>,\n private canCallTool?: (toolName: string, input: unknown, options: { signal: AbortSignal }) => Promise<PermissionResult>,\n private canAnswerQuestion?: (question: string, options: { signal: AbortSignal }) => Promise<QuestionResult>\n ) {\n this.readMessages();\n this.sdkMessages = this.readSdkMessages();\n }\n\n setChild(child: ChildProcessWithoutNullStreams): void {\n this.child = child;\n }\n\n kill(signal: NodeJS.Signals = 'SIGTERM'): void {\n if (this.child && !this.child.killed) {\n this.child.kill(signal);\n }\n }\n\n setError(error: Error): void {\n this.inputStream.error(error);\n }\n\n next(...args: [] | [undefined]): Promise<IteratorResult<SDKMessage>> {\n return this.sdkMessages.next(...args);\n }\n\n return(value?: any): Promise<IteratorResult<SDKMessage>> {\n if (this.sdkMessages.return) {\n return this.sdkMessages.return(value);\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n\n throw(e: any): Promise<IteratorResult<SDKMessage>> {\n if (this.sdkMessages.throw) {\n return this.sdkMessages.throw(e);\n }\n return Promise.reject(e);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<SDKMessage> {\n return this.sdkMessages;\n }\n\n private async readMessages(): Promise<void> {\n const rl = createInterface({ input: this.childStdout });\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const message = JSON.parse(line) as SDKMessage | SDKControlResponse;\n if (message.type === 'control_response') {\n const cr = message as SDKControlResponse;\n const handler = this.pendingControlResponses.get(cr.response.request_id);\n if (handler) handler(cr.response);\n continue;\n }\n if (message.type === 'control_request') {\n await this.handleControlRequest(message as unknown as CanUseToolControlRequest);\n continue;\n }\n if (message.type === 'control_cancel_request') {\n this.handleControlCancelRequest(message as unknown as ControlCancelRequest);\n continue;\n }\n this.inputStream.enqueue(message);\n } catch {\n // ignore non-JSON\n }\n }\n await this.processExitPromise;\n } catch (error) {\n this.inputStream.error(error as Error);\n } finally {\n this.inputStream.done();\n this.cleanupControllers();\n rl.close();\n }\n }\n\n private async *readSdkMessages(): AsyncIterableIterator<SDKMessage> {\n for await (const message of this.inputStream) {\n yield message;\n }\n }\n\n async interrupt(): Promise<void> {\n if (!this.childStdin) throw new Error('Interrupt requires --input-format stream-json');\n await this.request({ subtype: 'interrupt' }, this.childStdin);\n }\n\n private request(request: { subtype: string }, childStdin: Writable): Promise<SDKControlResponse['response']> {\n const requestId = Math.random().toString(36).substring(2, 15);\n const sdkRequest = {\n request_id: requestId,\n type: 'control_request',\n request,\n };\n return new Promise((resolve, reject) => {\n this.pendingControlResponses.set(requestId, (response) => {\n if (response.subtype === 'success') {\n resolve(response);\n } else {\n reject(new Error(response.error));\n }\n });\n childStdin.write(JSON.stringify(sdkRequest) + '\\n');\n });\n }\n\n private async handleControlRequest(request: CanUseToolControlRequest): Promise<void> {\n if (!this.childStdin) return;\n const controller = new AbortController();\n this.cancelControllers.set(request.request_id, controller);\n try {\n const response = await this.processControlRequest(request, controller.signal);\n const controlResponse: CanUseToolControlResponse = {\n type: 'control_response',\n response: {\n subtype: 'success',\n request_id: request.request_id,\n response,\n },\n };\n this.childStdin.write(JSON.stringify(controlResponse) + '\\n');\n } catch (error) {\n const controlErrorResponse: CanUseToolControlResponse = {\n type: 'control_response',\n response: {\n subtype: 'error',\n request_id: request.request_id,\n error: error instanceof Error ? error.message : String(error),\n },\n };\n this.childStdin.write(JSON.stringify(controlErrorResponse) + '\\n');\n } finally {\n this.cancelControllers.delete(request.request_id);\n }\n }\n\n private handleControlCancelRequest(request: ControlCancelRequest): void {\n const controller = this.cancelControllers.get(request.request_id);\n if (controller) {\n controller.abort();\n this.cancelControllers.delete(request.request_id);\n }\n }\n\n private async processControlRequest(request: CanUseToolControlRequest, signal: AbortSignal): Promise<PermissionResult | QuestionResult> {\n if (request.request.subtype === 'can_use_tool') {\n if (!this.canCallTool) {\n throw new Error('canCallTool callback is not provided.');\n }\n return this.canCallTool(request.request.tool_name, request.request.input, { signal });\n }\n if (request.request.subtype === 'can_answer_question') {\n if (!this.canAnswerQuestion) {\n throw new Error('canAnswerQuestion callback is not provided.');\n }\n const qReq = request as unknown as { request: { question: string } };\n return this.canAnswerQuestion(qReq.request.question, { signal });\n }\n throw new Error('Unsupported control request subtype: ' + request.request.subtype);\n }\n\n private cleanupControllers(): void {\n for (const [requestId, controller] of this.cancelControllers.entries()) {\n controller.abort();\n this.cancelControllers.delete(requestId);\n }\n }\n}\n\nexport function query(config: { prompt: QueryPrompt; options?: QueryOptions }): Query {\n const {\n prompt,\n options: {\n allowedTools = [],\n appendSystemPrompt,\n customSystemPrompt,\n cwd,\n disallowedTools = [],\n executable = 'node',\n executableArgs = [],\n maxTurns,\n mcpServers,\n pathToClaudeCodeExecutable = 'claude',\n permissionMode = 'default',\n continue: continueConversation,\n resume,\n model,\n fallbackModel,\n strictMcpConfig,\n canCallTool,\n canAnswerQuestion,\n settingsPath,\n env,\n abort,\n } = {},\n } = config;\n\n if (abort?.aborted) {\n throw new AbortError('Claude Code process aborted by user');\n }\n\n if (canCallTool && typeof prompt === 'string') {\n throw new Error('canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable.');\n }\n\n if (!process.env.CLAUDE_CODE_ENTRYPOINT) {\n process.env.CLAUDE_CODE_ENTRYPOINT = 'sdk-ts';\n }\n\n const args = buildClaudeArgs({\n allowedTools,\n appendSystemPrompt,\n customSystemPrompt,\n maxTurns,\n model,\n canCallTool,\n continue: continueConversation,\n resume,\n disallowedTools,\n mcpServers,\n strictMcpConfig,\n permissionMode,\n settingsPath,\n fallbackModel,\n });\n\n if (typeof prompt === 'string') {\n args.push('--print', prompt.trim());\n } else {\n args.push('--input-format', 'stream-json');\n }\n\n const isJsFile = pathToClaudeCodeExecutable.endsWith('.js') || pathToClaudeCodeExecutable.endsWith('.cjs');\n const isCommandOnly = pathToClaudeCodeExecutable === 'claude';\n if (!isCommandOnly && !existsSync(pathToClaudeCodeExecutable)) {\n throw new ReferenceError(`Claude Code executable not found at ${pathToClaudeCodeExecutable}`);\n }\n\n const spawnCommand = isJsFile ? executable : pathToClaudeCodeExecutable;\n const spawnArgs = isJsFile ? [...executableArgs, pathToClaudeCodeExecutable, ...args] : args;\n\n const spawnEnv = isCommandOnly ? { ...getCleanEnv(), ...env } : { ...process.env, ...env };\n\n const child = spawn(spawnCommand, spawnArgs, {\n cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n signal: abort,\n env: spawnEnv,\n shell: !isJsFile && process.platform === 'win32',\n windowsHide: true,\n }) as ChildProcessWithoutNullStreams;\n\n // Drain stderr to prevent buffer deadlock\n child.stderr.resume();\n\n let childStdin: Writable | null = null;\n if (typeof prompt === 'string') {\n child.stdin.end();\n } else {\n (async () => {\n try {\n for await (const msg of prompt) {\n if (abort?.aborted) break;\n const data = JSON.stringify(msg) + '\\n';\n if (!child.stdin.write(data)) {\n await new Promise<void>((resolve) => child.stdin.once('drain', resolve));\n }\n }\n } finally {\n child.stdin.end();\n }\n })();\n childStdin = child.stdin;\n }\n\n const cleanup = () => {\n if (!child.killed) child.kill('SIGTERM');\n };\n\n abort?.addEventListener('abort', cleanup);\n\n const processExitPromise = new Promise<void>((resolve) => {\n child.on('close', (code) => {\n if (abort?.aborted) {\n q.setError(new AbortError('Claude Code process aborted by user'));\n } else if (code !== 0 && code !== null) {\n q.setError(new Error(`Claude Code process exited with code ${code}`));\n } else {\n resolve();\n }\n });\n });\n\n const q = new Query(childStdin, child.stdout, processExitPromise, canCallTool, canAnswerQuestion);\n q.setChild(child);\n\n child.on('error', (error) => {\n if (abort?.aborted) {\n q.setError(new AbortError('Claude Code process aborted by user'));\n } else {\n q.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));\n }\n });\n\n processExitPromise.finally(() => {\n cleanup();\n abort?.removeEventListener('abort', cleanup);\n });\n\n return q;\n}\n","export class Stream<T> implements AsyncIterableIterator<T> {\n private queue: T[] = [];\n private readResolve?: (value: IteratorResult<T>) => void;\n private readReject?: (error: Error) => void;\n private isDone = false;\n private hasError?: Error;\n private started = false;\n\n constructor(private returned?: () => void) {}\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n if (this.started) {\n throw new Error('Stream can only be iterated once');\n }\n this.started = true;\n return this;\n }\n\n async next(): Promise<IteratorResult<T>> {\n if (this.queue.length > 0) {\n return Promise.resolve({ done: false, value: this.queue.shift()! });\n }\n if (this.isDone) {\n return Promise.resolve({ done: true, value: undefined });\n }\n if (this.hasError) {\n return Promise.reject(this.hasError);\n }\n return new Promise((resolve, reject) => {\n this.readResolve = resolve;\n this.readReject = reject;\n });\n }\n\n enqueue(value: T): void {\n if (this.isDone || this.hasError) return;\n if (this.readResolve) {\n const resolve = this.readResolve;\n this.readResolve = undefined;\n this.readReject = undefined;\n resolve({ done: false, value });\n } else {\n this.queue.push(value);\n }\n }\n\n done(): void {\n if (this.isDone || this.hasError) return;\n this.isDone = true;\n if (this.readResolve) {\n const resolve = this.readResolve;\n this.readResolve = undefined;\n this.readReject = undefined;\n resolve({ done: true, value: undefined });\n }\n }\n\n error(error: Error): void {\n if (this.isDone || this.hasError) return;\n this.hasError = error;\n if (this.readReject) {\n const reject = this.readReject;\n this.readResolve = undefined;\n this.readReject = undefined;\n reject(error);\n }\n }\n\n async return(): Promise<IteratorResult<T>> {\n this.isDone = true;\n if (this.returned) {\n this.returned();\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n}\n","export interface SDKMessage {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface SDKUserMessage extends SDKMessage {\n type: 'user';\n parent_tool_use_id?: string;\n message: {\n role: 'user';\n content: string | Array<{\n type: string;\n text?: string;\n tool_use_id?: string;\n content?: unknown;\n [key: string]: unknown;\n }>;\n };\n}\n\nexport interface SDKAssistantMessage extends SDKMessage {\n type: 'assistant';\n parent_tool_use_id?: string;\n message: {\n role: 'assistant';\n content: Array<{\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n thinking?: string;\n [key: string]: unknown;\n }>;\n };\n}\n\nexport interface SDKSystemMessage extends SDKMessage {\n type: 'system';\n subtype: string;\n session_id?: string;\n model?: string;\n cwd?: string;\n tools?: string[];\n slash_commands?: string[];\n}\n\nexport interface SDKResultMessage extends SDKMessage {\n type: 'result';\n subtype: 'success' | 'error_max_turns' | 'error_during_execution';\n result?: string;\n num_turns: number;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n total_cost_usd: number;\n duration_ms: number;\n duration_api_ms: number;\n is_error: boolean;\n session_id: string;\n}\n\nexport interface SDKControlResponse extends SDKMessage {\n type: 'control_response';\n response: {\n request_id: string;\n subtype: 'success' | 'error';\n error?: string;\n };\n}\n\nexport interface SDKLog extends SDKMessage {\n type: 'log';\n log: {\n level: 'debug' | 'info' | 'warn' | 'error';\n message: string;\n };\n}\n\nexport interface ControlRequest {\n subtype: string;\n}\n\nexport interface CanUseToolRequest extends ControlRequest {\n subtype: 'can_use_tool';\n tool_name: string;\n input: unknown;\n}\n\nexport interface CanUseToolControlRequest {\n type: 'control_request';\n request_id: string;\n request: CanUseToolRequest;\n}\n\nexport interface CanAnswerQuestionRequest extends ControlRequest {\n subtype: 'can_answer_question';\n question: string;\n}\n\nexport interface CanAnswerQuestionControlRequest {\n type: 'control_request';\n request_id: string;\n request: CanAnswerQuestionRequest;\n}\n\nexport interface CanUseToolControlResponse {\n type: 'control_response';\n response: {\n subtype: 'success' | 'error';\n request_id: string;\n response?: PermissionResult | QuestionResult;\n error?: string;\n };\n}\n\nexport interface ControlCancelRequest {\n type: 'control_cancel_request';\n request_id: string;\n}\n\nexport interface SDKControlRequest {\n request_id: string;\n type: 'control_request';\n request: ControlRequest;\n}\n\nexport type PermissionResult =\n | { behavior: 'allow'; updatedInput: Record<string, unknown> }\n | { behavior: 'deny'; message: string };\n\n/**\n * Result of a question answered by user\n */\nexport type QuestionResult =\n | { action: 'answer'; answer: string }\n | { action: 'skip' }\n | { action: 'deny'; message?: string };\n\nexport interface CanCallToolCallback {\n (toolName: string, input: unknown, options: { signal: AbortSignal }): Promise<PermissionResult>;\n}\n\nexport interface CanAnswerQuestionCallback {\n (question: string, options: { signal: AbortSignal }): Promise<QuestionResult>;\n}\n\nexport interface QueryOptions {\n abort?: AbortSignal;\n allowedTools?: string[];\n appendSystemPrompt?: string;\n customSystemPrompt?: string;\n cwd?: string;\n disallowedTools?: string[];\n executable?: string;\n executableArgs?: string[];\n maxTurns?: number;\n mcpServers?: Record<string, unknown>;\n pathToClaudeCodeExecutable?: string;\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n continue?: boolean;\n resume?: string;\n model?: string;\n fallbackModel?: string;\n strictMcpConfig?: boolean;\n canCallTool?: CanCallToolCallback;\n canAnswerQuestion?: CanAnswerQuestionCallback;\n settingsPath?: string;\n /** Disable hooks, LSP, plugin sync, etc. for cleaner remote mode */\n bare?: boolean;\n env?: Record<string, string | undefined>;\n}\n\nexport type QueryPrompt = string | AsyncIterable<SDKMessage>;\n\nexport class AbortError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AbortError';\n }\n}\n","/** Claude Code hook event names */\nexport type ClaudeHookEventType =\n | 'SessionStart'\n | 'SessionEnd'\n | 'PreToolUse'\n | 'PermissionRequest'\n | 'PostToolUse'\n | 'PostToolUseFailure'\n | 'Stop';\n\n/** Valid Claude hook event types */\nconst VALID_CLAUDE_EVENTS: ClaudeHookEventType[] = [\n 'SessionStart',\n 'SessionEnd',\n 'PreToolUse',\n 'PermissionRequest',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'Stop',\n];\n\n/**\n * Check if a string is a valid Claude hook event type\n */\nexport function isClaudeHookEventType(eventType: string): eventType is ClaudeHookEventType {\n return VALID_CLAUDE_EVENTS.includes(eventType as ClaudeHookEventType);\n}\n","import { randomUUID } from 'crypto';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { Logger } from 'pino';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport type { InteractionRequest } from '../../../core/interaction/types.js';\nimport { CodexAppServerClient, type ApprovalHandler } from './codexAppServerClient.js';\nimport type { ApprovalPolicy, ReviewDecision } from './codexAppServerTypes.js';\nimport type { AgentCommand, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport type { MergedTool } from '../../../core/agent/TurnAggregator.js';\n\ninterface CodexTransportState extends TransportState {\n client: CodexAppServerClient;\n threadId: string;\n chatId: string;\n channel: string;\n cwd?: string;\n}\n\nexport class CodexAppAgentAdapter extends BaseAgentAdapter {\n readonly agentType = 'codex' as const;\n readonly transportType = 'stdio' as const;\n readonly version = '1.0.0';\n private token: string;\n private turnInProgress = new Set<string>();\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n private defaultWorkDir?: string;\n private defaultModel?: string;\n private defaultApprovalPolicy?: ApprovalPolicy;\n\n constructor(options: {\n bus: EventBus;\n logger: Logger;\n bridge: AgentBridgePort;\n token: string;\n command?: string[];\n cwd?: string;\n env?: Record<string, string>;\n defaultWorkDir?: string;\n defaultModel?: string;\n defaultApprovalPolicy?: ApprovalPolicy;\n }) {\n super(options);\n this.token = options.token;\n this.command = options.command?.length ? options.command : ['codex', 'app-server', '--listen', 'stdio://'];\n this.spawnCwd = options.cwd;\n this.envExtra = options.env ?? {};\n this.defaultWorkDir = options.defaultWorkDir;\n this.defaultModel = options.defaultModel;\n this.defaultApprovalPolicy = options.defaultApprovalPolicy;\n }\n\n async initialize(): Promise<void> {\n this.logger.info('Codex adapter initializing');\n try {\n const { execSync } = await import('child_process');\n execSync('codex --version', { encoding: 'utf8', windowsHide: true });\n this.logger.info('Codex CLI detected');\n } catch (err) {\n this.logger.warn('Codex CLI not found. Install with: npm install -g @openai/codex');\n throw err;\n }\n\n await super.initialize();\n }\n\n async createTransportState(opts: CreateSessionOptions): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `codex-${randomUUID().slice(0, 8)}`;\n const chatId = opts.chatId ?? sessionId;\n const channel = opts.channel ?? 'broadcast';\n const cwd = opts.cwd || this.defaultWorkDir || process.cwd();\n this.logger.info({ sessionId, chatId, cwd, optsCwd: opts.cwd, defaultWorkDir: this.defaultWorkDir }, 'Creating Codex transport state');\n\n const client = new CodexAppServerClient({ logger: this.logger, command: this.command, cwd: this.spawnCwd, env: this.envExtra });\n await client.connect();\n\n const approvalPolicy = (opts.agentOptions?.approvalPolicy as ApprovalPolicy)\n ?? this.defaultApprovalPolicy\n ?? undefined;\n\n const { threadId } = await client.startThread({\n cwd,\n model: opts.model ?? this.defaultModel,\n approvalPolicy,\n });\n\n const state: CodexTransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n client,\n threadId,\n chatId,\n channel,\n cwd,\n };\n\n client.setEventHandler((msg) => this.handleCodexEvent(msg, sessionId, state));\n client.setApprovalHandler((params) => this.handleApproval(params, sessionId));\n\n this.transports.set(sessionId, state);\n\n this.logger.info({ sessionId, threadId }, 'Codex transport state created');\n\n return state;\n }\n\n async closeTransportState(state: TransportState, reason = 'close'): Promise<void> {\n const codexState = state as CodexTransportState;\n try {\n await codexState.client.disconnect();\n } catch (err) {\n this.logger.warn({ sessionId: state.sessionId, error: err }, 'Error disconnecting Codex client during closeTransportState');\n }\n this.emitEvent(EventNormalizer.sessionEnd(state.sessionId, this.agentType, this.transportType, reason));\n this.transports.delete(state.sessionId);\n }\n\n async sendCommand(state: TransportState, command: AgentCommand): Promise<void> {\n const codexState = state as CodexTransportState;\n const { client, chatId, channel } = codexState;\n const sessionId = state.sessionId;\n\n this.logger.info({ sessionId, commandType: command.type }, 'Handling command');\n\n switch (command.type) {\n case 'user:message': {\n if (this.turnInProgress.has(sessionId)) {\n this.logger.warn({ sessionId }, 'Concurrent turn rejected');\n this.bus.publishOutbound({\n channel,\n chatId,\n text: 'Codex is still processing the previous message. Please wait.',\n });\n return;\n }\n this.turnInProgress.add(sessionId);\n this.emitEvent(EventNormalizer.turnStarted(sessionId, this.agentType, this.transportType));\n try {\n this.logger.debug({ sessionId, contentLength: command.content.length }, 'Sending turn to Codex');\n await client.sendTurnAndWait(command.content, {\n cwd: codexState.cwd ?? process.cwd(),\n });\n this.logger.info({ sessionId }, 'Turn completed');\n } finally {\n this.turnInProgress.delete(sessionId);\n }\n break;\n }\n case 'permission:response': {\n this.logger.warn('Manual permission:response via sendCommand not implemented for Codex v1');\n break;\n }\n case 'interrupt': {\n this.logger.info({ sessionId }, 'Interrupting turn');\n await client.interruptTurn();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n await this.closeTransportState(codexState);\n break;\n }\n }\n }\n\n private async handleCodexEvent(msg: { type: string } & Record<string, unknown>, sessionId: string, state: CodexTransportState): Promise<void> {\n const timestamp = new Date().toISOString();\n this.logger.info({ sessionId, eventType: msg.type }, 'Codex event received from client');\n\n switch (msg.type) {\n case 'agent_message': {\n const content = typeof msg.message === 'string' ? msg.message : '';\n this.logger.debug({ sessionId, contentPreview: content.slice(0, 80) }, 'Publishing agent_message');\n this.emitEvent(EventNormalizer.turnFinished(sessionId, this.agentType, this.transportType, {\n lastAssistantMessage: content,\n thinking: '',\n tools: [],\n }));\n break;\n }\n\n case 'exec_command_begin':\n case 'patch_apply_begin': {\n // Codex tool begin events are tracked internally; we emit on end\n break;\n }\n\n case 'exec_command_end':\n case 'patch_apply_end': {\n const toolName = msg.type === 'exec_command_end' ? 'codex_exec_command' : 'codex_patch_apply';\n this.logger.debug({ sessionId, toolName, eventType: msg.type }, 'Publishing tool:executed');\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, {\n toolCallId: `${sessionId}-${toolName}`,\n toolName,\n summary: `${toolName}: ${typeof msg.output === 'string' ? msg.output.slice(0, 100) : ''}`,\n toolInput: msg.command ? { command: msg.command } : msg.changes ? { changes: msg.changes } : {},\n output: typeof msg.output === 'string' ? msg.output : undefined,\n isTimeout: false,\n }));\n break;\n }\n\n case 'task_complete': {\n this.logger.info({ sessionId }, 'Task complete');\n // Note: session remains active for follow-up messages.\n // session:end is only emitted by closeTransportState (/clear, /stop, shutdown).\n break;\n }\n\n case 'turn_aborted': {\n const reason = (msg.reason as string | undefined) ?? 'aborted';\n this.logger.info({ sessionId, reason }, 'Turn aborted');\n // Note: session remains active for follow-up messages.\n break;\n }\n\n case 'tool:post':\n case 'tool:failure': {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Forwarding tool event');\n const toolCallId = typeof msg.toolCallId === 'string' ? msg.toolCallId : `${sessionId}-tool`;\n const toolName = typeof msg.toolName === 'string' ? msg.toolName : 'unknown';\n const tool: MergedTool = {\n toolCallId,\n toolName,\n summary: typeof msg.summary === 'string' ? msg.summary : `${toolName}: tool event`,\n toolInput: (msg.toolInput as Record<string, unknown>) || {},\n output: typeof msg.output === 'string' ? msg.output : undefined,\n isTimeout: false,\n };\n if (msg.type === 'tool:failure') {\n this.emitEvent(EventNormalizer.toolFailure(sessionId, this.agentType, this.transportType, tool, typeof msg.error === 'string' ? msg.error : undefined));\n } else {\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, tool));\n }\n break;\n }\n\n default: {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Unhandled Codex event type');\n break;\n }\n }\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0], sessionId: string): Promise<ReviewDecision> {\n const state = this.transports.get(sessionId) as CodexTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId, callId: params.callId }, 'Approval request but session not found, auto-denying');\n return 'denied';\n }\n\n const toolNameMap: Record<string, string> = {\n exec: 'codex_exec_command',\n patch: 'codex_patch_apply',\n mcp: 'codex_mcp_elicitation',\n };\n\n const toolName = toolNameMap[params.type] || params.type;\n this.logger.info({ sessionId, callId: params.callId, toolName }, 'Codex approval request');\n\n const interactionRequest: InteractionRequest = {\n requestId: params.callId,\n sessionId,\n type: 'permission',\n toolName,\n toolInput: params.command ? { command: params.command } :\n params.fileChanges ? { fileChanges: params.fileChanges } :\n params.input ? { input: params.input } : {},\n timestamp: Date.now(),\n };\n\n try {\n const response = await this.bridge.evaluateInteraction(interactionRequest);\n const decision: ReviewDecision = response.action === 'allow' ? 'approved' : 'denied';\n this.logger.info({ sessionId, callId: params.callId, toolName, decision }, 'Codex approval resolved');\n return decision;\n } catch (err) {\n this.logger.error({ error: err, sessionId, callId: params.callId }, 'Codex approval handler error');\n return 'denied';\n }\n }\n}\n","/**\n * Codex App Server Client — drives Codex via the v2 JSON-RPC protocol\n * (`codex app-server`), replacing the legacy MCP-based CodexMcpClient.\n *\n * Protocol: JSON-RPC 2.0 over stdio (newline-delimited JSON).\n * Adapted from happy project for handsoff.\n */\n\nimport { spawn, type ChildProcess, execFileSync } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport type {\n InitializeParams,\n NewConversationParams,\n NewConversationResponse,\n ResumeConversationParams,\n ResumeConversationResponse,\n InterruptConversationParams,\n ReviewDecision,\n EventMsg,\n JsonRpcRequest,\n JsonRpcResponse,\n ApprovalPolicy,\n SandboxMode,\n InputItem,\n ReasoningEffort,\n McpServerElicitationRequestResponse,\n} from './codexAppServerTypes.js';\n\ntype PendingRequest = {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n method: string;\n epoch: number;\n};\n\ntype LegacyPatchChanges = Record<string, Record<string, unknown>>;\n\nexport type ApprovalHandler = (params: {\n type: 'exec' | 'patch' | 'mcp';\n callId: string;\n command?: string[];\n cwd?: string;\n fileChanges?: Record<string, unknown>;\n reason?: string | null;\n toolName?: string;\n input?: unknown;\n serverName?: string;\n message?: string;\n}) => Promise<ReviewDecision>;\n\ntype LoggerLike = {\n debug: (msg: string, ...args: unknown[]) => void;\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n};\n\nfunction isAppServerAvailable(command = 'codex'): boolean {\n try {\n execFileSync(command, ['--version'], { encoding: 'utf8', windowsHide: true });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalizeRawFileChangeList(changes: unknown): LegacyPatchChanges | undefined {\n if (!Array.isArray(changes)) {\n return undefined;\n }\n\n const normalized: LegacyPatchChanges = {};\n for (const change of changes) {\n if (!change || typeof change !== 'object' || Array.isArray(change)) {\n continue;\n }\n\n const path = typeof change.path === 'string' ? change.path : null;\n if (!path) {\n continue;\n }\n\n const entry: Record<string, unknown> = {};\n if (typeof change.diff === 'string') {\n entry.diff = change.diff;\n }\n if (change.kind && typeof change.kind === 'object' && !Array.isArray(change.kind)) {\n entry.kind = change.kind;\n }\n\n normalized[path] = entry;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\nexport class CodexAppServerClient {\n private process: ChildProcess | null = null;\n private readline: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private processEpoch = 0;\n private connected = false;\n private logger: LoggerLike | undefined;\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n\n // Session state\n private _threadId: string | null = null;\n private _turnId: string | null = null;\n private threadDefaults: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n } | null = null;\n\n // Turn completion tracking for the currently active sendTurnAndWait call.\n private pendingTurnCompletion: {\n resolve: (aborted: boolean) => void;\n started: boolean;\n turnId: string | null;\n } | null = null;\n\n // Tracks in-flight interruptTurn() RPCs so sendTurnAndWait can wait for them\n private pendingInterrupt: Promise<void> | null = null;\n private notificationProtocol: 'unknown' | 'legacy' | 'raw' = 'unknown';\n private completedTurnIds = new Set<string>();\n private rawFileChangesByItemId = new Map<string, LegacyPatchChanges>();\n\n // Handlers set by the consumer\n private eventHandler: ((msg: EventMsg) => void) | null = null;\n private approvalHandler: ApprovalHandler | null = null;\n\n constructor(options?: { logger?: LoggerLike; command?: string[]; cwd?: string; env?: Record<string, string> }) {\n this.logger = options?.logger;\n this.command = options?.command?.length ? options.command : ['codex', 'app-server', '--listen', 'stdio://'];\n this.spawnCwd = options?.cwd;\n this.envExtra = options?.env ?? {};\n }\n\n get threadId(): string | null {\n return this._threadId;\n }\n\n get turnId(): string | null {\n return this._turnId;\n }\n\n setEventHandler(handler: (msg: EventMsg) => void): void {\n this.eventHandler = handler;\n }\n\n setApprovalHandler(handler: ApprovalHandler): void {\n this.approvalHandler = handler;\n }\n\n private extractTurnId(params: any): string | null {\n const turnId = params?.turn?.id ?? params?.turnId ?? params?.turn_id ?? null;\n return typeof turnId === 'string' && turnId.length > 0 ? turnId : null;\n }\n\n private extractTurnStatus(params: any): string | null {\n const status = params?.turn?.status ?? params?.status ?? null;\n return typeof status === 'string' && status.length > 0 ? status : null;\n }\n\n private shouldHandleRawNotification(method: string): boolean {\n const isRawNotification = method === 'thread/started'\n || method === 'turn/started'\n || method === 'turn/completed'\n || method === 'thread/status/changed'\n || method === 'thread/tokenUsage/updated'\n || method.startsWith('item/');\n\n if (!isRawNotification) {\n return false;\n }\n\n if (this.notificationProtocol === 'legacy') {\n return false;\n }\n\n if (this.notificationProtocol === 'unknown') {\n this.notificationProtocol = 'raw';\n }\n\n return true;\n }\n\n private emitRawTurnCompletion(\n turnId: string | null,\n status: string | null,\n error: unknown,\n source: string,\n ): void {\n const aborted = status === 'cancelled' || status === 'canceled' || status === 'aborted' || status === 'interrupted';\n\n this.tryResolvePendingTurn(aborted, turnId, source);\n this._turnId = null;\n\n if (turnId && this.completedTurnIds.has(turnId)) {\n return;\n }\n if (turnId) {\n this.completedTurnIds.add(turnId);\n }\n\n if (aborted) {\n this.eventHandler?.({\n type: 'turn_aborted',\n ...(turnId ? { turn_id: turnId } : {}),\n ...(status ? { status } : {}),\n ...(error !== undefined && error !== null ? { error } : {}),\n });\n return;\n }\n\n this.eventHandler?.({\n type: 'task_complete',\n ...(turnId ? { turn_id: turnId } : {}),\n ...(status ? { status } : {}),\n ...(error !== undefined && error !== null ? { error } : {}),\n });\n }\n\n private handleRawNotification(method: string, params: any): boolean {\n if (!this.shouldHandleRawNotification(method)) {\n return false;\n }\n\n if (method === 'turn/started') {\n const turnId = this.extractTurnId(params);\n if (turnId) {\n this._turnId = turnId;\n }\n this.markPendingTurnStarted(turnId);\n this.eventHandler?.({\n type: 'task_started',\n ...(turnId ? { turn_id: turnId } : {}),\n });\n return true;\n }\n\n if (method === 'turn/completed') {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n this.extractTurnStatus(params),\n params?.turn?.error ?? params?.error,\n method,\n );\n return true;\n }\n\n if (method === 'thread/status/changed') {\n const statusType = params?.status?.type;\n if (statusType === 'idle' && this.pendingTurnCompletion?.started) {\n this.emitRawTurnCompletion(this._turnId, 'completed', null, method);\n }\n return true;\n }\n\n if (method === 'thread/tokenUsage/updated') {\n const tokenUsage = params?.tokenUsage;\n if (tokenUsage && typeof tokenUsage === 'object') {\n this.eventHandler?.({\n type: 'token_count',\n ...tokenUsage,\n });\n }\n return true;\n }\n\n const item = params?.item;\n if (!item || typeof item !== 'object') {\n return method.startsWith('item/');\n }\n\n if (method === 'item/started' && item.type === 'commandExecution') {\n const callId = typeof item.id === 'string' ? item.id : '';\n this.eventHandler?.({\n type: 'exec_command_begin',\n call_id: callId,\n callId,\n command: item.command,\n cwd: item.cwd,\n description: item.command,\n });\n return true;\n }\n\n if (method === 'item/completed' && item.type === 'commandExecution') {\n const callId = typeof item.id === 'string' ? item.id : '';\n this.eventHandler?.({\n type: 'exec_command_end',\n call_id: callId,\n callId,\n output: item.aggregatedOutput ?? '',\n exit_code: item.exitCode ?? null,\n duration_ms: item.durationMs ?? null,\n status: item.status,\n cwd: item.cwd,\n command: item.command,\n });\n return true;\n }\n\n if (item.type === 'fileChange') {\n const callId = typeof item.id === 'string' ? item.id : '';\n const changes = normalizeRawFileChangeList(item.changes);\n\n if (callId && changes) {\n this.rawFileChangesByItemId.set(callId, changes);\n }\n\n if (method === 'item/started') {\n this.eventHandler?.({\n type: 'patch_apply_begin',\n call_id: callId,\n callId,\n changes: changes ?? {},\n });\n return true;\n }\n\n if (method === 'item/completed') {\n this.eventHandler?.({\n type: 'patch_apply_end',\n call_id: callId,\n callId,\n status: item.status,\n });\n\n if (callId && (item.status === 'completed' || item.status === 'failed' || item.status === 'declined')) {\n this.rawFileChangesByItemId.delete(callId);\n }\n return true;\n }\n }\n\n if (method === 'item/completed' && item.type === 'agentMessage') {\n const text = typeof item.text === 'string' ? item.text : '';\n if (text.length > 0) {\n this.eventHandler?.({\n type: 'agent_message',\n message: text,\n item_id: item.id,\n phase: item.phase,\n });\n }\n\n if (item.phase === 'final_answer' && this.pendingTurnCompletion?.started) {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n 'completed',\n null,\n `${method}:final_answer`,\n );\n }\n return true;\n }\n\n return method.startsWith('item/');\n }\n\n // --- Lifecycle ---\n\n async connect(): Promise<void> {\n if (this.connected) return;\n\n const cmd = this.command[0];\n const args = this.command.slice(1);\n\n if (!isAppServerAvailable(cmd)) {\n throw new Error(\n 'Codex CLI is not installed\\n\\n' +\n 'Please install Codex CLI using:\\n npm install -g @openai/codex\\n'\n );\n }\n\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (typeof value === 'string') env[key] = value;\n }\n for (const [key, value] of Object.entries(this.envExtra)) {\n env[key] = value;\n }\n const filter = 'codex_core::rollout::list=off';\n if (!env.RUST_LOG) {\n env.RUST_LOG = filter;\n } else if (!env.RUST_LOG.includes('codex_core::rollout::list=')) {\n env.RUST_LOG += `,${filter}`;\n }\n\n this.logger?.debug(`Spawning: ${cmd} ${args.join(' ')}`);\n\n const epoch = ++this.processEpoch;\n const spawnOpts: import('node:child_process').SpawnOptions = {\n stdio: ['pipe', 'pipe', 'pipe'],\n env,\n windowsHide: true,\n };\n if (this.spawnCwd) {\n spawnOpts.cwd = this.spawnCwd;\n }\n const proc = spawn(cmd, args, spawnOpts);\n this.process = proc;\n\n proc.on('error', (err) => {\n this.logger?.debug('Process error:', err);\n });\n\n proc.on('exit', (code, signal) => {\n this.logger?.debug(`Process exited: code=${code} signal=${signal}`);\n if (this.process !== proc || this.processEpoch !== epoch) {\n this.logger?.debug('Ignoring stale process exit');\n return;\n }\n this.connected = false;\n for (const [id, req] of this.pending) {\n if (req.epoch !== epoch) continue;\n req.reject(new Error(`Codex process exited (code=${code}) while waiting for ${req.method}`));\n this.pending.delete(id);\n }\n this.resolvePendingTurn(true);\n });\n\n proc.stderr?.on('data', (chunk: Buffer) => {\n if (this.process !== proc || this.processEpoch !== epoch) return;\n const text = chunk.toString().trim();\n if (text) this.logger?.debug(`[CodexAppServer:stderr] ${text}`);\n });\n\n this.readline = createInterface({ input: proc.stdout! });\n this.readline.on('line', (line) => {\n if (this.process !== proc || this.processEpoch !== epoch) return;\n this.handleLine(line, epoch);\n });\n\n const initParams: InitializeParams = {\n clientInfo: {\n name: 'handsoff-codex',\n title: 'Handsoff Codex Client',\n version: '1.0.0',\n },\n capabilities: {\n experimentalApi: true,\n },\n };\n await this.request('initialize', initParams);\n this.notify('initialized');\n this.connected = true;\n this.logger?.debug('Connected and initialized');\n }\n\n private async disconnectInternal(opts?: { preserveThreadState?: boolean }): Promise<void> {\n if (!this.connected && !this.process) return;\n\n const proc = this.process;\n const pid = proc?.pid;\n const epoch = this.processEpoch;\n this.logger?.debug(`Disconnecting; pid=${pid ?? 'none'}`);\n\n this.readline?.close();\n this.readline = null;\n\n try {\n proc?.stdin?.end();\n proc?.kill('SIGTERM');\n } catch { /* ignore */ }\n\n if (pid) {\n const killTimer = setTimeout(() => {\n try {\n process.kill(pid, 0);\n process.kill(pid, 'SIGKILL');\n } catch { /* already dead */ }\n }, 2000);\n killTimer.unref();\n }\n\n this.process = null;\n this.connected = false;\n this._turnId = null;\n this.notificationProtocol = 'unknown';\n this.completedTurnIds.clear();\n if (!opts?.preserveThreadState) {\n this._threadId = null;\n this.threadDefaults = null;\n }\n\n for (const [id, req] of this.pending) {\n if (req.epoch !== epoch) continue;\n req.reject(new Error(`Codex process disconnected while waiting for ${req.method}`));\n this.pending.delete(id);\n }\n\n this.resolvePendingTurn(true);\n this.logger?.debug('Disconnected');\n }\n\n async disconnect(): Promise<void> {\n await this.disconnectInternal();\n }\n\n private buildThreadConfig(mcpServers?: Record<string, unknown>): Record<string, unknown> | null {\n return mcpServers ? { mcp_servers: mcpServers } : null;\n }\n\n private rememberThreadDefaults(opts: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): void {\n this.threadDefaults = {\n model: opts.model,\n cwd: opts.cwd,\n approvalPolicy: opts.approvalPolicy,\n sandbox: opts.sandbox,\n mcpServers: opts.mcpServers,\n };\n }\n\n // --- Thread management ---\n\n async startThread(opts: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): Promise<{ threadId: string; model: string }> {\n const params: NewConversationParams = {\n model: opts.model ?? null,\n modelProvider: null,\n profile: null,\n cwd: opts.cwd ?? process.cwd(),\n approvalPolicy: opts.approvalPolicy ?? null,\n sandbox: opts.sandbox ?? null,\n config: this.buildThreadConfig(opts.mcpServers),\n baseInstructions: null,\n developerInstructions: null,\n compactPrompt: null,\n includeApplyPatchTool: null,\n experimentalRawEvents: false,\n persistExtendedHistory: true,\n };\n\n const result = await this.request('thread/start', params) as NewConversationResponse;\n this._threadId = result.thread.id;\n this._turnId = null;\n this.rememberThreadDefaults(opts);\n this.logger?.debug(`Thread started: ${this._threadId}`);\n return { threadId: result.thread.id, model: result.model };\n }\n\n async resumeThread(opts?: {\n threadId?: string;\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): Promise<{ threadId: string; model: string }> {\n const threadId = opts?.threadId ?? this._threadId;\n if (!threadId) {\n throw new Error('No thread available to resume.');\n }\n\n const defaults = this.threadDefaults ?? {};\n const params: ResumeConversationParams = {\n threadId,\n model: opts?.model ?? defaults.model ?? null,\n modelProvider: null,\n cwd: opts?.cwd ?? defaults.cwd ?? process.cwd(),\n approvalPolicy: opts?.approvalPolicy ?? defaults.approvalPolicy ?? null,\n sandbox: opts?.sandbox ?? defaults.sandbox ?? null,\n config: this.buildThreadConfig(opts?.mcpServers ?? defaults.mcpServers),\n baseInstructions: null,\n developerInstructions: null,\n persistExtendedHistory: true,\n };\n\n const result = await this.request('thread/resume', params) as ResumeConversationResponse;\n this._threadId = result.thread.id;\n this._turnId = null;\n this.rememberThreadDefaults({\n model: opts?.model ?? defaults.model,\n cwd: opts?.cwd ?? defaults.cwd,\n approvalPolicy: opts?.approvalPolicy ?? defaults.approvalPolicy,\n sandbox: opts?.sandbox ?? defaults.sandbox,\n mcpServers: opts?.mcpServers ?? defaults.mcpServers,\n });\n this.logger?.debug(`Thread resumed: ${this._threadId}`);\n return { threadId: result.thread.id, model: result.model };\n }\n\n async reconnectAndResumeThread(): Promise<boolean> {\n const threadId = this._threadId;\n await this.disconnectInternal({ preserveThreadState: !!threadId });\n await this.connect();\n\n if (!threadId) {\n return false;\n }\n\n try {\n await this.resumeThread({ threadId });\n return true;\n } catch (error) {\n this.logger?.warn('Failed to resume thread after reconnect', error);\n this._threadId = null;\n this.threadDefaults = null;\n return false;\n }\n }\n\n // --- Turn management ---\n\n private static readonly ABORT_GRACE_MS = 3_000;\n\n private hasPendingTurnCompletion(): boolean {\n return this.pendingTurnCompletion !== null;\n }\n\n private resolvePendingTurn(aborted: boolean): void {\n if (!this.pendingTurnCompletion) return;\n this.pendingTurnCompletion.resolve(aborted);\n this.pendingTurnCompletion = null;\n }\n\n private markPendingTurnStarted(turnId?: string | null): void {\n if (!this.pendingTurnCompletion) return;\n this.pendingTurnCompletion.started = true;\n if (turnId) {\n this.pendingTurnCompletion.turnId = turnId;\n }\n }\n\n private tryResolvePendingTurn(aborted: boolean, turnId: string | null, source: string): void {\n const pending = this.pendingTurnCompletion;\n if (!pending) return;\n\n if (!pending.started) {\n this.logger?.debug(`Ignoring ${source} before task_started`);\n return;\n }\n\n if (pending.turnId && turnId && pending.turnId !== turnId) {\n this.logger?.debug(\n `Ignoring ${source} for turn ${turnId}; awaiting ${pending.turnId}`,\n );\n return;\n }\n\n this.resolvePendingTurn(aborted);\n }\n\n private async waitForTurnCompletion(timeoutMs: number): Promise<boolean> {\n if (!this.hasPendingTurnCompletion()) {\n return true;\n }\n\n const deadline = Date.now() + Math.max(0, timeoutMs);\n while (this.hasPendingTurnCompletion()) {\n if (Date.now() >= deadline) {\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n return true;\n }\n\n async abortTurnWithFallback(opts?: {\n gracePeriodMs?: number;\n forceRestartOnTimeout?: boolean;\n }): Promise<{ hadActiveTurn: boolean; aborted: boolean; forcedRestart: boolean; resumedThread: boolean }> {\n const hadActiveTurn = this.hasPendingTurnCompletion();\n\n if (!hadActiveTurn) {\n return { hadActiveTurn: false, aborted: false, forcedRestart: false, resumedThread: false };\n }\n\n await this.interruptTurn();\n\n const gracePeriodMs = opts?.gracePeriodMs ?? CodexAppServerClient.ABORT_GRACE_MS;\n const settled = await this.waitForTurnCompletion(gracePeriodMs);\n if (settled) {\n return { hadActiveTurn: true, aborted: true, forcedRestart: false, resumedThread: false };\n }\n\n const shouldForceRestart = opts?.forceRestartOnTimeout ?? true;\n if (!shouldForceRestart) {\n return { hadActiveTurn: true, aborted: false, forcedRestart: false, resumedThread: false };\n }\n\n this.logger?.warn(`interrupt did not settle turn in ${gracePeriodMs}ms; force-restarting app-server`);\n const pendingTurnId = this.pendingTurnCompletion?.turnId ?? this._turnId;\n if (this.pendingTurnCompletion?.started) {\n this.eventHandler?.({\n type: 'turn_aborted',\n reason: 'interrupted',\n ...(pendingTurnId ? { turn_id: pendingTurnId } : {}),\n forced_restart: true,\n });\n }\n const resumedThread = await this.reconnectAndResumeThread();\n return { hadActiveTurn: true, aborted: true, forcedRestart: true, resumedThread };\n }\n\n async sendTurn(prompt: string, opts?: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n effort?: ReasoningEffort;\n }): Promise<void> {\n if (!this._threadId) {\n throw new Error('No active thread. Call startThread first.');\n }\n\n const input: InputItem[] = [\n { type: 'text', text: prompt },\n ];\n\n const params: Record<string, unknown> = {\n threadId: this._threadId,\n input,\n };\n if (opts?.cwd) params.cwd = opts.cwd;\n if (opts?.approvalPolicy) params.approvalPolicy = opts.approvalPolicy;\n if (opts?.model) params.model = opts.model;\n if (opts?.effort) params.effort = opts.effort;\n\n if (opts?.sandbox) {\n switch (opts.sandbox) {\n case 'workspace-write':\n params.sandboxPolicy = { type: 'workspaceWrite' };\n break;\n case 'danger-full-access':\n params.sandboxPolicy = { type: 'dangerFullAccess' };\n break;\n case 'read-only':\n params.sandboxPolicy = { type: 'readOnly' };\n break;\n }\n }\n\n const result = await this.request('turn/start', params) as { turn?: { id?: string | null } };\n const turnId = result?.turn?.id;\n if (typeof turnId === 'string' && turnId.length > 0) {\n this._turnId = turnId;\n if (this.pendingTurnCompletion) {\n this.pendingTurnCompletion.turnId = turnId;\n }\n }\n }\n\n private static readonly TURN_TIMEOUT_MS = 10 * 60 * 1000;\n\n async sendTurnAndWait(prompt: string, opts?: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n effort?: ReasoningEffort;\n turnTimeoutMs?: number;\n }): Promise<{ aborted: boolean }> {\n if (this.pendingInterrupt) {\n await this.pendingInterrupt;\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n\n const timeoutMs = opts?.turnTimeoutMs ?? CodexAppServerClient.TURN_TIMEOUT_MS;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const completion = new Promise<boolean>((resolve) => {\n this.pendingTurnCompletion = {\n resolve,\n started: false,\n turnId: null,\n };\n\n timer = setTimeout(() => {\n if (this.pendingTurnCompletion) {\n this.logger?.warn(`Turn timed out after ${timeoutMs}ms — treating as abort`);\n this.resolvePendingTurn(true);\n }\n }, timeoutMs);\n });\n\n try {\n await this.sendTurn(prompt, opts);\n } catch (err) {\n if (timer) clearTimeout(timer);\n this.pendingTurnCompletion = null;\n throw err;\n }\n\n const aborted = await completion;\n if (timer) clearTimeout(timer);\n return { aborted };\n }\n\n async interruptTurn(): Promise<void> {\n if (!this._threadId) return;\n if (!this._turnId) {\n this.logger?.debug('interruptTurn: no active turnId, skipping');\n return;\n }\n const params: InterruptConversationParams = {\n threadId: this._threadId,\n turnId: this._turnId,\n };\n const doInterrupt = async () => {\n try {\n await this.request('turn/interrupt', params);\n } catch (err) {\n this.logger?.debug('interruptTurn error (may be expected):', err);\n } finally {\n this.pendingInterrupt = null;\n }\n };\n this.pendingInterrupt = doInterrupt();\n return this.pendingInterrupt;\n }\n\n hasActiveThread(): boolean {\n return this._threadId !== null;\n }\n\n // --- JSON-RPC transport ---\n\n private static readonly REQUEST_TIMEOUT_MS = 30_000;\n\n private request(method: string, params?: unknown, timeoutMs?: number): Promise<unknown> {\n const timeout = timeoutMs ?? CodexAppServerClient.REQUEST_TIMEOUT_MS;\n return new Promise((resolve, reject) => {\n if (!this.process?.stdin?.writable) {\n reject(new Error(`Cannot send ${method}: stdin not writable`));\n return;\n }\n const id = this.nextId++;\n\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`${method} timed out after ${timeout}ms (id=${id})`));\n }, timeout);\n\n this.pending.set(id, {\n resolve: (result) => { clearTimeout(timer); resolve(result); },\n reject: (err) => { clearTimeout(timer); reject(err); },\n method,\n epoch: this.processEpoch,\n });\n\n const msg: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\n const line = JSON.stringify(msg) + '\\n';\n this.logger?.debug(`-> ${method} (id=${id})`);\n this.process.stdin.write(line);\n });\n }\n\n private notify(method: string, params?: unknown): void {\n if (!this.process?.stdin?.writable) return;\n const msg: JsonRpcRequest = { jsonrpc: '2.0', method, params };\n this.process.stdin.write(JSON.stringify(msg) + '\\n');\n this.logger?.debug(`-> ${method} (notification)`);\n }\n\n private respond(id: number, result: unknown): void {\n if (!this.process?.stdin?.writable) return;\n const msg: JsonRpcResponse = { jsonrpc: '2.0', id, result };\n this.process.stdin.write(JSON.stringify(msg) + '\\n');\n this.logger?.debug(`-> response (id=${id})`);\n }\n\n private handleLine(line: string, sourceEpoch: number = this.processEpoch): void {\n if (sourceEpoch !== this.processEpoch) {\n return;\n }\n if (!line.trim()) return;\n\n let msg: any;\n try {\n msg = JSON.parse(line);\n } catch {\n this.logger?.debug('Non-JSON line:', line.substring(0, 200));\n return;\n }\n\n if (msg.id != null && (msg.result !== undefined || msg.error !== undefined)) {\n const pending = this.pending.get(msg.id);\n if (pending) {\n if (pending.epoch !== sourceEpoch) {\n this.logger?.debug(`Ignoring response from stale epoch for id=${msg.id}`);\n return;\n }\n this.pending.delete(msg.id);\n if (msg.error) {\n pending.reject(new Error(`${pending.method}: ${msg.error.message} (code=${msg.error.code})`));\n } else {\n pending.resolve(msg.result);\n }\n }\n return;\n }\n\n if (msg.id != null && msg.method) {\n this.handleServerRequest(msg.id, msg.method, msg.params).catch((err) => {\n this.logger?.debug('Error handling server request:', err);\n });\n return;\n }\n\n if (msg.method) {\n this.handleNotification(msg.method, msg.params);\n return;\n }\n\n this.logger?.debug('Unhandled message:', JSON.stringify(msg).substring(0, 300));\n }\n\n private mapDecisionToWire(decision: ReviewDecision, legacy: boolean): string | Record<string, unknown> {\n if (typeof decision === 'string') {\n if (legacy) {\n return decision;\n }\n switch (decision) {\n case 'approved': return 'accept';\n case 'approved_for_session': return 'acceptForSession';\n case 'denied': return 'decline';\n case 'abort': return 'cancel';\n default: return 'decline';\n }\n }\n if ('approved_execpolicy_amendment' in decision) {\n return decision;\n }\n return legacy ? 'denied' : 'decline';\n }\n\n private parseToolNameFromElicitationMessage(message: unknown): string | null {\n if (typeof message !== 'string') {\n return null;\n }\n const match = message.match(/tool \"([^\"]+)\"/i);\n return match?.[1] ?? null;\n }\n\n private mapDecisionToMcpElicitationResponse(\n decision: ReviewDecision,\n params: any,\n ): McpServerElicitationRequestResponse {\n if (typeof decision === 'string') {\n switch (decision) {\n case 'approved':\n case 'approved_for_session':\n return {\n action: 'accept',\n content: params?.mode === 'form' ? {} : null,\n _meta: null,\n };\n case 'abort':\n return {\n action: 'cancel',\n content: null,\n _meta: null,\n };\n case 'denied':\n default:\n return {\n action: 'decline',\n content: null,\n _meta: null,\n };\n }\n }\n\n return {\n action: 'decline',\n content: null,\n _meta: null,\n };\n }\n\n private async handleServerRequest(id: number, method: string, params: any): Promise<void> {\n if (method === 'mcpServer/elicitation/request') {\n const toolName = this.parseToolNameFromElicitationMessage(params?.message) ?? params?.serverName ?? 'McpTool';\n const decision = await this.handleApproval({\n type: 'mcp',\n callId: `${params?.serverName ?? 'mcp'}:${id}`,\n toolName,\n input: params?._meta?.tool_params ?? {},\n serverName: params?.serverName,\n message: params?.message,\n });\n this.respond(id, this.mapDecisionToMcpElicitationResponse(decision, params));\n return;\n }\n\n if (method === 'item/commandExecution/requestApproval' || method === 'execCommandApproval') {\n const legacy = method === 'execCommandApproval';\n const callId = params.itemId ?? params.callId ?? String(id);\n const decision = await this.handleApproval({\n type: 'exec',\n callId,\n command: params.command != null ? [params.command] : [],\n cwd: params.cwd,\n reason: params.reason,\n });\n this.respond(id, { decision: this.mapDecisionToWire(decision, legacy) });\n return;\n }\n\n if (method === 'item/fileChange/requestApproval' || method === 'applyPatchApproval') {\n const legacy = method === 'applyPatchApproval';\n const callId = params.itemId ?? params.callId ?? String(id);\n const decision = await this.handleApproval({\n type: 'patch',\n callId,\n fileChanges: params.fileChanges ?? (typeof callId === 'string'\n ? this.rawFileChangesByItemId.get(callId)\n : undefined),\n reason: params.reason,\n });\n this.respond(id, { decision: this.mapDecisionToWire(decision, legacy) });\n return;\n }\n\n this.logger?.debug(`Unknown server request: ${method}`);\n this.respond(id, {});\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0]): Promise<ReviewDecision> {\n if (this.approvalHandler) {\n try {\n return await this.approvalHandler(params);\n } catch (err) {\n this.logger?.debug('Approval handler error:', err);\n return 'denied';\n }\n }\n return 'denied';\n }\n\n private handleNotification(method: string, params: any): void {\n if (method === 'codex/event' || method.startsWith('codex/event/')) {\n this.notificationProtocol = 'legacy';\n const msg = params?.msg;\n if (msg) {\n if (msg.type === 'task_started' && msg.turn_id) {\n this._turnId = msg.turn_id;\n }\n if (msg.type === 'task_started') {\n this.markPendingTurnStarted(msg.turn_id ?? msg.turnId ?? null);\n }\n this.eventHandler?.(msg);\n if (msg.type === 'task_complete' || msg.type === 'turn_aborted') {\n const turnId = msg.turn_id ?? msg.turnId ?? null;\n if (turnId) {\n this.completedTurnIds.add(turnId);\n }\n this.tryResolvePendingTurn(\n msg.type === 'turn_aborted',\n turnId,\n `codex/event/${msg.type}`,\n );\n this._turnId = null;\n }\n }\n return;\n }\n\n if (this.handleRawNotification(method, params)) {\n return;\n }\n\n if (method === 'thread/started' || method === 'turn/started' ||\n method === 'turn/completed' || method === 'thread/status/changed') {\n if (method === 'turn/started') {\n const turnId = this.extractTurnId(params);\n if (turnId) {\n this._turnId = turnId;\n }\n this.markPendingTurnStarted(turnId);\n }\n if (method === 'turn/completed') {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n this.extractTurnStatus(params),\n params?.turn?.error ?? params?.error,\n method,\n );\n }\n return;\n }\n\n this.logger?.debug(`Notification: ${method}`);\n }\n}\n","import { appendFile, mkdir, readdir, readFile } from 'fs/promises';\nimport { readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport interface SessionFile {\n sessionId: string;\n agentType: string;\n date: string;\n path: string;\n size: number;\n}\n\ninterface PersistedEvent {\n v: number;\n ts: string;\n [key: string]: unknown;\n}\n\nexport class Persistence {\n private baseDir: string;\n\n constructor(baseDir: string) {\n this.baseDir = baseDir;\n }\n\n /**\n * Write event to session's JSONL file (append-only)\n * File structure: {baseDir}/{YYYY-MM-DD}/{agentType}-{sessionId}.jsonl\n */\n async write(sessionId: string, agentType: string, event: unknown): Promise<void> {\n const date = new Date().toISOString().split('T')[0];\n const dateDir = join(this.baseDir, date);\n const filePath = join(dateDir, `${agentType}-${sessionId}.jsonl`);\n\n // Create date directory if it doesn't exist\n if (!existsSync(dateDir)) {\n await mkdir(dateDir, { recursive: true });\n }\n\n // Create the persisted event with version and timestamp\n const persistedEvent: PersistedEvent = {\n v: 1,\n ts: new Date().toISOString(),\n ...(event as Record<string, unknown>),\n };\n\n // Append to file with newline\n const line = JSON.stringify(persistedEvent) + '\\n';\n await appendFile(filePath, line, { flag: 'a' });\n }\n\n /**\n * Read all events for a session\n */\n async *read(sessionId: string): AsyncIterable<unknown> {\n // Find the session file by scanning date directories\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n const dateDirs = entries.filter(e => e.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(e.name));\n\n for (const dateDir of dateDirs) {\n const dirPath = join(this.baseDir, dateDir.name);\n const files = await readdir(dirPath);\n\n // Find file matching sessionId\n const fileName = files.find(f => f.endsWith(`-${sessionId}.jsonl`));\n if (fileName) {\n const filePath = join(dirPath, fileName);\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.length > 0);\n\n for (const line of lines) {\n try {\n yield JSON.parse(line);\n } catch {\n // Skip invalid JSON lines\n continue;\n }\n }\n return; // Found and yielded all events, stop searching\n }\n }\n }\n\n /**\n * List all session files\n */\n list(): SessionFile[] {\n const sessions: SessionFile[] = [];\n\n if (!existsSync(this.baseDir)) {\n return sessions;\n }\n\n const entries = readdirSync(this.baseDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(entry.name)) {\n const date = entry.name;\n const dateDir = join(this.baseDir, date);\n const files = readdirSync(dateDir);\n\n for (const fileName of files) {\n if (fileName.endsWith('.jsonl')) {\n const filePath = join(dateDir, fileName);\n const stats = statSync(filePath);\n\n // Parse filename: {agentType}-{sessionId}.jsonl\n // agentType is the first part, sessionId is everything after the first dash\n const match = fileName.match(/^([^-]+)-(.+)\\.jsonl$/);\n if (match) {\n const [, agentType, sessionId] = match;\n sessions.push({\n sessionId,\n agentType,\n date,\n path: filePath,\n size: stats.size,\n });\n }\n }\n }\n }\n }\n\n return sessions;\n }\n}\n","import { createServer, IncomingMessage, Server, ServerResponse } from 'http';\nimport { URL } from 'url';\nimport { getLogger } from '../shared/logger.js';\nimport type { Gateway } from '../gateway/index.js';\nimport type { InteractionResponse } from '../core/interaction/types.js';\nimport { AgentAdapterRegistry } from '../core/adapter/AgentAdapterRegistry.js';\nimport { ClaudeHookAgentAdapter } from '../adapters/agent/claude/ClaudeHookAgentAdapter.js';\nimport { isClaudeHookEventType } from '../adapters/agent/claude/hook-types.js';\nimport type { AgentType } from '../core/adapter/types.js';\n\nexport type RequestHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;\nexport type UpgradeHandler = (request: IncomingMessage, socket: import('stream').Duplex, head: Buffer) => void;\n\ninterface Route {\n method: string;\n path: string | RegExp;\n handler: RequestHandler;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * HTTP Server for the Gateway\n */\nexport class HttpServer {\n private server: Server | null = null;\n private routes: Route[] = [];\n private upgradeHandlers = new Map<string, UpgradeHandler>();\n\n constructor(private port: number) {}\n\n /**\n * Register a route handler\n */\n registerRoute(method: string, path: string | RegExp, handler: RequestHandler): void {\n this.routes.push({ method: method.toUpperCase(), path, handler });\n logger.debug(`Registered route: ${method} ${path}`);\n }\n\n /**\n * Register a WebSocket upgrade handler for a specific path\n */\n onUpgrade(path: string, handler: UpgradeHandler): () => void {\n this.upgradeHandlers.set(path, handler);\n logger.debug(`Registered upgrade handler: ${path}`);\n return () => {\n this.upgradeHandlers.delete(path);\n logger.debug(`Unregistered upgrade handler: ${path}`);\n };\n }\n\n /**\n * Start the HTTP server\n */\n async start(): Promise<void> {\n this.server = createServer(this.handleRequest.bind(this));\n\n // Handle upgrade requests\n this.server.on('upgrade', (request, socket, head) => {\n const pathname = request.url\n ? new URL(request.url, `http://localhost:${this.port}`).pathname\n : '';\n\n const handler = this.upgradeHandlers.get(pathname);\n if (handler) {\n handler(request, socket, head);\n } else {\n socket.destroy();\n }\n });\n\n return new Promise((resolve, reject) => {\n this.server?.listen(this.port, () => {\n logger.info(`HTTP server listening on port ${this.port}`);\n resolve();\n });\n this.server?.on('error', reject);\n });\n }\n\n /**\n * Stop the HTTP server\n */\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.server?.close(() => {\n logger.info('HTTP server stopped');\n resolve();\n });\n });\n }\n\n /**\n * Get the underlying server instance\n */\n getServer(): Server | null {\n return this.server;\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n (async () => {\n const url = new URL(req.url || '/', `http://localhost:${this.port}`);\n const pathname = url.pathname;\n const method = (req.method || 'GET').toUpperCase();\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Find matching route\n const route = this.routes.find((r) => {\n if (r.method !== method) return false;\n if (typeof r.path === 'string') {\n return r.path === pathname;\n }\n return r.path.test(pathname);\n });\n\n if (route) {\n await route.handler(req, res);\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n })().catch((error) => {\n logger.error('Error handling HTTP request:', error);\n if (!res.headersSent) {\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n }\n}\n\n/**\n * Parse JSON body from incoming request\n */\nexport function parseJsonBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n try {\n if (!body) {\n resolve({});\n return;\n }\n resolve(JSON.parse(body));\n } catch (error) {\n reject(error);\n }\n });\n req.on('error', reject);\n });\n}\n\n/**\n * Send JSON response helper\n */\nexport function sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.writeHead(statusCode, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\n/**\n * Format hook response per Claude Code hook protocol.\n *\n * | EventType | Tool | Response Format |\n * |-----------|------|-----------------|\n * | PermissionRequest (non-AskUserQuestion) | any | hookSpecificOutput.decision |\n * | PreToolUse (AskUserQuestion) | AskUserQuestion | hookSpecificOutput.decision with updatedInput.answers |\n * | PreToolUse (other tool) | any | { accepted, message?, data? } |\n */\nfunction formatHookResponse(\n eventType: string,\n toolName: string,\n result: InteractionResponse\n): string {\n const isAskUserQuestion = toolName === 'AskUserQuestion';\n\n if (isAskUserQuestion) {\n // AskUserQuestion uses PermissionRequest format with updatedInput\n const questions = result._toolInput?.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; value?: unknown }>;\n }> | undefined;\n const question = questions?.[0];\n\n const selectedValueStr =\n result.selectedValues && result.selectedValues.length > 0\n ? result.selectedValues.map(String).join(', ')\n : undefined;\n const answerValue = result.customInput ?? selectedValueStr ?? '';\n\n const updatedInput: Record<string, unknown> = {\n ...result._toolInput,\n answers: question?.question\n ? { [question.question]: answerValue }\n : {},\n };\n\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: 'allow',\n updatedInput,\n },\n },\n });\n }\n\n if (eventType === 'PermissionRequest') {\n // PermissionRequest uses PermissionRequest format\n let updatedPermissions: unknown[] | undefined;\n if (result.permissionUpdates && result.permissionUpdates.length > 0) {\n updatedPermissions = result.permissionUpdates.map((rule) => ({\n type: rule.type,\n ...(rule.rules && { rules: rule.rules }),\n ...(rule.behavior && { behavior: rule.behavior }),\n destination: rule.destination ?? (result.permanent ? 'userSettings' : 'session'),\n ...(rule.mode && { mode: rule.mode }),\n ...(rule.directories && { directories: rule.directories }),\n }));\n }\n\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: result.action === 'select' ? 'allow' : result.action,\n ...(result.message !== undefined && { message: result.message }),\n ...(result.selectedValues !== undefined && {\n data: result.selectedValues.map(String).join(', '),\n }),\n ...(updatedPermissions !== undefined && { updatedPermissions }),\n },\n },\n });\n }\n\n // For PreToolUse and other hooks\n return JSON.stringify({\n accepted: ['allow', 'select', 'confirm'].includes(result.action),\n message: result.message,\n ...(result.selectedValues !== undefined && {\n data: result.selectedValues.map(String).join(', '),\n }),\n });\n}\n\n/**\n * Setup HTTP routes for the Gateway\n */\nexport function setupRoutes(\n httpServer: HttpServer,\n gateway: Gateway,\n getClientCount: () => number\n): void {\n // Health check\n httpServer.registerRoute('GET', '/health', (_req, res) => {\n sendJson(res, 200, { status: 'ok', version: VERSION });\n });\n\n // Status\n httpServer.registerRoute('GET', '/status', (_req, res) => {\n const sessions = gateway.listSessions();\n sendJson(res, 200, {\n running: true,\n sessions: sessions.map((s) => ({\n sessionId: s.id,\n agentType: s.agentType,\n status: s.status,\n startedAt: s.startedAt?.toISOString(),\n updatedAt: new Date(s.updatedAt).toISOString(),\n })),\n clients: getClientCount(),\n });\n });\n\n // Register agent\n httpServer.registerRoute('POST', '/api/v1/agents', async (req, res) => {\n try {\n const body = await parseJsonBody(req);\n\n if (!body.agentType || typeof body.agentType !== 'string' || body.agentType.trim() === '') {\n sendJson(res, 400, { error: 'Missing or invalid agentType' });\n return;\n }\n\n const agentType = body.agentType.trim();\n const token = gateway.registerAgent(agentType);\n\n logger.info(`Registered agent: ${agentType} with token: ${token.substring(0, 8)}...`);\n\n sendJson(res, 201, {\n token,\n hooks: {\n endpoint: `/hook/${token}/{event}`,\n events: [\n 'SessionStart',\n 'SessionEnd',\n 'Stop',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'PreToolUse',\n 'PermissionRequest',\n 'SubagentStart',\n 'SubagentStop',\n 'UserPromptSubmit',\n ],\n },\n });\n } catch (error) {\n logger.error('Error registering agent:', error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n\n // List agents\n httpServer.registerRoute('GET', '/api/v1/agents', (_req, res) => {\n const registeredAgents = gateway.listRegisteredAgents();\n const sessions = gateway.listSessions({ includeEnded: true });\n const sessionCounts = new Map<string, number>();\n\n for (const session of sessions) {\n const token = session.token || 'unknown';\n sessionCounts.set(token, (sessionCounts.get(token) || 0) + 1);\n }\n\n const agents = registeredAgents.map(({ token, agentType }) => ({\n token,\n agentType,\n sessionCount: sessionCounts.get(token) || 0,\n }));\n\n sendJson(res, 200, { agents });\n });\n\n // Hook endpoint: /hook/{token}/{event}\n // Supports both legacy format (/hook/{token}/Stop) and unified format (/hook/{token}/event)\n httpServer.registerRoute('POST', /^\\/hook\\/[^/]+\\/(.+)$/, async (req, res) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const match = url.pathname.match(/^\\/hook\\/([^/]+)\\/(.+)$/);\n if (!match) {\n sendJson(res, 404, { error: 'Not found' });\n return;\n }\n\n const [, token, pathEventType] = match;\n const body = await parseJsonBody(req);\n\n // Support unified hook format: /hook/{token}/event\n // In unified format, event type is passed in body.hook_event_name\n const eventType = pathEventType === 'event' && body.hook_event_name\n ? String(body.hook_event_name)\n : pathEventType;\n\n if (!isClaudeHookEventType(eventType)) {\n sendJson(res, 202, { accepted: true, warning: 'Unknown event type' });\n return;\n }\n\n // DEBUG: Log the full token being used\n logger.debug({ token: token.substring(0, 8), fullToken: token, eventType }, 'Processing hook request');\n\n try {\n // Token validation / auto-registration\n let agentType = gateway.getAgentRegistry().getAgentType(token);\n if (!agentType) {\n logger.warn(`Auto-registering unknown token from hook request: ${token.substring(0, 8)}...`);\n agentType = 'claude';\n gateway.registerAgent(agentType, token);\n }\n\n logger.info({ eventType, token: token.substring(0, 8), body }, 'Hook payload received');\n\n // Get hook adapter for this agent type\n const adapter = AgentAdapterRegistry.getInstance()\n .get(agentType as AgentType, 'hook') as ClaudeHookAgentAdapter | undefined;\n\n if (!adapter) {\n logger.warn({ agentType, eventType }, 'Hook adapter not available');\n sendJson(res, 503, { error: 'Hook adapter not available' });\n return;\n }\n\n // Route to adapter\n if (eventType === 'PreToolUse' || eventType === 'PermissionRequest') {\n const requestId = typeof body.request_id === 'string'\n ? body.request_id\n : typeof body.session_id === 'string'\n ? body.session_id\n : `req-${Date.now()}`;\n const toolName = typeof body.tool_name === 'string' ? body.tool_name : 'unknown';\n\n // Permission hooks wait for user decision; timeout is managed by InteractionQueue\n const result = await adapter.processPermissionRequest(eventType, body, requestId);\n const responseBody = formatHookResponse(eventType, toolName, result);\n logger.info({ eventType, response: responseBody }, 'Sending hook response');\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(responseBody);\n } else {\n adapter.processHookEvent(eventType, body).catch((err) => {\n logger.warn({ eventType, error: err instanceof Error ? err.message : String(err) }, 'Hook event processing failed');\n });\n sendJson(res, 202, { accepted: true });\n }\n } catch (error) {\n logger.error(`Error processing hook for token ${token.substring(0, 8)}...:`, error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n}\n","import { WebSocketServer as WSWebSocketServer, WebSocket } from 'ws';\nimport { IncomingMessage } from 'http';\nimport { URL } from 'url';\nimport { getLogger } from '../shared/logger.js';\nimport type { HttpServer } from './http.js';\nimport type { Gateway } from '../gateway/index.js';\nimport type { EventFrame, ResponseFrame } from '../gateway/events.js';\nimport type { InteractionQueue } from '../adapters/interaction/index.js';\n\nexport interface Client {\n id: string;\n ws: WebSocket;\n isAlive: boolean;\n filters?: ClientFilters;\n}\n\nexport interface ClientFilters {\n agentTypes?: string[];\n sessionIds?: string[];\n}\n\nexport type MessageHandler = (clientId: string, message: WebSocketMessage) => void;\nexport type ConnectionHandler = (clientId: string) => void;\n\nexport interface WebSocketMessage {\n type: string;\n id?: string;\n requestId?: string;\n allow?: boolean;\n reason?: string;\n filters?: ClientFilters;\n [key: string]: unknown;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * WebSocket Server for the Gateway\n */\nexport class WebSocketServer {\n private wss: WSWebSocketServer | null = null;\n private clients = new Map<string, Client>();\n private messageHandlers: MessageHandler[] = [];\n private connectionHandlers: ConnectionHandler[] = [];\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private clientIdCounter = 0;\n\n constructor(\n private httpServer: HttpServer,\n private options: { heartbeatIntervalMs?: number; path?: string } = {}\n ) {}\n\n /**\n * Start the WebSocket server\n */\n async start(): Promise<void> {\n const httpSvr = this.httpServer.getServer();\n if (!httpSvr) {\n throw new Error('HTTP server must be started before WebSocket server');\n }\n\n this.wss = new WSWebSocketServer({ noServer: true });\n this.setupConnectionHandlers();\n this.startHeartbeat();\n\n // Register upgrade handler with HTTP server\n const path = this.options.path || '/ws';\n this.httpServer.onUpgrade(path, (request, socket, head) => {\n this.wss?.handleUpgrade(request, socket, head, (ws) => {\n this.wss?.emit('connection', ws, request);\n });\n });\n\n logger.info(`WebSocket server registered on path: ${path}`);\n }\n\n /**\n * Stop the WebSocket server\n */\n async stop(): Promise<void> {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n\n this.closeAll();\n\n return new Promise((resolve) => {\n this.wss?.close(() => {\n logger.info('WebSocket server stopped');\n resolve();\n });\n });\n }\n\n /**\n * Add a message handler\n */\n onMessage(handler: MessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Add a connection handler\n */\n onConnection(handler: ConnectionHandler): void {\n this.connectionHandlers.push(handler);\n }\n\n /**\n * Add a new client connection\n */\n add(ws: WebSocket, req?: IncomingMessage): string {\n const clientId = `client-${++this.clientIdCounter}`;\n const client: Client = {\n id: clientId,\n ws,\n isAlive: true,\n };\n this.clients.set(clientId, client);\n\n // Parse query parameters for pre-filters\n if (req?.url) {\n const url = new URL(req.url, 'http://localhost');\n const agentType = url.searchParams.get('agentType');\n const sessionId = url.searchParams.get('sessionId');\n\n if (agentType || sessionId) {\n client.filters = {\n agentTypes: agentType ? [agentType] : undefined,\n sessionIds: sessionId ? [sessionId] : undefined,\n };\n }\n }\n\n ws.on('pong', () => {\n client.isAlive = true;\n });\n\n ws.on('message', (data: Buffer) => {\n try {\n const message = JSON.parse(data.toString()) as WebSocketMessage;\n this.handleMessage(clientId, message);\n } catch (error) {\n logger.error('Invalid WebSocket message:', error);\n this.send(clientId, {\n type: 'res',\n id: 'error',\n error: { code: 400, message: 'Invalid JSON message' },\n });\n }\n });\n\n ws.on('close', () => {\n this.remove(clientId);\n });\n\n ws.on('error', (error) => {\n logger.error(`WebSocket error for client ${clientId}:`, error);\n this.remove(clientId);\n });\n\n logger.info(`WebSocket client connected: ${clientId}`);\n\n for (const handler of this.connectionHandlers) {\n try {\n handler(clientId);\n } catch (error) {\n logger.error('Error in connection handler:', error);\n }\n }\n\n return clientId;\n }\n\n /**\n * Remove a client connection\n */\n remove(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n this.clients.delete(clientId);\n logger.info(`WebSocket client disconnected: ${clientId}`);\n }\n }\n\n /**\n * Get a client by ID\n */\n get(clientId: string): Client | undefined {\n return this.clients.get(clientId);\n }\n\n /**\n * Get count of connected clients\n */\n getClientCount(): number {\n return this.clients.size;\n }\n\n /**\n * Send a message to a specific client\n */\n send(clientId: string, message: unknown): boolean {\n const client = this.clients.get(clientId);\n if (client && client.ws.readyState === WebSocket.OPEN) {\n client.ws.send(JSON.stringify(message));\n return true;\n }\n return false;\n }\n\n /**\n * Broadcast a message to all connected clients\n */\n broadcast(message: unknown, filter?: (client: Client) => boolean): void {\n const messageStr = JSON.stringify(message);\n for (const [, client] of this.clients) {\n if (client.ws.readyState === WebSocket.OPEN) {\n if (!filter || filter(client)) {\n client.ws.send(messageStr);\n }\n }\n }\n }\n\n /**\n * Close all client connections\n */\n closeAll(): void {\n for (const [, client] of this.clients) {\n client.ws.close();\n }\n this.clients.clear();\n }\n\n /**\n * Set client filters\n */\n setFilters(clientId: string, filters: ClientFilters): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = filters;\n }\n }\n\n /**\n * Clear client filters\n */\n clearFilters(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = undefined;\n }\n }\n\n private setupConnectionHandlers(): void {\n this.wss?.on('connection', (ws: WebSocket, req: IncomingMessage) => {\n this.add(ws, req);\n });\n }\n\n private handleMessage(clientId: string, message: WebSocketMessage): void {\n for (const handler of this.messageHandlers) {\n try {\n handler(clientId, message);\n } catch (error) {\n logger.error('Error in WebSocket message handler:', error);\n }\n }\n }\n\n private startHeartbeat(): void {\n const intervalMs = this.options.heartbeatIntervalMs || 30000;\n this.heartbeatInterval = setInterval(() => {\n for (const [, client] of this.clients) {\n if (!client.isAlive) {\n client.ws.terminate();\n this.remove(client.id);\n continue;\n }\n client.isAlive = false;\n client.ws.ping();\n }\n }, intervalMs);\n }\n}\n\nexport interface WebSocketSetupOptions {\n interactionQueue?: InteractionQueue;\n}\n\n/**\n * Setup WebSocket message handlers\n */\nexport function setupWebSocketHandlers(\n wsServer: WebSocketServer,\n gateway: Gateway,\n options: WebSocketSetupOptions = {}\n): void {\n const { interactionQueue } = options;\n // Send welcome message on new connection\n wsServer.onConnection((clientId) => {\n const welcomeFrame: ResponseFrame = {\n type: 'res',\n id: 'welcome',\n result: {\n message: 'Connected to Handsoff Gateway',\n version: VERSION,\n clientId,\n },\n };\n wsServer.send(clientId, welcomeFrame);\n });\n\n // Handle subscription messages\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'subscribe') {\n const filters = message.filters as { agentTypes?: string[]; sessionIds?: string[] } | undefined;\n wsServer.setFilters(clientId, filters || {});\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'subscribe',\n result: { subscribed: true },\n });\n } else if (message.type === 'unsubscribe') {\n wsServer.clearFilters(clientId);\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'unsubscribe',\n result: { unsubscribed: true },\n });\n }\n });\n\n // Handle list_sessions message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'list_sessions') {\n const sessions = gateway.listSessions();\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'list_sessions',\n result: {\n sessions: sessions.map((s) => ({\n id: s.id,\n agentType: s.agentType,\n status: s.status,\n startedAt: s.startedAt?.toISOString(),\n updatedAt: new Date(s.updatedAt).toISOString(),\n })),\n },\n });\n }\n });\n\n // Handle unknown message types\n wsServer.onMessage((clientId, message) => {\n const knownTypes = ['subscribe', 'unsubscribe', 'list_sessions', 'welcome', 'permission_decision', 'list_pending_permissions'];\n if (!knownTypes.includes(message.type)) {\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'unknown',\n error: { code: 400, message: `Unknown message type: ${message.type}` },\n });\n }\n });\n\n // Handle permission_decision message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'permission_decision' && interactionQueue) {\n const { requestId, allow, reason } = message as {\n requestId: string;\n allow: boolean;\n reason?: string;\n };\n\n const success = interactionQueue.respond(requestId, {\n requestId,\n action: allow ? 'allow' : 'deny',\n message: reason,\n });\n\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'permission_decision',\n result: {\n success,\n message: success ? 'Decision recorded' : 'Request not found or already decided',\n },\n });\n }\n });\n\n // Handle list_pending_permissions message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'list_pending_permissions' && interactionQueue) {\n const pending = interactionQueue.listPending();\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'list_pending_permissions',\n result: { pending },\n });\n }\n });\n}\n\n/**\n * Broadcast event to WebSocket clients with filtering\n */\nexport function broadcastEvent(wsServer: WebSocketServer, frame: EventFrame): void {\n wsServer.broadcast(frame, (client) => {\n if (!client.filters) return true;\n\n const { agentTypes, sessionIds } = client.filters;\n const { agentType, sessionId } = frame.payload;\n\n if (agentTypes && agentTypes.length > 0 && !agentTypes.includes(agentType)) {\n return false;\n }\n\n if (sessionIds && sessionIds.length > 0 && !sessionIds.includes(sessionId)) {\n return false;\n }\n\n return true;\n });\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\n\nexport interface Credentials {\n version: string;\n hookToken: string;\n createdAt: string;\n}\n\nconst CREDENTIALS_VERSION = '1';\nconst DEFAULT_TOKEN_LENGTH = 8;\n\nfunction getCredentialsPath(): string {\n return join(homedir(), '.handsoff', 'credentials.json');\n}\n\nfunction generateToken(): string {\n return randomBytes(DEFAULT_TOKEN_LENGTH).toString('hex');\n}\n\nexport function loadCredentials(): Credentials | null {\n const path = getCredentialsPath();\n\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n console.error(`Failed to load credentials from ${path}:`, error);\n return null;\n }\n}\n\nexport function saveCredentials(credentials: Credentials): void {\n const path = getCredentialsPath();\n // Ensure directory exists before writing\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(credentials, null, 2), { mode: 0o600 });\n}\n\nexport function getOrCreateHookToken(): string {\n const existing = loadCredentials();\n\n if (existing?.hookToken) {\n return existing.hookToken;\n }\n\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n\nexport function getHookToken(): string | null {\n return loadCredentials()?.hookToken ?? null;\n}\n\nexport function resetCredentials(): string {\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n","import { randomUUID } from 'crypto';\nimport { getLogger } from '../../shared/logger.js';\nimport type {\n InteractionResponse,\n InteractionRequestResult,\n InteractionQueueOptions,\n PendingInteraction,\n PendingInteractionInfo,\n} from './types.js';\nimport type { InteractionRequest } from '../../core/interaction/types.js';\n\nexport class InteractionQueue {\n private pending = new Map<string, PendingInteraction>();\n private timeoutMs: number;\n private defaultOnTimeout: 'allow' | 'deny';\n\n constructor(options: InteractionQueueOptions = {}) {\n this.timeoutMs = options.timeoutMs ?? 300000; // 5 minutes\n this.defaultOnTimeout = options.defaultOnTimeout ?? 'deny';\n }\n\n request(request: InteractionRequest): InteractionRequestResult {\n const requestId = randomUUID();\n\n const responsePromise = new Promise<InteractionResponse>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pending.delete(requestId);\n getLogger().info(\n `[Interaction] Timeout: ${request.toolName} | requestId=${requestId} | default=${this.defaultOnTimeout}`\n );\n resolve({\n requestId,\n action: this.defaultOnTimeout,\n message: `Interaction request timed out after ${this.timeoutMs}ms`,\n });\n }, this.timeoutMs);\n\n const pending: PendingInteraction = {\n requestId,\n sessionId: request.sessionId,\n type: request.type,\n toolName: request.toolName,\n toolInput: request.toolInput,\n timestamp: request.timestamp,\n timeoutId,\n resolve: (response) => {\n clearTimeout(timeoutId);\n this.pending.delete(requestId);\n resolve(response);\n },\n reject: (error) => {\n clearTimeout(timeoutId);\n this.pending.delete(requestId);\n reject(error);\n },\n };\n\n this.pending.set(requestId, pending);\n });\n\n return { requestId, responsePromise };\n }\n\n respond(requestId: string, response: InteractionResponse): boolean {\n const pending = this.pending.get(requestId);\n if (!pending) {\n getLogger().warn(`[Interaction] Response failed: requestId=${requestId} not found`);\n return false;\n }\n\n const elapsed = Date.now() - pending.timestamp;\n const dataInfo = response.selectedValues?.length || response.customInput !== undefined\n ? ` | value=${response.selectedValues?.join(', ') ?? response.customInput}`\n : '';\n getLogger().info(\n `[Interaction] Response: ${pending.toolName} | requestId=${requestId} | action=${response.action}${dataInfo} | waited=${elapsed}ms`\n );\n\n // Include original toolInput in the response for formatting\n const fullResponse: InteractionResponse = {\n ...response,\n _toolInput: pending.toolInput,\n };\n\n pending.resolve(fullResponse);\n return true;\n }\n\n get(requestId: string): PendingInteraction | undefined {\n return this.pending.get(requestId);\n }\n\n listPending(): PendingInteractionInfo[] {\n const now = Date.now();\n return Array.from(this.pending.values()).map((p) => ({\n requestId: p.requestId,\n sessionId: p.sessionId,\n type: p.type as InteractionRequest['type'],\n toolName: p.toolName,\n elapsedMs: now - p.timestamp,\n }));\n }\n\n cancelAll(reason: string): void {\n const count = this.pending.size;\n if (count === 0) return;\n\n getLogger().info(`[Interaction] Cancel all: ${count} pending | reason=${reason}`);\n for (const [, pending] of this.pending) {\n pending.reject(new Error(`Cancelled: ${reason}`));\n }\n this.pending.clear();\n }\n\n cancelBySession(sessionId: string, reason: string): number {\n let count = 0;\n for (const [id, pending] of this.pending) {\n if (pending.sessionId === sessionId) {\n pending.reject(new Error(`Cancelled: ${reason}`));\n this.pending.delete(id);\n count++;\n }\n }\n if (count > 0) {\n getLogger().info(`[Interaction] Cancel session: ${count} pending | sessionId=${sessionId} | reason=${reason}`);\n }\n return count;\n }\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport dotenv from 'dotenv';\n// Note: Notification types removed - using EventBus architecture now\n\n// Load .env file if exists\ndotenv.config();\n\nexport interface GeneralConfig {\n log_level: string;\n hook_server_port: number;\n}\n\nexport interface TelegramConfig {\n enabled: boolean;\n bot_token: string;\n allowed_users: string[];\n notify_types?: string[];\n}\n\nexport interface FeishuConfig {\n enabled: boolean;\n app_id: string;\n app_secret: string;\n allowed_users?: string[];\n notify_types?: string[];\n}\n\nexport interface ClaudeAgentConfig {\n adapter?: 'hooks' | 'remote';\n binary: string;\n work_dir: string;\n model: string;\n permission_mode?: string;\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n}\n\nexport interface LoggerConfig {\n enabled: boolean;\n notify_types?: string[];\n}\n\nexport interface PermissionConfig {\n timeout_ms: number;\n default_on_timeout: 'allow' | 'deny';\n}\n\nexport interface ChannelConfig {\n logger?: LoggerConfig;\n telegram?: TelegramConfig;\n feishu?: FeishuConfig;\n permission?: PermissionConfig;\n app?: AppChannelConfig;\n}\n\nexport interface AppChannelConfig {\n enabled: boolean;\n channel_id: string;\n auth_token: string;\n heartbeat_interval_ms?: number;\n notify_types?: string[];\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig;\n codex?: CodexAgentConfig;\n}\n\nexport interface BindingsConfig {\n claude?: string; // \"channelType:channelInstanceId\" e.g. \"telegram:abc123\"\n codex?: string;\n}\n\nexport interface Config {\n general: GeneralConfig;\n channel: ChannelConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n log_level: 'info',\n hook_server_port: 9876,\n },\n channel: {\n logger: {\n enabled: true,\n },\n telegram: {\n enabled: true,\n bot_token: '',\n allowed_users: [],\n },\n feishu: {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [],\n notify_types: [],\n },\n permission: {\n timeout_ms: 300000, // 5 minutes\n default_on_timeout: 'deny',\n },\n app: {\n enabled: false,\n channel_id: '',\n auth_token: '',\n },\n },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n },\n },\n bindings: {},\n};\n\nfunction getConfigPath(): string {\n return join(homedir(), '.handsoff', 'config.toml');\n}\n\nfunction mergeWithDefaults(raw: any): Config {\n return {\n general: {\n ...DEFAULT_CONFIG.general,\n ...(raw.general || {}),\n hook_server_port: parseInt(\n process.env.HANDSOFF_HOOK_SERVER_PORT ||\n String(raw.general?.hook_server_port || DEFAULT_CONFIG.general.hook_server_port),\n 10\n ),\n },\n channel: {\n logger: {\n ...DEFAULT_CONFIG.channel.logger,\n ...(raw.channel?.logger || {}),\n notify_types: raw.channel?.logger?.notify_types,\n },\n telegram: {\n ...DEFAULT_CONFIG.channel.telegram,\n ...(raw.channel?.telegram || {}),\n allowed_users: (raw.channel?.telegram?.allowed_users || []).map(String),\n bot_token:\n process.env.HANDSOFF_TELEGRAM_BOT_TOKEN ||\n raw.channel?.telegram?.bot_token ||\n '',\n notify_types: raw.channel?.telegram?.notify_types,\n },\n feishu: {\n ...DEFAULT_CONFIG.channel.feishu,\n ...(raw.channel?.feishu || {}),\n allowed_users: raw.channel?.feishu?.allowed_users || [],\n app_id:\n process.env.HANDSOFF_FEISHU_APP_ID || raw.channel?.feishu?.app_id || '',\n app_secret:\n process.env.HANDSOFF_FEISHU_APP_SECRET ||\n raw.channel?.feishu?.app_secret ||\n '',\n notify_types: raw.channel?.feishu?.notify_types,\n },\n permission: {\n ...DEFAULT_CONFIG.channel.permission,\n ...(raw.channel?.permission || {}),\n // Support env var override\n timeout_ms: parseInt(\n process.env.HANDSOFF_PERMISSION_TIMEOUT_MS ||\n String(\n raw.channel?.permission?.timeout_ms ||\n DEFAULT_CONFIG.channel.permission!.timeout_ms\n ),\n 10\n ),\n default_on_timeout:\n (process.env.HANDSOFF_PERMISSION_DEFAULT as 'allow' | 'deny') ||\n raw.channel?.permission?.default_on_timeout ||\n DEFAULT_CONFIG.channel.permission!.default_on_timeout,\n },\n app: {\n ...DEFAULT_CONFIG.channel.app!,\n ...(raw.channel?.app || {}),\n enabled: raw.channel?.app?.enabled === true,\n channel_id: String(raw.channel?.app?.channel_id || ''),\n auth_token: String(raw.channel?.app?.auth_token || ''),\n heartbeat_interval_ms: raw.channel?.app?.heartbeat_interval_ms\n ? parseInt(String(raw.channel?.app?.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channel?.app?.notify_types)\n ? raw.channel.app.notify_types.map(String)\n : undefined,\n },\n },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n },\n codex: {\n ...DEFAULT_CONFIG.agent.codex!,\n ...(raw.agent?.codex || {}),\n command: raw.agent?.codex?.command\n ? raw.agent.codex.command\n : DEFAULT_CONFIG.agent.codex!.command,\n work_dir: raw.agent?.codex?.work_dir || DEFAULT_CONFIG.agent.codex!.work_dir,\n model: raw.agent?.codex?.model || DEFAULT_CONFIG.agent.codex!.model,\n approval_policy: raw.agent?.codex?.approval_policy || DEFAULT_CONFIG.agent.codex!.approval_policy,\n },\n },\n bindings: {\n ...DEFAULT_CONFIG.bindings,\n ...(raw.bindings || {}),\n },\n };\n}\n\nexport function loadConfig(): Config {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return DEFAULT_CONFIG;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const raw = TOML.parse(content) as any;\n return mergeWithDefaults(raw);\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return DEFAULT_CONFIG;\n }\n}\n","import EventEmitter from 'events';\nimport { getLogger } from '../../shared/logger.js';\nimport { BusEvent, EventHandler } from './types.js';\nimport {\n InboundMessage,\n OutboundMessage,\n InteractionRequestEvent,\n InteractionResponseEvent,\n CommandEvent,\n SessionStartEvent,\n SessionEndEvent,\n ToolPostEvent,\n ToolFailureEvent,\n TurnFinishedEvent,\n ToolExecutedEvent,\n TurnThinkingEvent,\n FinishedEvent,\n NotificationEvent,\n AllBusEvents,\n ProtocolEvent,\n} from './events.js';\n\n/**\n * 类型安全的事件总线\n * 支持 Inbound/Outbound 双向事件流\n */\nexport class EventBus {\n private emitter: EventEmitter;\n private logger: ReturnType<typeof getLogger>;\n\n constructor() {\n this.emitter = new EventEmitter();\n this.logger = getLogger();\n this.logger.debug('EventBus initialized');\n }\n\n /**\n * 通用事件发布\n */\n emit<T extends AllBusEvents>(event: T): void {\n this.emitter.emit(event.type, event);\n }\n\n /**\n * 通用事件订阅\n */\n on<T extends AllBusEvents>(\n eventType: T['type'],\n handler: EventHandler<T>\n ): () => void {\n this.emitter.on(eventType, handler);\n return () => {\n this.emitter.off(eventType, handler);\n };\n }\n\n /**\n * 发布入站消息\n */\n publishInbound(message: Omit<InboundMessage, 'type' | 'timestamp'>): void {\n const event: InboundMessage = {\n ...message,\n type: 'inbound:message',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅入站消息\n */\n onInbound(handler: EventHandler<InboundMessage>): () => void {\n return this.on('inbound:message', handler);\n }\n\n /**\n * 发布出站消息\n */\n publishOutbound(message: Omit<OutboundMessage, 'type' | 'timestamp'>): void {\n const event: OutboundMessage = {\n ...message,\n type: 'outbound:message',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅出站消息\n */\n onOutbound(handler: EventHandler<OutboundMessage>): () => void {\n return this.on('outbound:message', handler);\n }\n\n /**\n * @deprecated Use publishInteractionRequest instead\n * 发布权限申请事件 (backward compatibility - converts to interaction:request)\n */\n publishPermissionRequest(\n request: {\n requestId: string;\n sessionId: string;\n toolName: string;\n args: Record<string, unknown>;\n chatId: string;\n messageId: string;\n cwd?: string;\n }\n ): void {\n const event: InteractionRequestEvent = {\n requestId: request.requestId,\n sessionId: request.sessionId,\n interactionType: 'permission',\n content: {\n title: `Permission Required: ${request.toolName}`,\n description: `${request.toolName} ${JSON.stringify(request.args)}`,\n permission: {\n riskLevel: 'medium',\n args: request.args,\n },\n },\n chatId: request.chatId,\n messageId: request.messageId,\n cwd: request.cwd,\n type: 'interaction:request',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限申请事件\n * Now filters interaction:request events for permission type\n */\n onPermissionRequest(handler: EventHandler<InteractionRequestEvent>): () => void {\n return this.on('interaction:request', (event: InteractionRequestEvent) => {\n if (event.interactionType === 'permission') {\n handler(event);\n }\n });\n }\n\n /**\n * @deprecated Use publishInteractionResponse instead\n * 发布权限决策事件 (backward compatibility - converts to interaction:response)\n */\n publishPermissionDecision(\n decision: {\n requestId: string;\n decision: 'allow' | 'deny' | 'always_allow';\n reason?: string;\n }\n ): void {\n const event: InteractionResponseEvent = {\n requestId: decision.requestId,\n response: {\n requestId: decision.requestId,\n action: decision.decision === 'always_allow' ? 'allow' : decision.decision,\n message: decision.reason,\n },\n reason: decision.reason,\n type: 'interaction:response',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限决策事件\n * Now subscribes to interaction:response\n */\n onPermissionDecision(handler: EventHandler<InteractionResponseEvent>): () => void {\n return this.on('interaction:response', handler);\n }\n\n /**\n * Publish interaction request event\n */\n publishInteractionRequest(\n request: Omit<InteractionRequestEvent, 'type' | 'timestamp'>\n ): void {\n const event: InteractionRequestEvent = {\n ...request,\n type: 'interaction:request',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * Subscribe to interaction request events\n */\n onInteractionRequest(\n handler: EventHandler<InteractionRequestEvent>\n ): () => void {\n return this.on('interaction:request', handler);\n }\n\n /**\n * Publish interaction response event\n */\n publishInteractionResponse(\n response: Omit<InteractionResponseEvent, 'type' | 'timestamp'>\n ): void {\n const event: InteractionResponseEvent = {\n ...response,\n type: 'interaction:response',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * Subscribe to interaction response events\n */\n onInteractionResponse(\n handler: EventHandler<InteractionResponseEvent>\n ): () => void {\n return this.on('interaction:response', handler);\n }\n\n /**\n * 发布 Session 开始事件\n */\n publishSessionStart(\n session: Omit<SessionStartEvent, 'type' | 'timestamp'>\n ): void {\n const event: SessionStartEvent = {\n ...session,\n type: 'session:start',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅 Session 开始事件\n */\n onSessionStart(handler: EventHandler<SessionStartEvent>): () => void {\n return this.on('session:start', handler);\n }\n\n /**\n * 发布 Session 结束事件\n */\n publishSessionEnd(\n session: Omit<SessionEndEvent, 'type' | 'timestamp'>\n ): void {\n const event: SessionEndEvent = {\n ...session,\n type: 'session:end',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅 Session 结束事件\n */\n onSessionEnd(handler: EventHandler<SessionEndEvent>): () => void {\n return this.on('session:end', handler);\n }\n\n publishToolPost(tool: Omit<ToolPostEvent, 'type' | 'timestamp'>): void {\n const event: ToolPostEvent = { ...tool, type: 'tool:post', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolPost(handler: EventHandler<ToolPostEvent>): () => void {\n return this.on('tool:post', handler);\n }\n\n publishToolFailure(tool: Omit<ToolFailureEvent, 'type' | 'timestamp'>): void {\n const event: ToolFailureEvent = { ...tool, type: 'tool:failure', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolFailure(handler: EventHandler<ToolFailureEvent>): () => void {\n return this.on('tool:failure', handler);\n }\n\n publishToolExecuted(tool: Omit<ToolExecutedEvent, 'type' | 'timestamp'>): void {\n const event: ToolExecutedEvent = { ...tool, type: 'tool:executed', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolExecuted(handler: EventHandler<ToolExecutedEvent>): () => void {\n return this.on('tool:executed', handler);\n }\n\n publishFinished(finished: Omit<FinishedEvent, 'type' | 'timestamp'>): void {\n const event: FinishedEvent = { ...finished, type: 'turn:finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onFinished(handler: EventHandler<FinishedEvent>): () => void {\n return this.on('turn:finished', handler);\n }\n\n publishTurnFinished(finished: Omit<TurnFinishedEvent, 'type' | 'timestamp'>): void {\n const event: TurnFinishedEvent = { ...finished, type: 'turn:finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onTurnFinished(handler: EventHandler<TurnFinishedEvent>): () => void {\n return this.on('turn:finished', handler);\n }\n\n publishTurnThinking(sessionId: string, thinking: string): void {\n // [Extension Point — Streaming Thinking]\n // Called once per turn with complete thinking (current), and once per chunk (streaming).\n // Consumers (NotificationHandler) treat both cases identically — no streaming logic needed here.\n // Streaming upgrade: call this more frequently with incremental content; no consumer changes required.\n const event: TurnThinkingEvent = { type: 'turn:thinking', sessionId, thinking, timestamp: new Date() };\n this.emit(event);\n }\n\n onTurnThinking(handler: EventHandler<TurnThinkingEvent>): () => void {\n return this.on('turn:thinking', handler);\n }\n\n /**\n * 发布命令事件\n */\n publishCommand(command: Omit<CommandEvent, 'type' | 'timestamp'>): void {\n const event: CommandEvent = {\n ...command,\n type: 'command',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅命令事件\n */\n onCommand(handler: EventHandler<CommandEvent>): () => void {\n return this.on('command', handler);\n }\n\n /**\n * 发布通知事件\n */\n publishNotification(\n notification: Omit<NotificationEvent, 'type' | 'timestamp'>\n ): void {\n const event: NotificationEvent = {\n ...notification,\n type: 'notification',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅通知事件\n */\n onNotification(handler: EventHandler<NotificationEvent>): () => void {\n return this.on('notification', handler);\n }\n\n /**\n * 移除所有监听器\n */\n removeAllListeners(): void {\n this.emitter.removeAllListeners();\n this.logger.debug('All event listeners removed');\n }\n\n /**\n * 获取监听器数量\n */\n listenerCount(eventType: AllBusEvents['type']): number {\n return this.emitter.listenerCount(eventType);\n }\n\n}\n\n/**\n * 创建 EventBus 实例\n */\nexport function createEventBus(): EventBus {\n return new EventBus();\n}\n\n// 导出所有类型\nexport * from './types.js';\nexport * from './events.js';\n","import type { Channel, ChannelConstructor } from './types.js';\n\n/**\n * Channel 注册表类(单例模式)\n * 用于管理所有 Channel 类的注册和发现\n */\nexport class ChannelRegistry {\n private static instance: ChannelRegistry | null = null;\n private registry: Map<string, ChannelConstructor> = new Map();\n\n /**\n * 私有构造函数,防止外部实例化\n */\n private constructor() {}\n\n /**\n * 获取 ChannelRegistry 单例实例\n * @returns ChannelRegistry 实例\n */\n static getInstance(): ChannelRegistry {\n if (!ChannelRegistry.instance) {\n ChannelRegistry.instance = new ChannelRegistry();\n }\n return ChannelRegistry.instance;\n }\n\n /**\n * 注册 Channel 类\n * @param name - Channel 唯一标识名\n * @param channelClass - Channel 构造函数\n */\n register(name: string, channelClass: ChannelConstructor): void {\n if (this.registry.has(name)) {\n console.warn(`Channel \"${name}\" is already registered, overwriting...`);\n }\n this.registry.set(name, channelClass);\n }\n\n /**\n * 获取已注册的 Channel 类\n * @param name - Channel 唯一标识名\n * @returns Channel 构造函数,如果不存在则返回 undefined\n */\n get(name: string): ChannelConstructor | undefined {\n return this.registry.get(name);\n }\n\n /**\n * 检查是否已注册指定 Channel\n * @param name - Channel 唯一标识名\n * @returns 是否已注册\n */\n has(name: string): boolean {\n return this.registry.has(name);\n }\n\n /**\n * 列出所有已注册的 Channel 名称\n * @returns Channel 名称数组\n */\n list(): string[] {\n return Array.from(this.registry.keys());\n }\n\n /**\n * 清空注册表(主要用于测试)\n */\n clear(): void {\n this.registry.clear();\n }\n\n /**\n * 重置单例实例(主要用于测试)\n */\n static resetInstance(): void {\n ChannelRegistry.instance = null;\n }\n}\n\n/**\n * Channel 装饰器\n * 用于自动注册 Channel 类到注册表\n *\n * 使用示例:\n * ```typescript\n * @Channel('telegram')\n * export class TelegramChannel extends BaseChannel {\n * // ...\n * }\n * ```\n *\n * @param name - Channel 唯一标识名\n * @returns 类装饰器函数\n */\nexport function Channel(name: string): ClassDecorator {\n return function <T extends Function>(target: T): T {\n const registry = ChannelRegistry.getInstance();\n registry.register(name, target as unknown as ChannelConstructor);\n return target;\n };\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { OutboundMessage } from '../bus/events.js';\nimport type { Button } from '../bus/types.js';\nimport type { Channel, ChannelConfig, ConnectionHealth } from './types.js';\nimport { ChannelRegistry } from './registry.js';\nimport { getLogger, createChannelLogger } from '../../shared/logger.js';\n\n/**\n * Channels 配置映射\n */\nexport interface ChannelsConfig {\n [channelName: string]: ChannelConfig;\n}\n\n/**\n * Channel 状态信息\n */\nexport interface ChannelStatus {\n name: string;\n displayName: string;\n isRunning: boolean;\n capabilities: {\n supportsButtons: boolean;\n supportsMarkdown: boolean;\n supportsImages: boolean;\n supportsStreaming: boolean;\n };\n}\n\n/**\n * Channel 连接状态信息\n */\nexport interface ChannelConnectionStatus {\n name: string;\n displayName: string;\n isRunning: boolean;\n connectionState: ConnectionHealth['state'];\n lastPingTime?: Date;\n reconnectCount: number;\n errorMessage?: string;\n}\n\n/**\n * ChannelManager\n * 统一管理所有 Channel 的生命周期和消息路由\n */\nexport class ChannelManager {\n /** EventBus 实例 */\n private bus: EventBus;\n\n /** 日志记录器 */\n private logger: Logger;\n\n /** 已创建的 Channel 实例映射 */\n private channels: Map<string, Channel> = new Map();\n\n /** 出站消息处理器取消函数 */\n private unsubscribeOutbound: (() => void) | null = null;\n\n /** 健康检查定时器 */\n private healthCheckTimer: NodeJS.Timeout | null = null;\n\n /** 健康检查间隔(毫秒) */\n private readonly HEALTH_CHECK_INTERVAL = 30000; // 30秒\n\n /**\n * 构造函数\n * @param bus - EventBus 实例\n * @param logger - 可选的日志记录器\n */\n constructor(bus: EventBus, logger?: Logger) {\n this.bus = bus;\n this.logger = logger || getLogger();\n this.logger.debug('ChannelManager initialized');\n }\n\n /**\n * 从配置初始化所有启用的 Channel\n * @param channelsConfig - Channel 配置映射\n */\n initializeFromConfig(channelsConfig: ChannelsConfig): void {\n const registry = ChannelRegistry.getInstance();\n\n for (const [name, config] of Object.entries(channelsConfig)) {\n if (!config.enabled) {\n this.logger.debug({ channel: name }, '[Channel] Disabled, skipping');\n continue;\n }\n\n const ChannelClass = registry.get(name);\n if (!ChannelClass) {\n this.logger.warn(\n { channel: name },\n '[Channel] Class not found in registry'\n );\n continue;\n }\n\n try {\n const channelLogger = createChannelLogger(name);\n const channel = new ChannelClass(config, this.bus, channelLogger);\n this.channels.set(name, channel);\n this.logger.info({ channel: name }, '[Channel] Initialized');\n } catch (error) {\n this.logger.error(\n { channel: name, error },\n 'Failed to initialize channel'\n );\n }\n }\n }\n\n /**\n * 启动所有 Channel(带重试机制)\n */\n async startAll(): Promise<void> {\n this.logger.info(\n { count: this.channels.size },\n '[Channel] Starting all'\n );\n\n // 启动所有 Channel\n for (const [name, channel] of this.channels) {\n await this.startChannelWithRetry(name, channel);\n }\n\n // 设置出站消息路由\n this.setupOutboundRouting();\n\n // 启动健康检查\n this.startHealthCheck();\n\n this.logger.info('[Channel] All started');\n }\n\n /**\n * 启动单个 Channel(带重试)\n */\n private async startChannelWithRetry(\n name: string,\n channel: Channel,\n maxRetries = 3\n ): Promise<void> {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n await channel.start();\n this.logger.debug({ channel: name }, '[Channel] Started');\n return;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(\n { channel: name, attempt, error: errorMessage },\n '[Channel] Start failed'\n );\n\n if (attempt === maxRetries) {\n this.logger.error({ channel: name }, '[Channel] Start failed after retries');\n return;\n }\n\n // 指数退避重试\n const delay = 1000 * Math.pow(2, attempt - 1);\n this.logger.debug({ channel: name, delay }, '[Channel] Retrying');\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n /**\n * 停止所有 Channel(优雅关闭)\n */\n async stopAll(): Promise<void> {\n this.logger.info(\n { count: this.channels.size },\n '[Channel] Stopping all'\n );\n\n // 停止健康检查\n this.stopHealthCheck();\n\n // 取消出站消息监听\n if (this.unsubscribeOutbound) {\n this.unsubscribeOutbound();\n this.unsubscribeOutbound = null;\n this.logger.debug('[Channel] Outbound routing stopped');\n }\n\n // 优雅关闭所有 Channel(带超时)\n const stopPromises = Array.from(this.channels.entries()).map(\n async ([name, channel]) => {\n try {\n // 5秒超时\n await Promise.race([\n channel.stop(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Stop timeout')), 5000)\n ),\n ]);\n this.logger.debug({ channel: name }, '[Channel] Stopped');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ channel: name, error: errorMessage }, '[Channel] Stop failed');\n }\n }\n );\n\n await Promise.all(stopPromises);\n this.logger.info('[Channel] All stopped');\n }\n\n /**\n * 启动健康检查定时器\n */\n private startHealthCheck(): void {\n this.healthCheckTimer = setInterval(() => {\n this.performHealthCheck();\n }, this.HEALTH_CHECK_INTERVAL);\n this.logger.debug('Health check started');\n }\n\n /**\n * 停止健康检查定时器\n */\n private stopHealthCheck(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = null;\n this.logger.debug('Health check stopped');\n }\n }\n\n /**\n * 执行健康检查\n */\n private performHealthCheck(): void {\n for (const [name, channel] of this.channels) {\n const health = channel.getConnectionHealth?.();\n if (health) {\n this.logger.debug(\n { channel: name, state: health.state, reconnectCount: health.reconnectCount },\n 'Health check'\n );\n\n // 告警:重连次数过多\n if (health.state === 'error' && health.reconnectCount > 5) {\n this.logger.warn(\n { channel: name, reconnectCount: health.reconnectCount },\n 'Channel connection unstable'\n );\n }\n }\n }\n }\n\n /**\n * 注册一个已初始化的 Channel\n * @param channel - Channel 实例\n */\n register(channel: Channel): void {\n const name = channel.name;\n if (this.channels.has(name)) {\n this.logger.warn({ channel: name }, '[Channel] Already registered, replacing');\n }\n this.channels.set(name, channel);\n this.logger.info({ channel: name }, '[Channel] Registered');\n }\n\n /**\n * 获取指定 Channel\n * @param name - Channel 名称\n * @returns Channel 实例,如果不存在则返回 undefined\n */\n getChannel(name: string): Channel | undefined {\n return this.channels.get(name);\n }\n\n /**\n * 获取所有 Channel 状态\n * @returns Channel 状态数组\n */\n getStatus(): ChannelStatus[] {\n const status: ChannelStatus[] = [];\n\n for (const channel of this.channels.values()) {\n status.push({\n name: channel.name,\n displayName: channel.displayName,\n isRunning: channel.isRunning,\n capabilities: {\n supportsButtons: channel.capabilities.supportsButtons,\n supportsMarkdown: channel.capabilities.supportsMarkdown,\n supportsImages: channel.capabilities.supportsImages,\n supportsStreaming: channel.capabilities.supportsStreaming,\n },\n });\n }\n\n return status;\n }\n\n /**\n * 获取所有 Channel 的连接状态\n */\n getConnectionStatus(): ChannelConnectionStatus[] {\n const status: ChannelConnectionStatus[] = [];\n\n for (const [name, channel] of this.channels) {\n const health = channel.getConnectionHealth?.() || {\n state: 'unknown' as const,\n reconnectCount: 0,\n };\n\n status.push({\n name: channel.name,\n displayName: channel.displayName,\n isRunning: channel.isRunning,\n connectionState: health.state,\n lastPingTime: health.lastPingTime,\n reconnectCount: health.reconnectCount,\n errorMessage: health.errorMessage,\n });\n }\n\n return status;\n }\n\n /**\n * 获取已启用的 Channel 数量\n */\n get count(): number {\n return this.channels.size;\n }\n\n /**\n * 设置出站消息路由\n * 监听 EventBus 的 outbound 事件,根据 channel 路由到对应的 Channel\n */\n private setupOutboundRouting(): void {\n this.unsubscribeOutbound = this.bus.onOutbound(\n async (event: OutboundMessage) => {\n // 从 event 中获取 channel 信息\n const channelName = (event as OutboundMessage & { channel?: string }).channel;\n const eventType = event.metadata?.eventType as string | undefined;\n const channelInstanceId = event.metadata?.channelInstanceId as string | undefined;\n const resolvedChatId = event.metadata?.resolvedChatId as string | undefined;\n const sessionId = event.metadata?.sessionId as string | undefined;\n\n if (!channelName) {\n this.logger.warn(\n { event },\n 'Outbound message missing channel field'\n );\n return;\n }\n\n // 广播到所有 Channel\n if (channelName === 'broadcast') {\n await this.broadcastMessage(event);\n return;\n }\n\n this.logger.debug(\n {\n channel: channelName,\n eventType,\n chatId: event.chatId,\n resolvedChatId,\n channelInstanceId,\n sessionId,\n },\n '[Channel] Routing outbound message'\n );\n\n // 单 Channel 路由\n await this.routeToChannel(channelName, event);\n }\n );\n\n this.logger.debug('Outbound message routing setup complete');\n }\n\n /**\n * 广播消息到所有 Channel\n * 每个 Channel 会根据 shouldNotify() 决定是否处理\n */\n private async broadcastMessage(event: OutboundMessage): Promise<void> {\n const eventType = event.metadata?.eventType as string;\n\n this.logger.debug(\n { eventType, channelCount: this.channels.size },\n '[Channel] Broadcasting'\n );\n\n for (const [name, channel] of this.channels) {\n // Channel 自己决定是否处理\n if (!channel.shouldNotify(eventType)) {\n continue;\n }\n\n if (!channel.isRunning) {\n continue;\n }\n\n try {\n await channel.send(event);\n this.logger.debug(\n {\n channel: name,\n eventType,\n chatId: event.chatId,\n resolvedChatId: event.metadata?.resolvedChatId,\n sessionId: event.metadata?.sessionId,\n },\n '[Channel] Sent'\n );\n } catch (error) {\n this.logger.error({ channel: name, error: error instanceof Error ? error.message : String(error) }, '[Channel] Send failed');\n }\n }\n }\n\n /**\n * 路由消息到指定 Channel\n * 增加对流式消息的特殊处理\n */\n private async routeToChannel(\n channelName: string,\n event: OutboundMessage\n ): Promise<void> {\n const channel = this.channels.get(channelName);\n if (!channel) {\n this.logger.warn({ channel: channelName }, 'Channel not found');\n return;\n }\n\n if (!channel.isRunning) {\n this.logger.warn({ channel: channelName }, 'Channel is not running');\n return;\n }\n\n try {\n // 检查是否为流式消息(_streamDelta 标记)\n const isDelta = event.metadata?._streamDelta === true;\n const hasSendDelta = typeof channel.sendDelta === 'function';\n\n // 流式消息:使用 sendDelta\n if (isDelta && channel.supportsStreaming && hasSendDelta && channel.sendDelta) {\n await channel.sendDelta(\n event.chatId,\n event.text || '',\n {\n _streamId: event.metadata?._streamId as string | undefined,\n _streamEnd: event.metadata?._streamEnd as boolean | undefined,\n }\n );\n this.logger.debug(\n { channel: channelName, streamId: event.metadata?._streamId },\n 'Stream delta sent'\n );\n return;\n }\n\n // 普通消息:检查是否包含按钮且 Channel 支持按钮\n const buttons = (event as OutboundMessage & { buttons?: Button[][] }).buttons;\n if (\n buttons &&\n Array.isArray(buttons) &&\n buttons.length > 0 &&\n channel.capabilities.supportsButtons\n ) {\n await channel.sendWithButtons(event, buttons);\n this.logger.debug({ channel: channelName, hasButtons: true }, 'Message sent with buttons');\n } else {\n await channel.send(event);\n this.logger.debug(\n {\n channel: channelName,\n chatId: event.chatId,\n resolvedChatId: event.metadata?.resolvedChatId,\n eventType: event.metadata?.eventType,\n sessionId: event.metadata?.sessionId,\n },\n 'Message sent'\n );\n }\n } catch (error) {\n this.logger.error({ channel: channelName, error }, 'Failed to send message');\n }\n }\n}\n\n/**\n * 创建 ChannelManager 实例\n * @param bus - EventBus 实例\n * @param logger - 可选的日志记录器\n * @returns ChannelManager 实例\n */\nexport function createChannelManager(\n bus: EventBus,\n logger?: Logger\n): ChannelManager {\n return new ChannelManager(bus, logger);\n}\n","import type { Logger } from 'pino';\nimport { getLogger } from '../../shared/logger.js';\nimport { loadConfig, type BindingsConfig } from '../../config.js';\nimport { writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\n\nexport type AgentType = 'claude' | 'codex';\n\nexport class BindingService {\n private logger: Logger;\n /** Cache the config to avoid repeated disk reads. Refreshed on each bind/unbind since we write to disk. */\n private cachedConfig: ReturnType<typeof loadConfig> | null = null;\n\n constructor(logger?: Logger) {\n this.logger = logger ?? getLogger();\n }\n\n private getConfig() {\n if (!this.cachedConfig) {\n this.cachedConfig = loadConfig();\n }\n return this.cachedConfig;\n }\n\n /** Invalidate cache after writes so the next read picks up fresh data. */\n private invalidateCache(): void {\n this.cachedConfig = null;\n }\n\n /**\n * Get the current bindings config.\n */\n getBindings(): BindingsConfig {\n const config = this.getConfig();\n const bindings = config.bindings;\n // Return undefined when bindings is not present (not set in config)\n if (!bindings || Object.keys(bindings).length === 0) {\n return {};\n }\n return bindings;\n }\n\n /**\n * Get the channel instance ID that a given agent is bound to.\n */\n getBoundChannel(agent: AgentType): string | undefined {\n return this.getBindings()[agent];\n }\n\n /**\n * Get the agent bound to a given channel instance ID.\n */\n getBoundAgent(channelInstanceId: string): AgentType | undefined {\n const bindings = this.getBindings();\n for (const [agent, channelId] of Object.entries(bindings)) {\n if (channelId === channelInstanceId) {\n return agent as AgentType;\n }\n }\n return undefined;\n }\n\n /**\n * Bind an agent to a channel instance.\n * If the agent is already bound to another channel, it will be migrated.\n * If the target channel is already bound to another agent, that binding is replaced.\n * Returns the old channel instance ID that the agent was bound to (if any).\n */\n bindAgent(agent: AgentType, channelInstanceId: string): string | undefined {\n // Validate format: must be \"type:hash\"\n if (!channelInstanceId.includes(':')) {\n this.logger.error({ channelInstanceId }, '[Binding] Invalid channel instance ID format');\n return undefined;\n }\n\n const config = this.getConfig();\n const bindings = { ...(config.bindings ?? {}) } as Record<string, string | undefined>;\n const oldChannelId = bindings[agent];\n\n // Remove any existing binding where this channel was bound (swap/migration case)\n for (const [a, cid] of Object.entries(bindings)) {\n if (cid === channelInstanceId && a !== agent) {\n this.logger.debug({ agent: a, oldChannel: cid }, '[Binding] Removing conflicting binding');\n delete bindings[a];\n }\n }\n\n bindings[agent] = channelInstanceId;\n this.saveBindings(bindings as BindingsConfig);\n\n return oldChannelId;\n }\n\n /**\n * Unbind an agent from its current channel.\n * Returns the old channel instance ID (if any).\n */\n unbindAgent(agent: AgentType): string | undefined {\n const config = this.getConfig();\n const bindings = { ...(config.bindings ?? {}) };\n const oldChannelId = bindings[agent];\n\n if (!oldChannelId) {\n return undefined;\n }\n\n delete bindings[agent];\n this.saveBindings(bindings);\n\n this.logger.info({ agent, oldChannelId }, '[Binding] Agent unbound');\n return oldChannelId;\n }\n\n /**\n * Check if an agent is configured (i.e., can be bound).\n * An agent is configurable if it has a non-empty config entry.\n */\n isAgentConfigurable(agent: AgentType): boolean {\n const config = this.getConfig();\n if (agent === 'claude') {\n return !!config.agent.claude;\n }\n if (agent === 'codex') {\n return config.agent.codex?.enabled === true;\n }\n return false;\n }\n\n private saveBindings(bindings: BindingsConfig): void {\n const config = this.getConfig();\n const merged = {\n ...config,\n bindings,\n };\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n writeFileSync(configPath, TOML.stringify(merged as unknown as Parameters<typeof TOML.stringify>[0]));\n this.invalidateCache();\n }\n}","export const COMMAND_ROOT_SUBCOMMAND = '__root__';\n\nexport const SYSTEM_COMMAND_ROOTS = new Set([\n 'start',\n 'help',\n 'status',\n 'ping',\n 'bind',\n 'unbind',\n 'new',\n 'clear',\n 'stop',\n 'session',\n 'system',\n]);\n\nexport function getSlashCommandRoot(text: string): string | null {\n const trimmed = text.trim();\n if (!trimmed.startsWith('/')) {\n return null;\n }\n\n const withoutSlash = trimmed.slice(1);\n if (!withoutSlash) {\n return null;\n }\n\n const firstToken = withoutSlash.split(/\\s+/, 1)[0] ?? '';\n const root = firstToken.split(':', 1)[0] ?? '';\n return root.toLowerCase() || null;\n}\n\nexport function isSystemCommandText(text: string): boolean {\n const root = getSlashCommandRoot(text);\n return !!root && SYSTEM_COMMAND_ROOTS.has(root);\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { InboundMessage } from '../bus/events.js';\nimport { BindingService } from '../binding/index.js';\nimport { getLogger } from '../../shared/logger.js';\nimport {\n getSlashCommandRoot,\n isSystemCommandText,\n} from '../command/routing.js';\n\n/**\n * InboundRouter\n *\n * 统一处理 channel 入站消息:\n * 1. 系统命令标记为 systemCommand,由 CommandHandler 执行\n * 2. agent 显式命令(如 /codex help)标记为 agentCommand,转给绑定 agent\n * 3. 普通文本默认转发给当前 channel 绑定的 agent\n */\nexport class InboundRouter {\n private readonly bus: EventBus;\n private readonly bindingService: BindingService;\n private readonly logger: Logger;\n private unsubscribe: (() => void) | null = null;\n\n constructor(bus: EventBus, logger?: Logger) {\n this.bus = bus;\n this.bindingService = new BindingService(logger);\n this.logger = logger ?? getLogger();\n }\n\n start(): void {\n if (this.unsubscribe) {\n this.logger.warn('InboundRouter already started');\n return;\n }\n\n this.unsubscribe = this.bus.onInbound(this.handleInbound.bind(this));\n this.logger.info('InboundRouter started');\n }\n\n stop(): void {\n if (!this.unsubscribe) {\n return;\n }\n\n this.unsubscribe();\n this.unsubscribe = null;\n this.logger.info('InboundRouter stopped');\n }\n\n private handleInbound(message: InboundMessage): void {\n if (message.targetAgent || message.systemCommand) {\n return;\n }\n\n const boundAgent = this.bindingService.getBoundAgent(message.channelInstanceId);\n const commandRoot = getSlashCommandRoot(message.text);\n\n if (isSystemCommandText(message.text)) {\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n commandRoot,\n },\n '[InboundRouter] Routed inbound message to system command handler'\n );\n this.bus.publishInbound({\n ...message,\n systemCommand: true,\n });\n return;\n }\n\n if (!boundAgent) {\n if (commandRoot) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'No agent is bound to this channel. Run /bind <agent> first.',\n replyToMessageId: message.messageId,\n });\n } else {\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n },\n '[InboundRouter] Dropping plain text because no agent is bound'\n );\n }\n return;\n }\n\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n targetAgent: boundAgent,\n commandRoot,\n },\n '[InboundRouter] Routed inbound message to bound agent'\n );\n this.bus.publishInbound({\n ...message,\n targetAgent: boundAgent,\n agentCommand: false,\n });\n }\n\n}\n","import { COMMAND_ROOT_SUBCOMMAND } from './routing.js';\n\n/**\n * Parsed command structure\n */\nexport interface ParsedCommand {\n /** Main command */\n command: string;\n /** Subcommand */\n subcommand: string;\n /** Argument list */\n args: string[];\n}\n\n/**\n * Command parser\n * Parses command strings in various formats\n */\nexport class CommandParser {\n /**\n * Check if content is a command (starts with /)\n * @param content - Content to check\n * @returns true if content is a command\n */\n isCommand(content: string): boolean {\n if (!content || typeof content !== 'string') {\n return false;\n }\n return content.trim().startsWith('/');\n }\n\n /**\n * Parse command content\n * Supports formats:\n * - /command subcommand arg1 arg2\n * - /command:subcommand arg1 arg2\n * - /command (root command)\n * @param content - Content to parse\n * @returns ParsedCommand or null if not a command\n */\n parse(content: string): ParsedCommand | null {\n if (!this.isCommand(content)) {\n return null;\n }\n\n const trimmed = content.trim();\n\n // Remove the leading '/' and split by whitespace\n const withoutSlash = trimmed.slice(1);\n\n // Check for /command:subcommand format\n const colonIndex = withoutSlash.indexOf(':');\n const spaceIndex = withoutSlash.indexOf(' ');\n\n let command: string;\n let subcommand: string;\n let argsString: string;\n\n if (colonIndex !== -1 && (spaceIndex === -1 || colonIndex < spaceIndex)) {\n // Format: /command:subcommand arg1 arg2\n command = withoutSlash.slice(0, colonIndex);\n const afterColon = withoutSlash.slice(colonIndex + 1);\n const firstSpaceAfterColon = afterColon.indexOf(' ');\n\n if (firstSpaceAfterColon === -1) {\n // No args: /command:subcommand\n subcommand = afterColon;\n argsString = '';\n } else {\n subcommand = afterColon.slice(0, firstSpaceAfterColon);\n argsString = afterColon.slice(firstSpaceAfterColon + 1);\n }\n } else {\n // Format: /command subcommand arg1 arg2\n const parts = withoutSlash.split(/\\s+/);\n command = parts[0];\n\n if (parts.length === 1) {\n // Only command: /command\n subcommand = COMMAND_ROOT_SUBCOMMAND;\n argsString = '';\n } else {\n subcommand = parts[1];\n argsString = parts.slice(2).join(' ');\n }\n }\n\n // Parse arguments, handling multiple spaces\n const args = argsString\n .trim()\n .split(/\\s+/)\n .filter(arg => arg.length > 0);\n\n return {\n command,\n subcommand,\n args,\n };\n }\n}\n\n/**\n * Global command parser instance\n */\nexport const commandParser = new CommandParser();\n","import type { Logger } from 'pino';\nimport { CommandRegistry } from './index.js';\nimport { CommandParser, ParsedCommand } from './parser.js';\nimport { CommandContext } from './types.js';\nimport { getLogger } from '../../shared/logger.js';\nimport { COMMAND_ROOT_SUBCOMMAND } from './routing.js';\n\n/**\n * Command executor\n * Parses and executes commands using the registry\n */\nexport class CommandExecutor {\n private parser: CommandParser;\n private registry: CommandRegistry;\n private logger: Logger;\n\n /**\n * Create a command executor\n * @param registry - Command registry for looking up handlers\n * @param logger - Optional logger instance\n */\n constructor(registry: CommandRegistry, logger?: Logger) {\n this.parser = new CommandParser();\n this.registry = registry;\n this.logger = logger ?? getLogger();\n }\n\n /**\n * Check if content is a command\n * @param content - Content to check\n * @returns true if content is a command\n */\n isCommand(content: string): boolean {\n return this.parser.isCommand(content);\n }\n\n /**\n * Execute a command\n * @param content - Command content to execute\n * @param context - Command execution context\n * @returns Command result string, or null if not a command\n */\n async execute(\n content: string,\n context: CommandContext\n ): Promise<string | null> {\n // Parse the command\n const parsed = this.parser.parse(content);\n if (!parsed) {\n return null;\n }\n\n this.logger.debug(\n { command: parsed.command, subcommand: parsed.subcommand, args: parsed.args },\n 'Executing command'\n );\n\n // Look up the handler\n const handler = this.registry.get(parsed.command, parsed.subcommand);\n\n if (!handler) {\n // Command not found - provide helpful message\n if (this.registry.hasGroup(parsed.command)) {\n // Group exists but subcommand doesn't\n const availableSubcommands = Object.keys(\n this.registry.getGroup(parsed.command) ?? {}\n )\n .filter((name) => name !== COMMAND_ROOT_SUBCOMMAND)\n .join(', ');\n\n if (parsed.subcommand === COMMAND_ROOT_SUBCOMMAND) {\n return `/${parsed.command} needs a subcommand. Available: ${availableSubcommands || 'none'}`;\n }\n\n return `Unknown subcommand \"${parsed.subcommand}\" for /${parsed.command}. Available: ${availableSubcommands || 'none'}`;\n }\n // Group doesn't exist\n const availableGroups = this.registry.getGroups();\n if (availableGroups.length === 0) {\n return `Unknown command /${parsed.command}. No commands are currently registered.`;\n }\n return `Unknown command /${parsed.command}. Available commands: ${availableGroups.join(', ')}`;\n }\n\n // Execute the handler\n try {\n const result = await handler.handler(parsed.args, context);\n return result;\n } catch (error) {\n this.logger.error(\n {\n command: parsed.command,\n subcommand: parsed.subcommand,\n error: error instanceof Error ? error.message : String(error),\n },\n 'Command execution failed'\n );\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n return `Error executing /${parsed.command} ${parsed.subcommand}: ${errorMessage}`;\n }\n }\n\n /**\n * Get the parsed command without executing\n * @param content - Content to parse\n * @returns ParsedCommand or null\n */\n parse(content: string): ParsedCommand | null {\n return this.parser.parse(content);\n }\n}\n","import { CommandHandler } from '../types.js';\nimport { BindingService, type AgentType } from '../../binding/index.js';\nimport { getLogger } from '../../../shared/logger.js';\n\nconst bindingService = new BindingService();\n\nexport const bindCommand: CommandHandler = {\n description: 'Bind this channel to an agent',\n usage: '/bind <claude|codex>',\n\n async handler(args: string[], context) {\n const logger = getLogger();\n const [agentArg] = args;\n\n if (!agentArg) {\n return 'Usage: /bind <claude|codex>';\n }\n\n const agent = agentArg as AgentType;\n if (agent !== 'claude' && agent !== 'codex') {\n return `Unknown agent \"${agentArg}\". Available: claude, codex`;\n }\n\n if (!bindingService.isAgentConfigurable(agent)) {\n return `\"${agent}\" is not configured and cannot be bound. Run the wizard first.`;\n }\n\n const instanceId = context.source.channelInstanceId;\n const oldChannelId = bindingService.bindAgent(agent, instanceId);\n logger.info({ agent, channelInstanceId: instanceId, oldChannelId }, '[bind] Binding changed');\n\n if (oldChannelId && oldChannelId !== instanceId) {\n return `${agent} has been moved from ${oldChannelId} to this channel (${instanceId}).`;\n }\n\n return `${agent} is now bound to this channel (${instanceId}).`;\n },\n};\n\nexport const unbindCommand: CommandHandler = {\n description: 'Unbind the current channel from its agent',\n usage: '/unbind',\n\n async handler() {\n return 'Use /unbind <agent> to remove a binding explicitly.';\n },\n};\n\nexport const unbindAgentCommand: CommandHandler = {\n description: 'Unbind an agent from its current channel',\n usage: '/unbind <claude|codex>',\n\n async handler(args: string[], context) {\n const logger = getLogger();\n const [agentArg] = args;\n\n if (agentArg) {\n if (agentArg !== 'claude' && agentArg !== 'codex') {\n return `Unknown agent \"${agentArg}\". Available: claude, codex`;\n }\n\n const oldChannelId = bindingService.unbindAgent(agentArg);\n if (!oldChannelId) {\n return `${agentArg} is not currently bound.`;\n }\n\n logger.info({ agent: agentArg, oldChannelId }, '[unbind] Agent unbound');\n return `${agentArg} has been unbound from ${oldChannelId}.`;\n }\n\n const currentAgent = bindingService.getBoundAgent(context.source.channelInstanceId);\n if (!currentAgent) {\n return 'No agent is bound to this channel.';\n }\n\n const oldChannelId = bindingService.unbindAgent(currentAgent);\n logger.info({ agent: currentAgent, oldChannelId }, '[unbind] Agent unbound');\n return `${currentAgent} has been unbound from this channel.`;\n },\n};\n","import { CommandHandler } from '../types.js';\n\nexport const helpCommand: CommandHandler = {\n description: 'Show system and agent command help',\n usage: '/help',\n handler: async (): Promise<string> => {\n return [\n '**Command Model**',\n '',\n '**Core System Commands**',\n '- `/start` show the quick-start message',\n '- `/help` show this help',\n '- `/status` show Handsoff runtime status',\n '- `/bind <agent>` bind this channel to an agent',\n '- `/unbind` remove the current binding',\n '- `/new` start fresh for this chat',\n '- `/clear` clear the current chat session',\n '- `/stop` stop the current chat session',\n '- `/session` inspect the current chat session',\n '',\n 'Plain text and any non-system commands are forwarded to the bound agent.',\n ].join('\\n');\n },\n};\n\nexport function registerHelpCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('help', 'help', helpCommand);\n}\n","import { CommandContext, CommandGroup, CommandHandler } from '../types.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { BindingService } from '../../binding/index.js';\nimport type { AgentType, SessionInfo } from '../../../core/adapter/types.js';\n\nconst bindingService = new BindingService();\n\nfunction formatDuration(start: Date, end?: Date): string {\n const endTime = end ?? new Date();\n const diff = endTime.getTime() - start.getTime();\n\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;\n if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n\nfunction getBoundAgentContext(context: CommandContext): {\n agentType?: AgentType;\n sessionId?: string;\n session?: ReturnType<CommandContext['sessionManager']['getSession']>;\n} {\n const agentType = bindingService.getBoundAgent(context.source.channelInstanceId);\n if (!agentType) {\n return {};\n }\n\n const sessionId = `${agentType}-${context.source.chatId}`;\n return {\n agentType,\n sessionId,\n session: context.sessionManager.getSession(sessionId),\n };\n}\n\nconst listHandler: CommandHandler = {\n description: 'List active sessions',\n usage: '/session list [--agent <type>] [--all]',\n handler: async (args: string[]): Promise<string> => {\n let agentFilter: string | undefined;\n let includeEnded = false;\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--agent' && i + 1 < args.length) {\n agentFilter = args[i + 1];\n i++;\n } else if (args[i] === '--all') {\n includeEnded = true;\n }\n }\n\n const registry = SessionScannerRegistry.getInstance();\n let sessions: SessionInfo[] = agentFilter\n ? await registry.scanByAgent(agentFilter as AgentType)\n : await registry.scanAll();\n\n if (!includeEnded) {\n sessions = sessions.filter((s) => s.status === 'active');\n }\n\n if (sessions.length === 0) {\n return includeEnded ? 'No sessions found.' : 'No active sessions.';\n }\n\n const byAgent = new Map<string, SessionInfo[]>();\n for (const session of sessions) {\n const list = byAgent.get(session.agentType) ?? [];\n list.push(session);\n byAgent.set(session.agentType, list);\n }\n\n const lines: string[] = [includeEnded ? '**All Sessions**' : '**Active Sessions**', ''];\n for (const [agentType, agentSessions] of byAgent) {\n lines.push(`**${agentType}** (${agentSessions.length})`);\n for (const session of agentSessions) {\n lines.push(`- \\`${session.id}\\` (${session.status}, ${formatDuration(session.startedAt)})`);\n }\n lines.push('');\n }\n\n return lines.join('\\n').trim();\n },\n};\n\nconst statusHandler: CommandHandler = {\n description: 'Show details for a specific session',\n usage: '/session status <session-id>',\n handler: async (args: string[]): Promise<string> => {\n const sessionId = args[0];\n if (!sessionId) {\n return 'Usage: /session status <session-id>';\n }\n\n const registry = SessionScannerRegistry.getInstance();\n const session = (await registry.scanAll()).find((entry) => entry.id === sessionId);\n if (!session) {\n return `Session \\`${sessionId}\\` not found.`;\n }\n\n const lines = [\n `**Session ${session.id}**`,\n '',\n `Agent: ${session.agentType}`,\n `Transport: ${session.transportType}`,\n `Status: ${session.status}`,\n `Started: ${session.startedAt.toISOString()}`,\n `Duration: ${formatDuration(session.startedAt)}`,\n ];\n\n if (session.cwd) {\n lines.push(`Workdir: \\`${session.cwd}\\``);\n }\n\n return lines.join('\\n');\n },\n};\n\nconst countHandler: CommandHandler = {\n description: 'Show session counts',\n usage: '/session count',\n handler: async (_args, context): Promise<string> => {\n const allSessions = context.sessionManager.listSessions();\n const active = allSessions.filter((s) => s.status === 'active');\n const closed = allSessions.filter((s) => s.status !== 'active');\n\n return [\n '**Session Statistics**',\n '',\n `Active: ${active.length}`,\n `Closed: ${closed.length}`,\n `Total: ${allSessions.length}`,\n ].join('\\n');\n },\n};\n\nexport const sessionRootCommand: CommandHandler = {\n description: 'Show the current chat session for the bound agent',\n usage: '/session',\n handler: async (_args, context): Promise<string> => {\n const bound = getBoundAgentContext(context);\n if (!bound.agentType) {\n return 'No agent is bound to this channel.';\n }\n\n if (!bound.session || bound.session.getStatus() !== 'active') {\n if (bound.agentType === 'claude') {\n return 'This channel is bound to Claude. Claude sessions are started from the local Claude Code client, so use `/claude status` to inspect hook state and active Claude sessions.';\n }\n return `This channel is bound to ${bound.agentType}, but there is no active session for this chat yet. Send a message to start one.`;\n }\n\n const lines = [\n '**Current Session**',\n '',\n `Agent: ${bound.agentType}`,\n `Session ID: \\`${bound.sessionId}\\``,\n `Status: ${bound.session.getStatus()}`,\n `Started: ${new Date(bound.session.createdAt).toISOString()}`,\n ];\n\n if (bound.session.cwd) {\n lines.push(`CWD: \\`${bound.session.cwd}\\``);\n }\n\n return lines.join('\\n');\n },\n};\n\nasync function resetCurrentSession(context: CommandContext): Promise<string> {\n const bound = getBoundAgentContext(context);\n if (!bound.agentType) {\n return 'No agent is bound to this channel.';\n }\n\n if (bound.agentType === 'claude') {\n return 'Claude sessions are managed by the local Claude Code client. Stop or restart Claude locally, then use this channel for approvals and notifications.';\n }\n\n if (!bound.session || bound.session.getStatus() !== 'active') {\n return `No active ${bound.agentType} session for this chat. The next message will start a fresh session.`;\n }\n\n await context.sessionManager.closeSession(bound.session.id);\n return `Closed the active ${bound.agentType} session. The next message will start a fresh session.`;\n}\n\nexport const clearCommand: CommandHandler = {\n description: 'Clear the current chat session',\n usage: '/clear',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const newCommand: CommandHandler = {\n description: 'Start fresh for the current chat',\n usage: '/new',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const stopCommand: CommandHandler = {\n description: 'Stop the current chat session',\n usage: '/stop',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const sessionCommands: CommandGroup = {\n list: listHandler,\n status: statusHandler,\n count: countHandler,\n};\n\nexport function registerSessionCommands(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n for (const [subcommand, handler] of Object.entries(sessionCommands)) {\n registerFn('session', subcommand, handler);\n }\n}\n","import { CommandHandler } from '../types.js';\nimport { BindingService } from '../../binding/index.js';\n\nconst bindingService = new BindingService();\n\nexport const startCommand: CommandHandler = {\n description: 'Show the quick-start guide for this channel',\n usage: '/start',\n handler: async (_args, context): Promise<string> => {\n const boundAgent = bindingService.getBoundAgent(context.source.channelInstanceId);\n\n return [\n '**Handsoff**',\n '',\n boundAgent\n ? `This channel is currently bound to **${boundAgent}**.`\n : 'This channel is not bound to an agent yet.',\n '',\n '**How to use it**',\n '- Send plain text to talk to the bound agent.',\n '- Use `/new` or `/clear` to start fresh in this chat.',\n '- Use `/session` to inspect the current chat session.',\n '- Use `/help` to see system commands.',\n ].join('\\n');\n },\n};\n\nexport function registerStartCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('start', 'start', startCommand);\n}\n","import { CommandGroup, CommandHandler } from '../types.js';\nimport process from 'process';\nimport os from 'os';\n\nconst systemStartTime = Date.now();\n\nfunction formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(2)} ${units[unitIndex]}`;\n}\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours % 24}h`);\n if (minutes > 0) parts.push(`${minutes % 60}m`);\n if (seconds > 0 || parts.length === 0) parts.push(`${seconds % 60}s`);\n return parts.join(' ');\n}\n\nexport const statusCommand: CommandHandler = {\n description: 'Show Handsoff runtime status',\n usage: '/status',\n handler: async (): Promise<string> => {\n const uptime = Date.now() - systemStartTime;\n const memoryUsage = process.memoryUsage();\n const totalMem = os.totalmem();\n const freeMem = os.freemem();\n const cpus = os.cpus();\n\n return [\n '**Handsoff Status**',\n '',\n `Uptime: ${formatDuration(uptime)}`,\n `Sessions: runtime process alive`,\n '',\n '**Runtime**',\n `Node.js: ${process.version}`,\n `Platform: ${process.platform} (${process.arch})`,\n '',\n '**Memory**',\n `RSS: ${formatBytes(memoryUsage.rss)}`,\n `Heap: ${formatBytes(memoryUsage.heapUsed)} / ${formatBytes(memoryUsage.heapTotal)}`,\n `System free: ${formatBytes(freeMem)} / ${formatBytes(totalMem)}`,\n '',\n '**CPU**',\n `Model: ${cpus[0]?.model ?? 'Unknown'}`,\n `Cores: ${cpus.length}`,\n `Load avg: ${os.loadavg().map((value) => value.toFixed(2)).join(', ')}`,\n ].join('\\n');\n },\n};\n\nexport const pingCommand: CommandHandler = {\n description: 'Check whether the gateway is responsive',\n usage: '/ping',\n handler: async (): Promise<string> => 'Pong. Handsoff is running.',\n};\n\nexport const systemCommands: CommandGroup = {\n status: statusCommand,\n ping: pingCommand,\n};\n\nexport function registerSystemCommands(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n for (const [subcommand, handler] of Object.entries(systemCommands)) {\n registerFn('system', subcommand, handler);\n }\n}\n","import { CommandRegistry } from '../index.js';\nimport { bindCommand, unbindAgentCommand } from './bind.js';\nimport { helpCommand } from './help.js';\nimport {\n clearCommand,\n newCommand,\n registerSessionCommands,\n sessionRootCommand,\n stopCommand,\n} from './session.js';\nimport { startCommand } from './start.js';\nimport { pingCommand, registerSystemCommands, statusCommand } from './system.js';\nimport { COMMAND_ROOT_SUBCOMMAND } from '../routing.js';\n\nexport { bindCommand, unbindCommand, unbindAgentCommand } from './bind.js';\nexport { helpCommand, registerHelpCommand } from './help.js';\nexport {\n clearCommand,\n newCommand,\n registerSessionCommands,\n sessionCommands,\n sessionRootCommand,\n stopCommand,\n} from './session.js';\nexport { startCommand, registerStartCommand } from './start.js';\nexport { pingCommand, registerSystemCommands, statusCommand, systemCommands } from './system.js';\n\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n registry.register('start', COMMAND_ROOT_SUBCOMMAND, startCommand);\n registry.register('help', COMMAND_ROOT_SUBCOMMAND, helpCommand);\n registry.register('status', COMMAND_ROOT_SUBCOMMAND, statusCommand);\n registry.register('ping', COMMAND_ROOT_SUBCOMMAND, pingCommand);\n registry.register('bind', COMMAND_ROOT_SUBCOMMAND, bindCommand);\n registry.register('unbind', COMMAND_ROOT_SUBCOMMAND, unbindAgentCommand);\n registry.register('new', COMMAND_ROOT_SUBCOMMAND, newCommand);\n registry.register('clear', COMMAND_ROOT_SUBCOMMAND, clearCommand);\n registry.register('stop', COMMAND_ROOT_SUBCOMMAND, stopCommand);\n registry.register('session', COMMAND_ROOT_SUBCOMMAND, sessionRootCommand);\n\n registerSessionCommands((group, subcommand, handler) => {\n registry.register(group, subcommand, handler);\n });\n\n registerSystemCommands((group, subcommand, handler) => {\n registry.register(group, subcommand, handler);\n });\n}\n","import { getLogger } from '../../shared/logger.js';\nimport {\n CommandContext,\n CommandHandler,\n CommandGroup,\n CommandHandlerFunction,\n} from './types.js';\n\n/**\n * 命令注册表\n * 管理所有可用命令的注册和检索\n */\nexport class CommandRegistry {\n private commands = new Map<string, Map<string, CommandHandler>>();\n private logger = getLogger();\n\n /**\n * 注册单个命令\n * @param group - 命令组名称(如 'session')\n * @param subcommand - 子命令名称(如 'list')\n * @param handler - 命令处理器\n */\n register(\n group: string,\n subcommand: string,\n handler: CommandHandler\n ): void {\n if (!this.commands.has(group)) {\n this.commands.set(group, new Map());\n }\n const groupMap = this.commands.get(group)!;\n groupMap.set(subcommand, handler);\n this.logger.debug(\n { group, subcommand },\n 'Command registered'\n );\n }\n\n /**\n * 批量注册命令组\n * @param group - 命令组名称\n * @param handlers - 命令组(包含多个子命令)\n */\n registerGroup(group: string, handlers: CommandGroup): void {\n for (const [subcommand, handler] of Object.entries(handlers)) {\n this.register(group, subcommand, handler);\n }\n }\n\n /**\n * 获取命令处理器\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理器,如果不存在则返回 undefined\n */\n get(group: string, subcommand: string): CommandHandler | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n return groupMap.get(subcommand);\n }\n\n /**\n * 获取命令处理函数(便捷方法)\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理函数,如果不存在则返回 undefined\n */\n getHandler(group: string, subcommand: string): CommandHandlerFunction | undefined {\n return this.get(group, subcommand)?.handler;\n }\n\n /**\n * 检查命令是否存在\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否存在\n */\n has(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n return groupMap.has(subcommand);\n }\n\n /**\n * 检查命令组是否存在\n * @param group - 命令组名称\n * @returns 是否存在\n */\n hasGroup(group: string): boolean {\n return this.commands.has(group);\n }\n\n /**\n * 列出所有命令\n * @returns 所有命令的列表,格式为 { group, subcommand, description, usage }\n */\n list(): Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> {\n const result: Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> = [];\n\n for (const [group, groupMap] of this.commands.entries()) {\n for (const [subcommand, handler] of groupMap.entries()) {\n result.push({\n group,\n subcommand,\n description: handler.description,\n usage: handler.usage,\n });\n }\n }\n\n // 按组名和子命令名排序\n result.sort((a, b) => {\n if (a.group !== b.group) {\n return a.group.localeCompare(b.group);\n }\n return a.subcommand.localeCompare(b.subcommand);\n });\n\n return result;\n }\n\n /**\n * 获取命令组中的所有子命令\n * @param group - 命令组名称\n * @returns 命令组,如果不存在则返回 undefined\n */\n getGroup(group: string): CommandGroup | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n const result: CommandGroup = {};\n for (const [subcommand, handler] of groupMap.entries()) {\n result[subcommand] = handler;\n }\n return result;\n }\n\n /**\n * 获取所有命令组名称\n * @returns 命令组名称列表\n */\n getGroups(): string[] {\n return Array.from(this.commands.keys()).sort();\n }\n\n /**\n * 注销单个命令\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否成功注销\n */\n unregister(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n const result = groupMap.delete(subcommand);\n if (result) {\n this.logger.debug({ group, subcommand }, 'Command unregistered');\n }\n // 如果组为空,删除组\n if (groupMap.size === 0) {\n this.commands.delete(group);\n }\n return result;\n }\n\n /**\n * 清空所有命令\n */\n clear(): void {\n this.commands.clear();\n this.logger.debug('All commands cleared');\n }\n}\n\n/**\n * 全局命令注册表单例\n */\nexport const commandRegistry = new CommandRegistry();\n\n// 导出类型\nexport * from './types.js';\n\n// 导出命令执行器\nexport { CommandExecutor } from './executor.js';\n\n// 导出内置命令注册函数\nexport { registerBuiltinCommands } from './builtin/index.js';\n","import type { Logger } from 'pino';\nimport { EventBus } from '../../core/bus/index.js';\nimport type { SessionManager } from '../../core/session/SessionManager.js';\nimport {\n registerBuiltinCommands,\n commandRegistry,\n CommandExecutor,\n} from '../../core/command/index.js';\nimport type { InboundMessage } from '../../core/bus/events.js';\n\n/**\n * Setup command handler to process only system commands.\n *\n * InboundRouter is responsible for classifying inbound messages and republishing\n * system commands with `systemCommand: true`.\n */\nexport function setupCommandHandler(\n bus: EventBus,\n sessionManager: SessionManager,\n logger: Logger\n): () => void {\n registerBuiltinCommands(commandRegistry);\n logger.debug('Builtin commands registered');\n\n const executor = new CommandExecutor(commandRegistry, logger);\n\n return bus.onInbound(async (message: InboundMessage) => {\n if (!message.systemCommand) {\n return;\n }\n\n const result = await executor.execute(message.text, {\n source: message,\n bus,\n sessionManager,\n });\n\n if (result === null) {\n logger.warn(\n {\n text: message.text,\n textPreview: message.text.slice(0, 120),\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n },\n '[Command] Routed as system command but no handler was found'\n );\n return;\n }\n\n bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: result,\n replyToMessageId: message.messageId,\n });\n\n logger.info(\n {\n command: message.text.slice(0, 80),\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n },\n '[Command] Executed system command'\n );\n });\n}\n","import type { Logger } from 'pino';\nimport { EventBus } from '../../core/bus/index.js';\nimport { InteractionQueue } from '../../adapters/interaction/queue.js';\nimport { InteractionResponseEvent } from '../../core/bus/events.js';\n\n/**\n * Setup permission handler to route decisions to InteractionQueue\n * @param bus - EventBus instance\n * @param interactionQueue - Interaction queue for managing permission requests\n * @param logger - Logger instance\n * @returns Cleanup function to remove event listeners\n */\nexport function setupPermissionHandler(\n bus: EventBus,\n interactionQueue: InteractionQueue,\n logger: Logger\n): () => void {\n // Subscribe to interaction response events\n const unsubscribe = bus.onInteractionResponse((event: InteractionResponseEvent) => {\n const { requestId, response, reason } = event;\n\n logger.debug(\n { requestId, action: response.action, reason },\n 'Processing interaction response'\n );\n\n // Apply response to queue\n const success = interactionQueue.respond(requestId, response);\n\n if (success) {\n logger.debug(\n { requestId, action: response.action },\n 'Interaction response applied'\n );\n } else {\n logger.warn(\n { requestId },\n 'Interaction response failed: request not found or already responded'\n );\n }\n });\n\n logger.debug('Permission handler setup complete');\n\n // Return cleanup function\n return unsubscribe;\n}\n","import { setupCommandHandler } from './command.js';\nimport { setupPermissionHandler } from './permission.js';\n\nexport { setupCommandHandler, setupPermissionHandler };\n\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../core/bus/index.js';\nimport type { SessionManager } from '../../core/session/SessionManager.js';\nimport type { InteractionQueue } from '../../adapters/interaction/index.js';\nimport type { Gateway } from '../index.js';\n\n/**\n * Setup all gateway handlers\n */\nexport function setupAllHandlers(\n bus: EventBus,\n gateway: Gateway,\n interactionQueue: InteractionQueue,\n logger: Logger\n): () => void {\n const cleanupFns: Array<() => void> = [];\n\n cleanupFns.push(setupCommandHandler(bus, gateway.getSessionManager(), logger));\n cleanupFns.push(setupPermissionHandler(bus, interactionQueue, logger));\n\n return () => {\n for (const fn of cleanupFns) {\n fn();\n }\n };\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../core/bus/index.js';\nimport { BindingService } from '../core/binding/index.js';\nimport type {\n SessionStartEvent,\n SessionEndEvent,\n ToolFailureEvent,\n InteractionRequestEvent,\n TurnFinishedEvent,\n ToolExecutedEvent,\n TurnThinkingEvent,\n ToolPostEvent,\n} from '../core/bus/events.js';\nimport type { NotificationContext } from './notification-context.js';\n\n/**\n * NotificationHandler 将 Gateway 事件转换为 OutboundMessage\n *\n * 职责:\n * 1. 监听 Gateway 事件 (session_start, session_end, permission_request, finished, tool_failure)\n * 2. 构建 NotificationContext\n * 3. 广播原始上下文到 EventBus\n * 4. 各 Channel 自行格式化\n */\nexport class NotificationHandler {\n private unsubscribeFns: Array<() => void> = [];\n private sessionAgentMap = new Map<string, 'claude' | 'codex'>();\n constructor(\n private bus: EventBus,\n private logger: Logger,\n private getSessionAgentType?: (sessionId: string) => 'claude' | 'codex' | undefined,\n private bindingService?: BindingService,\n ) {\n // Lazy instantiation if not provided (for backward compatibility)\n if (!this.bindingService) {\n this.bindingService = new BindingService(logger);\n }\n }\n\n /**\n * 启动监听\n */\n start(): void {\n if (this.unsubscribeFns.length > 0) {\n this.logger.warn('NotificationHandler already started');\n return;\n }\n this.unsubscribeFns.push(\n this.bus.onTurnFinished(this.handleTurnFinished.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolPost(this.handleToolPost.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolExecuted(this.handleToolExecuted.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onTurnThinking(this.handleTurnThinking.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionStart(this.handleSessionStart.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionEnd(this.handleSessionEnd.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolFailure(this.handleToolFailure.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionRequest(this.handleInteractionRequest.bind(this))\n );\n\n this.logger.info('NotificationHandler started');\n }\n\n /**\n * 停止监听\n */\n stop(): void {\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n this.logger.info('NotificationHandler stopped');\n }\n\n private async handleSessionStart(event: SessionStartEvent): Promise<void> {\n if (event.agentType) {\n this.sessionAgentMap.set(event.sessionId, event.agentType);\n }\n\n this.logger.debug({ sessionId: event.sessionId, cwd: event.cwd }, '[NotificationHandler] handleSessionStart');\n\n const context: NotificationContext = {\n eventType: 'session:start',\n sessionId: event.sessionId,\n agentType: event.agentType,\n userId: event.userId,\n chatId: event.chatId,\n cwd: event.cwd,\n };\n\n await this.publishContext(context);\n }\n\n private async handleSessionEnd(event: SessionEndEvent): Promise<void> {\n this.sessionAgentMap.delete(event.sessionId);\n await this.publishContext({\n eventType: 'session:end',\n sessionId: event.sessionId,\n userId: event.userId,\n chatId: event.chatId,\n reason: event.reason,\n });\n }\n\n private async handleInteractionRequest(event: InteractionRequestEvent): Promise<void> {\n // Map interaction type to event type\n const eventType = event.interactionType === 'permission'\n ? 'permission:request'\n : 'question:request';\n\n // Safely extract toolName from title\n const toolName = event.content.title?.replace(/^Permission Required: /, '') ?? '';\n\n const interaction = {\n type: eventType === 'permission:request' ? 'permission' as const : 'question' as const,\n requestId: event.requestId,\n toolName,\n title: event.content.title,\n description: event.content.description,\n permission: event.content.permission ? {\n riskLevel: event.content.permission.riskLevel,\n args: event.content.permission.args,\n } : undefined,\n question: event.content.question ? {\n question: event.content.question.text,\n header: event.content.question.header,\n options: event.content.question.options?.map(o => ({\n id: o.id,\n label: o.label,\n value: o.value,\n description: o.description,\n })) ?? [],\n multiSelect: event.content.question.multiSelect,\n } : undefined,\n };\n\n const context: NotificationContext = eventType === 'permission:request'\n ? {\n eventType: 'permission:request',\n sessionId: event.sessionId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction,\n }\n : {\n eventType: 'question:request',\n sessionId: event.sessionId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction,\n };\n\n await this.publishContext(context);\n }\n\n private async handleToolFailure(event: ToolFailureEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:failure',\n sessionId: event.sessionId,\n toolName: event.toolName,\n toolInput: event.toolInput,\n error: event.error,\n });\n }\n\n /**\n * [Streaming Extension] Currently emits one event per turn (complete thinking).\n * For streaming: called multiple times per turn with incremental chunks.\n * publishContext and Feishu formatter handle both cases identically — no changes needed here.\n */\n private async handleTurnThinking(event: TurnThinkingEvent): Promise<void> {\n await this.publishContext({\n eventType: 'turn:thinking',\n sessionId: event.sessionId,\n thinking: event.thinking,\n });\n }\n\n private async handleTurnFinished(event: TurnFinishedEvent): Promise<void> {\n this.logger.debug({ sessionId: event.sessionId, cwd: event.cwd }, '[NotificationHandler] handleTurnFinished');\n\n const context: NotificationContext = {\n eventType: 'turn:finished',\n sessionId: event.sessionId,\n agentType: event.agentType,\n userId: event.userId,\n chatId: event.chatId,\n cwd: event.cwd,\n reason: event.reason,\n lastAssistantMessage: event.lastAssistantMessage,\n thinking: event.thinking,\n durationMs: event.durationMs,\n usage: event.usage,\n summary: event.usage || event.durationMs\n ? {\n durationMs: event.durationMs,\n inputTokens: event.usage?.inputTokens,\n outputTokens: event.usage?.outputTokens,\n }\n : undefined,\n };\n\n await this.publishContext(context);\n }\n\n private async handleToolPost(event: ToolPostEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:post',\n sessionId: event.sessionId,\n toolCallId: event.toolCallId || '',\n toolName: event.toolName,\n toolInput: event.toolInput,\n });\n }\n\n private async handleToolExecuted(event: ToolExecutedEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:executed',\n sessionId: event.sessionId,\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n summary: event.summary,\n toolInput: event.toolInput as Record<string, unknown> | undefined,\n output: event.output,\n isTimeout: event.isTimeout,\n });\n }\n\n private async publishContext(context: NotificationContext): Promise<void> {\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId: context.sessionId,\n chatId: context.chatId,\n },\n 'Publishing notification'\n );\n\n const sessionId = context.sessionId;\n\n // If sessionId is missing, fall back to broadcast (backward compat)\n if (!sessionId) {\n await this.publishBroadcast(context);\n return;\n }\n\n const agentType = this.sessionAgentMap.get(sessionId)\n ?? this.getAgentTypeFromSession(sessionId)\n ?? this.getSessionAgentType?.(sessionId);\n\n if (!agentType) {\n // Fall back to broadcast if we can't determine agent\n this.logger.warn({ sessionId }, '[NotificationHandler] No agent type for session, broadcasting');\n await this.publishBroadcast(context);\n return;\n }\n\n const channelInstanceId = this.bindingService!.getBoundChannel(agentType);\n\n if (!channelInstanceId) {\n this.logger.debug({ agentType, sessionId }, '[NotificationHandler] No binding for agent, dropping event');\n return; // No channel bound to this agent — drop the event silently\n }\n\n // Parse \"telegram:abc123\" → channelType\n const channelType = channelInstanceId.split(':')[0];\n\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId,\n agentType,\n channelInstanceId,\n channelType,\n },\n '[NotificationHandler] Routing notification to bound channel'\n );\n\n await this.bus.publishOutbound({\n channel: channelType,\n chatId: sessionId,\n context,\n metadata: {\n eventType: context.eventType,\n channelInstanceId,\n sessionId,\n },\n });\n }\n\n private async publishBroadcast(context: NotificationContext): Promise<void> {\n await this.bus.publishOutbound({\n channel: 'broadcast',\n chatId: 'broadcast',\n context,\n metadata: { eventType: context.eventType },\n });\n }\n\n private getAgentTypeFromSession(sessionId: string): 'claude' | 'codex' | undefined {\n if (typeof sessionId !== 'string' || !sessionId) {\n return undefined;\n }\n // Session IDs for codex are prefixed \"codex-\"\n if (sessionId.startsWith('codex-')) {\n return 'codex';\n }\n if (sessionId.startsWith('claude-')) {\n return 'claude';\n }\n // For Claude sessions without prefix, check via sessionManager if available\n // Default to 'claude' for unknown sessions (backward compat)\n return undefined;\n }\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { Button } from '../bus/types.js';\nimport type { OutboundMessage } from '../bus/events.js';\nimport type { Channel, ChannelCapabilities, ChannelConfig, ConnectionHealth } from './types.js';\nimport type { NotificationContext } from '../../gateway/notification-context.js';\n\n/**\n * Channel 配置扩展接口\n */\nexport interface ExtendedChannelConfig extends ChannelConfig {\n // 权限控制由具体 Channel 实现自行管理\n}\n\n/**\n * Channel 抽象基类\n * 封装通用逻辑,具体 Channel 实现需要继承此类\n */\nexport abstract class BaseChannel implements Channel {\n /** Channel 唯一标识名 */\n abstract readonly name: string;\n\n /** Channel 显示名称 */\n abstract readonly displayName: string;\n\n /** Channel 能力声明 */\n abstract readonly capabilities: ChannelCapabilities;\n\n /** Channel 实例 ID,用于 1:1 绑定路由 */\n abstract readonly channelInstanceId: string;\n\n /**\n * 是否支持流式消息输出\n * 子类可覆盖此属性声明支持流式\n * 参考 nanobot BaseChannel.supports_streaming\n */\n readonly supportsStreaming: boolean = false;\n\n /** Channel 运行状态 */\n private _isRunning: boolean = false;\n\n /** Channel 配置 */\n protected config: ExtendedChannelConfig;\n\n /** 事件总线 */\n protected bus: EventBus;\n\n /** 日志记录器 */\n protected logger: Logger;\n\n /**\n * 连接健康状态\n * 子类需要维护自己的连接状态\n */\n protected connectionHealth: ConnectionHealth = {\n state: 'unknown',\n reconnectCount: 0,\n };\n\n /**\n * 获取连接健康状态\n */\n getConnectionHealth(): ConnectionHealth {\n return { ...this.connectionHealth };\n }\n\n /**\n * 更新连接状态(子类调用)\n * @param state - 新状态\n * @param errorMessage - 错误信息(可选)\n */\n protected updateConnectionState(\n state: ConnectionHealth['state'],\n errorMessage?: string\n ): void {\n this.connectionHealth.state = state;\n this.connectionHealth.lastPingTime = new Date();\n if (errorMessage) {\n this.connectionHealth.errorMessage = errorMessage;\n }\n if (state === 'connected') {\n this.connectionHealth.reconnectCount = 0;\n }\n this.logger.debug(\n { channel: this.name, state, errorMessage },\n 'Connection state updated'\n );\n }\n\n /**\n * 记录重连(子类调用)\n */\n protected recordReconnectAttempt(): void {\n this.connectionHealth.reconnectCount++;\n this.logger.debug(\n { channel: this.name, attempt: this.connectionHealth.reconnectCount },\n 'Reconnect attempt recorded'\n );\n }\n\n /**\n * 获取 Channel 运行状态\n */\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n /**\n * 流式消息发送\n * 用于打字机效果的逐字/逐句输出\n * 默认空实现,支持流式的子类应覆盖此方法\n * 参考 nanobot base.py send_delta\n *\n * @param chatId - 聊天ID\n * @param delta - 新增的文本片段\n * @param metadata - 可选元数据,包含 _streamId 和 _streamEnd\n */\n async sendDelta(\n chatId: string,\n delta: string,\n metadata?: {\n _streamId?: string;\n _streamEnd?: boolean;\n }\n ): Promise<void> {\n // 默认空实现,子类选择性覆盖\n }\n\n /**\n * 构造函数\n * @param config - Channel 配置\n * @param bus - 事件总线实例\n * @param logger - 日志记录器\n */\n constructor(config: ExtendedChannelConfig, bus: EventBus, logger: Logger) {\n this.config = config;\n this.bus = bus;\n this.logger = logger;\n }\n\n /**\n * 启动 Channel\n * 子类应该重写此方法并在 super.start() 后添加自定义逻辑\n */\n async start(): Promise<void> {\n this.logger.info({ channel: this.name }, 'Starting channel');\n this._isRunning = true;\n }\n\n /**\n * 停止 Channel\n * 子类应该重写此方法并在 super.stop() 后添加自定义逻辑\n */\n async stop(): Promise<void> {\n this.logger.info({ channel: this.name }, 'Stopping channel');\n this._isRunning = false;\n }\n\n /**\n * 发送消息\n * 子类必须实现此方法\n * @param message - 出站消息\n */\n abstract send(message: OutboundMessage): Promise<void>;\n\n /**\n * 发送带按钮的消息\n * 默认实现会忽略按钮,仅发送文本\n * 支持按钮的 Channel 应该重写此方法\n * @param message - 出站消息\n * @param buttons - 按钮二维数组\n */\n async sendWithButtons(message: OutboundMessage, buttons: Button[][]): Promise<void> {\n this.logger.debug(\n { channel: this.name, buttonRows: buttons.length },\n 'Buttons not supported, sending text only'\n );\n // 默认实现忽略按钮,只发送文本\n await this.send(message);\n }\n\n /**\n * 接收消息并转发到 EventBus\n * 子类在收到外部消息时应该调用此方法\n * @param chatId - 聊天ID\n * @param messageId - 消息ID\n * @param text - 消息文本\n * @param sender - 发送者信息\n */\n protected receiveMessage(\n chatId: string,\n messageId: string,\n text: string,\n sender: {\n id: string;\n username?: string;\n firstName?: string;\n lastName?: string;\n }\n ): void {\n // 检查发送者权限\n if (!this.isAllowed(sender.id)) {\n this.logger.warn(\n { channel: this.name, senderId: sender.id, chatId },\n 'Message from unauthorized sender ignored'\n );\n return;\n }\n\n this.logger.debug(\n {\n channel: this.name,\n channelInstanceId: this.channelInstanceId,\n chatId,\n messageId,\n senderId: sender.id,\n textPreview: text.slice(0, 120),\n },\n 'Receiving message and forwarding to bus'\n );\n\n // 转发到 EventBus\n this.bus.publishInbound({\n channel: this.name,\n channelInstanceId: this.channelInstanceId,\n chatId,\n messageId,\n text,\n sender,\n });\n }\n\n /**\n * 检查发送者是否有权限\n * 具体权限控制逻辑由子类实现\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected abstract isAllowed(senderId: string): boolean;\n\n /**\n * 检查是否应该处理某类通知\n * @param eventType - 事件类型 (session_start, session_end, permission_request, finished, error)\n * @returns 是否应该处理\n */\n shouldNotify(eventType: string): boolean {\n const notify_types = this.config.notify_types;\n\n // 未配置 notify_types 则不接收任何通知\n if (!notify_types || notify_types.length === 0) {\n return false;\n }\n\n // \"*\" 表示接收所有通知\n if (notify_types.includes('*')) {\n return true;\n }\n\n return notify_types.includes(eventType);\n }\n\n /**\n * 格式化通知上下文为 Channel 特定格式\n * 默认实现返回纯文本,子类可覆写以支持 HTML、Post 等格式\n * @param context - 通知上下文\n * @returns 格式化后的内容(字符串或特定类型)\n */\n format(context: NotificationContext): string | unknown {\n const lines: string[] = [];\n\n switch (context.eventType) {\n case 'permission:request':\n lines.push('🔐 Permission Request');\n lines.push(`Session: ${context.sessionId}`);\n if (context.toolName) {\n lines.push(`Tool: ${context.toolName}`);\n }\n if (context.toolInput && Object.keys(context.toolInput as Record<string, unknown> || {}).length > 0) {\n lines.push('');\n lines.push('Args:');\n lines.push(JSON.stringify(context.toolInput, null, 2));\n }\n break;\n\n case 'turn:finished':\n lines.push('✅ Task Completed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.durationMs !== undefined) {\n const seconds = (context.durationMs / 1000).toFixed(1);\n lines.push(`Duration: ${seconds}s`);\n }\n if (context.usage?.inputTokens !== undefined && context.usage?.outputTokens !== undefined) {\n lines.push(`Tokens: in ${context.usage.inputTokens} / out ${context.usage.outputTokens}`);\n }\n if (context.lastAssistantMessage) {\n lines.push('');\n lines.push('Result:');\n lines.push(context.lastAssistantMessage);\n }\n break;\n\n case 'session:start':\n lines.push('🟢 Session Started');\n lines.push(`Session: ${context.sessionId}`);\n if (context.userId) {\n lines.push(`User: ${context.userId.slice(0, 16)}`);\n }\n break;\n\n case 'session:end':\n lines.push('🔴 Session Ended');\n lines.push(`Session: ${context.sessionId}`);\n break;\n\n case 'tool:failure':\n lines.push('⚠️ Tool Failed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.toolName) {\n lines.push(`Tool: ${context.toolName}`);\n }\n if (context.error) {\n lines.push(`Error: ${context.error}`);\n }\n break;\n\n case 'question:request':\n lines.push('❓ Question');\n lines.push(`Session: ${context.sessionId}`);\n if (context.interaction?.question) {\n const q = context.interaction.question;\n if (q.header) {\n lines.push(`Header: ${q.header}`);\n }\n lines.push(`Question: ${q.question}`);\n if (q.options && q.options.length > 0) {\n lines.push('');\n lines.push('Options:');\n q.options.forEach((opt: { label: string; description?: string }, idx: number) => {\n lines.push(` ${idx + 1}. ${opt.label}${opt.description ? ` - ${opt.description}` : ''}`);\n });\n }\n }\n break;\n\n default:\n lines.push(`Event: ${(context as NotificationContext).eventType}`);\n lines.push(`Session: ${context.sessionId}`);\n }\n\n return lines.join('\\n');\n }\n}\n","import { Bot, type Context, type Api } from 'grammy';\nimport type { Logger } from 'pino';\n\n/**\n * 发送消息选项\n */\nexport interface SendMessageOptions {\n /** 解析模式 */\n parseMode?: 'Markdown' | 'MarkdownV2' | 'HTML';\n /** 回复消息ID */\n replyToMessageId?: number;\n /** 内联键盘 */\n replyMarkup?: {\n inline_keyboard: Array<\n Array<{\n text: string;\n callback_data: string;\n }>\n >;\n };\n}\n\n/**\n * Telegram Bot 包装类\n * 封装 grammy Bot 实例,提供重试机制和错误处理\n */\nexport class TelegramBot {\n /** grammy Bot 实例 */\n readonly bot: Bot;\n\n private logger: Logger;\n private isRunning: boolean = false;\n\n /**\n * 构造函数\n * @param token - Telegram Bot Token\n * @param logger - 日志记录器\n */\n constructor(token: string, logger: Logger) {\n this.bot = new Bot(token);\n this.logger = logger;\n\n // 设置错误处理\n this.bot.catch((err) => {\n this.logger.error({ error: err }, 'Telegram bot unhandled error');\n });\n }\n\n /**\n * 启动 Bot(带重试机制)\n * @param maxAttempts - 最大重试次数,默认 3\n * @param initialIntervalMs - 初始重试间隔(毫秒),默认 1000\n * @param startTimeoutMs - 启动超时时间(毫秒),默认 5000\n */\n async start(\n maxAttempts: number = 3,\n initialIntervalMs: number = 1000,\n startTimeoutMs: number = 5000\n ): Promise<void> {\n if (this.isRunning) {\n this.logger.warn('Bot is already running');\n return;\n }\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await this.startWithTimeout(startTimeoutMs);\n this.isRunning = true;\n this.logger.info('Telegram bot started successfully');\n return;\n } catch (error) {\n if (attempt === maxAttempts) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(\n { attempts: maxAttempts, error: errorMessage },\n 'Telegram bot failed to start after all attempts'\n );\n throw new Error(`Failed to start Telegram bot after ${maxAttempts} attempts: ${errorMessage}`);\n }\n const interval = initialIntervalMs * Math.pow(2, attempt - 1);\n this.logger.warn(\n { attempt, nextRetryIn: interval },\n `Telegram bot start attempt ${attempt} failed, retrying...`\n );\n await this.sleep(interval);\n }\n }\n }\n\n /**\n * 停止 Bot\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n this.logger.warn('Bot is not running');\n return;\n }\n\n try {\n await this.bot.stop();\n this.isRunning = false;\n this.logger.info('Telegram bot stopped');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ error: errorMessage }, 'Error stopping Telegram bot');\n throw error;\n }\n }\n\n /**\n * 发送消息\n * @param chatId - 聊天 ID\n * @param text - 消息文本\n * @param options - 发送选项\n */\n async sendMessage(\n chatId: string | number,\n text: string,\n options?: SendMessageOptions\n ): Promise<{ message_id: number }> {\n try {\n const result = await this.bot.api.sendMessage(chatId, text, {\n parse_mode: options?.parseMode,\n reply_to_message_id: options?.replyToMessageId,\n reply_markup: options?.replyMarkup,\n });\n this.logger.debug({ chatId }, 'Message sent successfully');\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ chatId, error: errorMessage }, 'Failed to send message');\n throw error;\n }\n }\n\n /**\n * 获取 grammy Bot 实例\n * 用于注册事件处理器\n */\n get instance(): Bot {\n return this.bot;\n }\n\n /**\n * 获取 Bot API\n */\n get api(): Api {\n return this.bot.api;\n }\n\n /**\n * 获取 Bot 运行状态\n */\n get running(): boolean {\n return this.isRunning;\n }\n\n /**\n * 注册回调查询处理器\n * @param handler - 处理器函数\n */\n onCallbackQuery(handler: (ctx: Context) => Promise<void>): void {\n this.bot.on('callback_query:data', handler);\n }\n\n /**\n * 注册文本消息处理器\n * @param handler - 处理器函数\n */\n onTextMessage(handler: (ctx: Context) => Promise<void>): void {\n this.bot.on('message:text', handler);\n }\n\n /**\n * 带超时启动 Bot\n * @param timeoutMs - 超时时间(毫秒)\n */\n private async startWithTimeout(timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Bot start timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.bot\n .start()\n .then(() => {\n clearTimeout(timeout);\n resolve();\n })\n .catch((error) => {\n clearTimeout(timeout);\n reject(error);\n });\n });\n }\n\n /**\n * 睡眠指定时间\n * @param ms - 毫秒\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","// src/i18n/index.ts\nimport './types.js';\nimport i18next from 'i18next';\nimport en from './locales/en.js';\n\nconst lng = process.env.HANDSOFF_LANG ?? 'en';\n\ni18next.init({\n initImmediate: false,\n lng,\n fallbackLng: 'en',\n resources: { en: { translation: en } },\n interpolation: { escapeValue: false },\n});\n\nexport const t = i18next.t.bind(i18next);\n","// src/i18n/locales/en.ts\nexport default {\n wizard: {\n section: {\n cli: '[ CLI Configuration ]',\n channel: '[ Channel Configuration ]',\n complete: '[ Setup Complete ]',\n },\n cli: {\n runAgain: 'Run init again when Claude Code is installed.',\n detected: 'Claude Code detected.',\n hooksInstalled: 'Hooks already installed.',\n hooksNotInstalled: 'Hooks not installed.',\n hooksTokenMismatch: 'Hooks have outdated token - reconfiguration required.',\n actionQuestion: 'Select action:',\n injectAction: 'Inject hooks configuration',\n updateAction: 'Update hooks configuration',\n backAction: 'Back',\n hookCheckbox: 'Select hooks:',\n noHooksSelected: 'No hooks selected, skipping injection.',\n injecting: 'Injecting hooks...',\n injected: 'Hooks injected',\n failed: 'Failed: {{error}}',\n remoteModeSkipHooks: 'Remote mode does not require hooks; skipping injection.',\n cleaningHooks: 'Cleaning up hooks from previous mode...',\n hooksCleaned: 'Hooks cleaned',\n cleanupWarning: 'Hook cleanup warning: {{error}}',\n },\n channel: {\n configuring: 'Configuring {{channel}}',\n telegram: {\n botToken: 'Telegram bot token:',\n allowedUsers: 'Allowed Telegram user IDs (comma-separated):',\n testing: 'Testing Telegram connection...',\n connected: 'Connected to Telegram',\n sendingTest: 'Sending test message...',\n testSent: 'Test message sent',\n testContent: 'Handsoff test message',\n testWarning: 'Could not send test message (user may not have messaged bot yet)',\n apiError: 'API error: {{status}}',\n connFailed: 'Connection failed: {{error}}',\n },\n feishu: {\n appId: 'Feishu App ID:',\n appSecret: 'Feishu App Secret:',\n allowedUsers: 'Allowed User IDs (comma-separated, e.g., ou_xxx,oc_xxx):',\n required: 'app_id and app_secret are required. Skipping.',\n },\n },\n codex: {\n enable: 'Enable Codex agent integration?',\n command: 'Codex app-server command:',\n workDir: 'Default Codex working directory (optional):',\n model: 'Default Codex model (optional):',\n approvalPolicy: 'Default Codex approval policy (optional):',\n detected: 'Codex CLI detected.',\n notDetected: 'Codex CLI not found in PATH.',\n enabled: 'Codex integration enabled.',\n disabled: 'Codex integration disabled.',\n },\n notify: {\n title: 'Notification types for {{channel}}',\n checkbox: 'Notification types:',\n saved: 'Notification types saved for {{channel}}',\n },\n menu: {\n select: 'Select:',\n next: '--- Next ---',\n testFailed: 'Test failed. Action:',\n retry: 'Retry',\n reenter: 'Re-enter',\n backToMenu: 'Back to menu',\n restartQuestion: 'Restart Gateway now?',\n },\n final: {\n noItems: 'No items configured.',\n itemOk: '{{item}}: OK',\n running: 'Gateway is running',\n runningChanges: 'Gateway is running with pending changes',\n configModified: 'Configuration was modified. Restart required to apply changes.',\n runningReady: 'Gateway is already running and ready.',\n notRunning: 'Gateway is not running',\n configModifiedStart: 'Configuration was modified. Starting Gateway with new configuration.',\n restarting: 'Restarting...',\n restarted: 'Gateway restarted with new configuration',\n starting: 'Starting...',\n started: 'Gateway started',\n startFailed: 'Failed: {{error}}',\n restartTip: 'Run `handsoff gateway start` to restart.',\n startTip: 'Run `handsoff gateway start` to start.',\n done: 'Done.',\n },\n },\n\n gateway: {\n stopping: 'Stopping daemon...',\n startedOnPort: 'Gateway started on port {{port}}',\n stopped: 'Daemon stopped',\n notRunning: 'Daemon is not running',\n restartedOnPort: 'Gateway restarted on port {{port}}',\n startFailed: 'Failed to start Gateway',\n stopFailed: 'Failed to stop Gateway',\n restartFailed: 'Failed to restart Gateway',\n error: ' Error: {{error}}',\n checkLogs: 'Check logs at: {{path}}',\n status: {\n title: 'Gateway Status:',\n running: 'Running: {{value}}',\n sessions: 'Sessions: {{count}}',\n clients: 'Connected clients: {{count}}',\n activeSessions: 'Active sessions:',\n notResponding: 'Gateway is not responding',\n notRunning: 'Gateway is not running',\n },\n },\n\n daemon: {\n alreadyRunning: 'Daemon is already running',\n startedOnPort: 'Daemon started on port {{port}}',\n startFailed: 'Daemon failed to start. Check logs for details.',\n checkLogs: 'Check logs at: {{path}}',\n portInUse: 'Warning: Port {{port}} still in use after {{ms}}ms',\n startError: 'Failed to start daemon: {{error}}',\n lackingToken: 'Daemon is running but PID file lacks token, restarting...',\n scriptNotFound: 'Daemon script not found: {{path}}',\n },\n\n status: {\n title: '=== Handsoff Status ===',\n daemon: {\n running: 'Daemon: ✓ Running',\n notRunning: 'Daemon: ✗ Not running',\n },\n port: 'Port: {{port}}',\n logLevel: 'Log Level: {{level}}',\n channels: 'Channels:',\n telegram: {\n enabled: 'Telegram: ✓ Enabled',\n disabled: 'Telegram: ✗ Disabled',\n },\n feishu: {\n enabled: 'Feishu: ✓ Enabled',\n disabled: 'Feishu: ✗ Disabled',\n },\n settingsBackup: 'Settings: ✓ Backup exists',\n settingsNoBackup: 'Settings: ✗ No backup',\n paths: 'Paths:',\n pathConfig: 'Config: {{path}}',\n pathLogs: 'Logs: {{path}}',\n pathBackup: 'Backup: {{path}}',\n },\n\n cli: {\n init: {\n configExists: 'Configuration exists. Continue?',\n cancelled: 'Cancelled.',\n },\n stop: {\n notRunning: 'Handsoff daemon is not running',\n stopping: 'Stopping handsoff daemon...',\n stopped: 'Daemon stopped successfully',\n failed: 'Failed to stop daemon cleanly',\n },\n attach: {\n checking: 'Checking Gateway status...',\n running: 'Gateway is running',\n notRunning: 'Gateway is not running. Start it with: handsoff gateway start',\n tokenNotFound: 'Hook token not found. Please run \"handsoff init\" first.',\n attached: 'Successfully attached {{agent}} to Gateway',\n start: 'Start \"claude\" to begin a session.',\n usingToken: 'Using hook token: {{token}}',\n settingsBacked: 'Claude settings backed up to: {{path}}',\n configuringHooks: 'Configuring hooks in Claude settings...',\n connected: 'Your Claude Code is now connected to handsoff Gateway.',\n forwarding: 'Events will be forwarded to connected clients.',\n tipStatus: 'Use \"handsoff gateway status\" to check status',\n tipDetach: 'Use \"handsoff detach\" to remove hooks and restore settings',\n },\n agent: {\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n tokenNotFound: 'Failed to get token from daemon',\n hooksConfigured: 'Claude hooks configured',\n startingIn: 'Starting Claude Code in {{dir}}...',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n configuring: 'Configuring Claude Code...',\n settingsBacked: 'Claude settings backed up',\n exited: '\\nClaude Code exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n tipStop: 'Use \"handsoff stop\" to stop the daemon and restore settings',\n detaching: '\\nDetaching from Claude...',\n },\n codex: {\n notInstalled: 'Codex CLI is not installed',\n installMethods: 'Please install Codex CLI using one of these methods:',\n option1npm: 'Option 1 - npm (recommended): npm install -g @openai/codex',\n option2brew: 'Option 2 - Homebrew (macOS): brew install --cask codex',\n alternative: 'Alternatively, use Claude Code: handsoff claude',\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n notEnabled: 'Codex adapter is not enabled in handsoff config.',\n enableHint: 'Enable it with \"handsoff init\" or by setting agent.codex.enabled = true in ~/.handsoff/config.toml, then restart the daemon.',\n startingIn: 'Starting Codex CLI {{version}} in {{dir}}',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n exited: '\\nCodex CLI exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n detaching: '\\nDetaching from Codex...',\n },\n debug: {\n starting: 'Starting hook debug server on port {{port}}',\n capturing: 'This will capture all incoming webhook requests...',\n pressCtrlC: 'Press Ctrl+C to stop.',\n stopping: '\\nStopping debug server...',\n },\n },\n\n notifications: {\n permission: {\n title: '🔐 Permission Request',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n args: 'Args: {{args}}',\n requestId: 'Request ID: {{requestId}}',\n allow: '✅ Allow',\n deny: '❌ Deny',\n },\n finished: {\n titleTelegram: '✅ Task Completed',\n titleLogger: '🏁 Task Completed',\n session: 'Session: {{sessionId}}',\n message: 'Message: {{message}}',\n eventType: 'Type: {{eventType}}',\n },\n sessionStart: {\n title: '🟢 Session Started',\n session: 'Session: {{sessionId}}',\n },\n error: {\n title: '❌ Error',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n message: 'Message: {{message}}',\n },\n unauthorized: 'You are not authorized to use this bot.',\n received: 'Message received.',\n processingError: 'Error processing message.',\n },\n\n eventTitles: {\n sessionStart: '🚀 Session Started',\n sessionEnd: '👋 Session Ended',\n turnFinished: '✅ Task Completed',\n turnThinking: '💭 Thinking...',\n toolPost: '🔧 Tool Call',\n toolExecuted: '✅ Tool Executed',\n toolFailure: '❌ Tool Failed',\n permissionRequest: '🔐 Permission Request',\n permissionResponse: '📋 Permission Response',\n questionRequest: '❓ Question',\n questionResponse: '📋 Question Response',\n agentMessage: '🤖 Agent Message',\n error: '⚠️ Error',\n fallback: '📋 Notification',\n },\n};\n","import type { SessionSummary } from '../core/session-context.js';\nimport type { ToolInfo } from '../core/adapter/types.js';\nimport { t } from '../i18n/index.js';\n\n/**\n * Unified interaction context for permission/question events.\n * Flattened shape — no `.content` wrapper.\n */\nexport interface InteractionContext {\n type: 'permission' | 'question';\n requestId: string;\n toolName: string;\n title: string;\n description?: string;\n permission?: {\n riskLevel: 'low' | 'medium' | 'high';\n args: Record<string, unknown>;\n };\n question?: {\n question: string;\n header?: string;\n options: Array<{ id: string; label: string; value: unknown; description?: string }>;\n multiSelect: boolean;\n };\n}\n\n/**\n * Unified NotificationContext event types\n * All channel formatters should handle these consistently\n */\nexport type NotificationEventType =\n | 'session:start' | 'session:end'\n | 'turn:finished' | 'turn:thinking'\n | 'tool:post' | 'tool:executed' | 'tool:failure'\n | 'permission:request' | 'permission:response'\n | 'question:request' | 'question:response'\n | 'agent:message'\n | 'error';\n\n/**\n * 获取统一的事件标题(emoji + 多语言)\n * 所有 Channel Formatter 应使用此函数以保证标题一致性\n */\nexport function getEventTitle(eventType: NotificationEventType): string {\n switch (eventType) {\n case 'session:start':\n return t('eventTitles.sessionStart');\n case 'session:end':\n return t('eventTitles.sessionEnd');\n case 'turn:finished':\n return t('eventTitles.turnFinished');\n case 'turn:thinking':\n return t('eventTitles.turnThinking');\n case 'tool:post':\n return t('eventTitles.toolPost');\n case 'tool:executed':\n return t('eventTitles.toolExecuted');\n case 'tool:failure':\n return t('eventTitles.toolFailure');\n case 'permission:request':\n return t('eventTitles.permissionRequest');\n case 'permission:response':\n return t('eventTitles.permissionResponse');\n case 'question:request':\n return t('eventTitles.questionRequest');\n case 'question:response':\n return t('eventTitles.questionResponse');\n case 'agent:message':\n return t('eventTitles.agentMessage');\n case 'error':\n return t('eventTitles.error');\n default:\n return t('eventTitles.fallback');\n }\n}\n\n// ==========================================\n// Base type — common fields for all events\n// ==========================================\ninterface NotificationContextBase {\n eventType: NotificationEventType;\n sessionId: string;\n agentType?: 'claude' | 'codex';\n userId?: string;\n chatId?: string;\n cwd?: string;\n timestamp?: string;\n}\n\n// ==========================================\n// Event-specific context types\n// ==========================================\n\nexport interface SessionStartContext extends NotificationContextBase {\n eventType: 'session:start';\n}\n\nexport interface SessionEndContext extends NotificationContextBase {\n eventType: 'session:end';\n reason?: string;\n}\n\nexport interface TurnFinishedContext extends NotificationContextBase {\n eventType: 'turn:finished';\n lastAssistantMessage?: string;\n thinking?: string;\n durationMs?: number;\n usage?: { inputTokens?: number; outputTokens?: number };\n summary?: SessionSummary;\n tools?: ToolInfo[];\n reason?: string;\n}\n\nexport interface TurnThinkingContext extends NotificationContextBase {\n eventType: 'turn:thinking';\n thinking: string;\n}\n\nexport interface ToolPostContext extends NotificationContextBase {\n eventType: 'tool:post';\n toolCallId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n}\n\nexport interface ToolExecutedContext extends NotificationContextBase {\n eventType: 'tool:executed';\n toolCallId: string;\n toolName: string;\n summary: string;\n toolInput?: Record<string, unknown>;\n output?: string;\n isTimeout: boolean;\n}\n\nexport interface ToolFailureContext extends NotificationContextBase {\n eventType: 'tool:failure';\n toolCallId?: string;\n toolName: string;\n summary?: string;\n toolInput?: Record<string, unknown>;\n error?: string;\n}\n\nexport interface PermissionRequestContext extends NotificationContextBase {\n eventType: 'permission:request';\n requestId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface QuestionRequestContext extends NotificationContextBase {\n eventType: 'question:request';\n requestId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface AgentMessageContext extends NotificationContextBase {\n eventType: 'agent:message';\n messageContent?: string;\n}\n\nexport interface ErrorContext extends NotificationContextBase {\n eventType: 'error';\n error?: string;\n}\n\n// ==========================================\n// Union type — no index signature\n// ==========================================\nexport type NotificationContext =\n | SessionStartContext\n | SessionEndContext\n | TurnFinishedContext\n | TurnThinkingContext\n | ToolPostContext\n | ToolExecutedContext\n | ToolFailureContext\n | PermissionRequestContext\n | QuestionRequestContext\n | AgentMessageContext\n | ErrorContext;\n","import type { NotificationContext } from '../../../gateway/notification-context.js';\nimport { getEventTitle } from '../../../gateway/notification-context.js';\n\n/**\n * Telegram HTML 格式化工具类\n * 生成 Telegram 支持的 HTML parse_mode 内容\n * 只需转义基础 HTML 字符: & < >\n */\nexport class TelegramFormatter {\n /**\n * 转义 HTML 特殊字符\n * @param text - 原始文本\n * @returns 转义后的文本\n */\n escape(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n /**\n * 格式化代码块\n * @param text - 代码内容\n * @param language - 可选的编程语言\n * @returns 格式化后的代码块\n */\n code(text: string, language?: string): string {\n const escaped = this.escape(text);\n if (language) {\n return `<pre><code class=\"language-${this.escape(language)}\">${escaped}</code></pre>`;\n }\n return `<pre><code>${escaped}</code></pre>`;\n }\n\n /**\n * 格式化内联代码\n * @param text - 代码内容\n * @returns 格式化后的内联代码\n */\n inlineCode(text: string): string {\n return `<code>${this.escape(text ?? '')}</code>`;\n }\n\n /**\n * 截断过长的文本\n * @param text - 原始文本\n * @param maxLength - 最大长度\n * @returns 截断后的文本\n */\n private truncate(text: string, maxLength = 3500): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength) + '...';\n }\n\n /**\n * 格式化权限申请消息\n */\n formatPermissionRequest(\n title: string,\n toolName: string,\n toolInput: Record<string, unknown> | undefined,\n cwd?: string\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n `<b>Tool:</b> ${this.escape(toolName)}`,\n ];\n if (cwd) {\n lines.push(`<b>Working Dir:</b> ${this.inlineCode(cwd)}`);\n }\n if (toolInput && Object.keys(toolInput).length > 0) {\n lines.push('', '<b>Args:</b>');\n lines.push(this.code(JSON.stringify(toolInput, null, 2), 'json'));\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化问题申请消息\n */\n formatQuestionRequest(\n title: string,\n header: string | undefined,\n question: string,\n options: Array<{ label: string; description?: string }>\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n ];\n if (header) {\n lines.push(`<b>${this.escape(header)}</b>`, '');\n }\n lines.push(this.escape(question));\n if (options.length > 0) {\n lines.push('', '<b>Options:</b>');\n options.forEach((opt, idx) => {\n const label = this.escape(opt.label);\n const desc = opt.description ? ` - ${this.escape(opt.description)}` : '';\n lines.push(`${idx + 1}. <code>${label}</code>${desc}`);\n });\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化通知上下文(统一入口)\n */\n format(context: NotificationContext): string {\n const title = getEventTitle(context.eventType);\n switch (context.eventType) {\n case 'permission:request':\n return this.formatPermissionRequest(\n title,\n context.toolName ?? 'Unknown',\n context.toolInput,\n undefined\n );\n\n case 'question:request':\n if (context.interaction?.question) {\n const q = context.interaction.question;\n return this.formatQuestionRequest(\n title,\n q.header,\n q.question,\n q.options\n );\n }\n return this.formatQuestionRequest(\n title,\n undefined,\n context.interaction?.description || '',\n []\n );\n\n case 'turn:finished':\n return this.formatFinished(\n title,\n context.durationMs,\n context.usage?.inputTokens,\n context.usage?.outputTokens,\n context.lastAssistantMessage\n );\n\n case 'session:start': {\n let startMsg = `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n if (context.cwd) {\n startMsg += `\\n<b>WorkDir:</b> ${this.escape(context.cwd)}`;\n }\n return startMsg;\n }\n\n case 'session:end':\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'tool:failure':\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName ?? 'Unknown')}`;\n\n case 'tool:executed':\n return this.formatToolExecuted(context);\n\n default:\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n }\n }\n\n /**\n * 格式化结果通知消息\n */\n formatFinished(\n title: string,\n durationMs?: number,\n inputTokens?: number,\n outputTokens?: number,\n result?: string\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n ];\n if (durationMs !== undefined) {\n const seconds = (durationMs / 1000).toFixed(1);\n lines.push(`<b>Duration:</b> ${this.escape(seconds)}s`);\n }\n if (inputTokens !== undefined && outputTokens !== undefined) {\n lines.push(`<b>Tokens:</b> in ${inputTokens} / out ${outputTokens}`);\n }\n if (result) {\n lines.push('', '<b>Result:</b>');\n // Try to parse as JSON, if fails treat as plain text\n try {\n const parsed = JSON.parse(result);\n lines.push(this.code(JSON.stringify(parsed, null, 2), 'json'));\n } catch {\n lines.push(this.escape(result));\n }\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 移除 HTML 标签,用于纯文本 fallback\n * @param text - 含 HTML 标签的文本\n * @returns 纯文本\n */\n static stripHtml(text: string): string {\n return text.replace(/<[^>]*>/g, '');\n }\n\n /**\n * 根据上下文获取标题\n */\n getTitleForContext(context: NotificationContext): string {\n return getEventTitle(context.eventType);\n }\n\n /**\n * 格式化 turn:finished 事件\n */\n private formatTurnFinished(context: NotificationContext): string {\n const lines = [\n '✅ <b>Task Completed</b>',\n '',\n `<b>Session:</b> ${this.escape(context.sessionId)}`,\n ];\n const c = context as unknown as Record<string, unknown>;\n if (c.durationMs !== undefined) {\n const seconds = ((c.durationMs as number) / 1000).toFixed(1);\n lines.push(`<b>Duration:</b> ${this.escape(seconds)}s`);\n }\n if (c.lastAssistantMessage) {\n lines.push('', this.escape(c.lastAssistantMessage as string));\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化 tool:executed 事件\n */\n private formatToolExecuted(context: NotificationContext): string {\n const title = getEventTitle(context.eventType);\n const c = context as unknown as Record<string, unknown>;\n const lines = [\n `${this.escape(title)}`,\n '',\n `<b>Session:</b> ${this.escape(context.sessionId)}`,\n `<b>Tool:</b> ${this.escape((c.toolName as string) || 'Unknown')}`,\n ];\n if (c.summary) {\n lines.push('', this.escape(c.summary as string));\n }\n return this.truncate(lines.join('\\n'));\n }\n}\n\n/**\n * 默认格式化器实例\n */\nexport const formatter = new TelegramFormatter();\n","import { createHash } from 'crypto';\n\n/**\n * Generate a channel instance ID from channel type and its credential.\n * Format: \"channelType:hash\" e.g. \"telegram:abc123def\"\n */\nexport function getChannelInstanceId(channelType: string, credential: string): string {\n const hash = createHash('sha256').update(credential).digest('hex').slice(0, 12);\n return `${channelType}:${hash}`;\n}\n\n/**\n * Parse a channel instance ID back into its components.\n */\nexport function parseChannelInstanceId(instanceId: string): { channelType: string; hash: string } | null {\n const parts = instanceId.split(':');\n if (parts.length !== 2) return null;\n return { channelType: parts[0], hash: parts[1] };\n}\n\n/**\n * Get display label for a channel instance ID.\n * Uses short hash for display purposes.\n */\nexport function getChannelInstanceLabel(channelType: string, hash: string, displayName?: string): string {\n return displayName ?? `${channelType} (${hash})`;\n}","import type { Logger } from 'pino';\nimport type { Context } from 'grammy';\nimport { BaseChannel, type ExtendedChannelConfig } from '../../../core/channel/base.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { OutboundMessage, InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { Button } from '../../../core/bus/types.js';\nimport type { NotificationContext } from '../../../gateway/notification-context.js';\nimport { TelegramBot } from './bot.js';\nimport { TelegramFormatter } from './formatter.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\n\nconst REQUEST_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Telegram Channel 配置\n */\nexport interface TelegramChannelConfig extends ExtendedChannelConfig {\n /** Telegram Bot Token */\n bot_token: string;\n /** 允许发送消息的用户ID列表 */\n allowed_users: string[];\n}\n\n/**\n * Telegram Channel 实现\n * 支持消息发送、按钮交互和权限申请处理\n */\n@Channel('telegram')\nexport class TelegramChannel extends BaseChannel {\n readonly name = 'telegram';\n readonly displayName = 'Telegram';\n readonly capabilities = {\n supportsButtons: true,\n supportsMarkdown: true,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private bot: TelegramBot;\n private telegramConfig: TelegramChannelConfig;\n private formatter: TelegramFormatter;\n private allowedUsers: Set<string>;\n private pendingRequests: Map<string, Map<string, number>> = new Map();\n private pendingOptions: Map<string, Array<{ id: string; label: string; value: unknown }>> = new Map();\n private pendingToolNames: Map<string, string> = new Map(); // requestId -> toolName for always_allow\n private waitingForCustomInput: Map<string, string> = new Map(); // userId -> requestId\n /** Tracks selected optionIds per user per requestId for multi-select questions */\n private pendingSelections: Map<string, Map<string, Set<string>>> = new Map();\n private unsubscribeInteractionResponse?: () => void;\n\n /**\n * 构造函数\n * @param config - Channel 配置\n * @param bus - 事件总线\n * @param logger - 日志记录器\n */\n constructor(config: TelegramChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n\n this.telegramConfig = config as TelegramChannelConfig;\n if (!this.telegramConfig.bot_token) {\n throw new Error('TelegramChannel requires bot_token in config');\n }\n\n this.bot = new TelegramBot(this.telegramConfig.bot_token, logger);\n this.formatter = new TelegramFormatter();\n this.allowedUsers = new Set(this.telegramConfig.allowed_users || []);\n }\n\n get channelInstanceId(): string {\n return getChannelInstanceId('telegram', this.telegramConfig.bot_token);\n }\n\n /**\n * 检查发送者是否有权限\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected isAllowed(senderId: string): boolean {\n // 如果没有配置允许的用户,拒绝所有\n if (this.allowedUsers.size === 0) {\n return false;\n }\n // 如果包含 \"*\",允许所有\n if (this.allowedUsers.has('*')) {\n return true;\n }\n // 检查 senderId 是否在允许列表中\n return this.allowedUsers.has(senderId);\n }\n\n /**\n * 格式化通知上下文为 Telegram HTML\n * 覆写 BaseChannel.format() 以支持 HTML 格式\n */\n format(context: NotificationContext): string {\n return this.formatter.format(context);\n }\n\n /**\n * 启动 Channel\n * 启动 Bot 并订阅权限申请事件\n */\n async start(): Promise<void> {\n await super.start();\n\n // 注册消息处理器\n this.registerMessageHandlers();\n this.logger.debug('Telegram message handlers registered');\n\n // 启动 Bot\n await this.bot.start();\n this.logger.info('Telegram bot start called');\n\n // 上报连接状态\n this.updateConnectionState('connected');\n\n // 订阅统一交互响应事件(用于清理按钮等)\n this.unsubscribeInteractionResponse = this.bus.onInteractionResponse(\n this.handleInteractionResponse.bind(this)\n );\n\n this.logger.info({ channel: this.name }, '[Channel] Started');\n }\n\n /**\n * 停止 Channel\n * 停止 Bot 并取消事件订阅\n */\n async stop(): Promise<void> {\n // 取消事件订阅\n this.unsubscribeInteractionResponse?.();\n\n // 停止 Bot\n await this.bot.stop();\n\n // 清理未决请求,避免内存泄漏\n this.pendingRequests.clear();\n this.pendingOptions.clear();\n this.pendingToolNames.clear();\n this.waitingForCustomInput.clear();\n this.pendingSelections.clear();\n\n // 上报连接状态\n this.updateConnectionState('disconnected');\n\n await super.stop();\n this.logger.info({ channel: this.name }, '[Channel] Stopped');\n }\n\n /**\n * 发送消息给所有允许的用户\n * @param message - 出站消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission/question requests - NotificationHandler routes to the bound channel via onOutbound\n if (\n (message.metadata?.eventType === 'permission:request' || message.metadata?.eventType === 'question:request') &&\n message.chatId === 'broadcast'\n ) {\n return;\n }\n\n // 优先使用 context 进行格式化,否则使用 text(向后兼容)\n let text: string;\n if (message.context) {\n text = this.format(message.context);\n this.logger.debug({ eventType: message.context.eventType }, 'Formatting Telegram message from context');\n } else if (message.text) {\n text = message.text;\n this.logger.debug({ textLength: message.text.length }, 'Using raw text for Telegram message');\n } else {\n this.logger.warn('No content to send in Telegram message');\n return;\n }\n\n // Build inline keyboard for interaction requests\n const eventType = message.metadata?.eventType;\n const ctx = message.context as Record<string, unknown> | undefined;\n const interaction = ctx?.interaction as import('../../../gateway/notification-context.js').InteractionContext | undefined;\n const requestId = ctx?.requestId as string | undefined;\n let replyMarkup: { inline_keyboard: Array<Array<{ text: string; callback_data: string }>> } | undefined;\n let isInteractionRequest = false;\n\n if ((eventType === 'permission:request' || eventType === 'question:request') && requestId && interaction) {\n isInteractionRequest = true;\n if (eventType === 'permission:request') {\n const toolName = (ctx?.toolName as string) || '';\n this.pendingToolNames.set(requestId, toolName);\n replyMarkup = {\n inline_keyboard: [\n [\n { text: '✅ Allow', callback_data: `allow:${requestId}` },\n { text: '❌ Deny', callback_data: `deny:${requestId}` },\n ],\n [{ text: '🔓 Always Allow', callback_data: `always_allow:${requestId}` }],\n ],\n };\n } else if (eventType === 'question:request' && interaction.question) {\n const question = interaction.question;\n this.pendingOptions.set(\n requestId,\n question.options.map((opt: { id: string; label: string; value: unknown }) => ({ id: opt.id, label: opt.label, value: opt.value }))\n );\n if (question.multiSelect) {\n this.pendingSelections.set(requestId, new Map());\n replyMarkup = { inline_keyboard: this.buildQuestionKeyboard(requestId, question.options, new Set()) };\n } else {\n replyMarkup = {\n inline_keyboard: question.options.map((opt: { id: string; label: string }) => [\n { text: opt.label, callback_data: `select:${requestId}:${opt.id}` },\n ]),\n };\n }\n }\n }\n\n const sentMessageIds = new Map<string, number>();\n\n for (const userId of this.allowedUsers) {\n if (userId === '*') continue;\n\n let messageId: number | undefined;\n try {\n const result = await this.bot.sendMessage(userId, text, {\n parseMode: 'HTML',\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup,\n });\n messageId = result.message_id;\n } catch (error) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n textLength: text.length,\n },\n 'Failed to send HTML message to user, falling back to plain text'\n );\n try {\n const result = await this.bot.sendMessage(userId, TelegramFormatter.stripHtml(text), {\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup,\n });\n messageId = result.message_id;\n } catch (fallbackError) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error: fallbackError,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Failed to send plain text message to user'\n );\n }\n }\n\n if (messageId !== undefined) {\n sentMessageIds.set(userId, messageId);\n this.logger.debug(\n {\n userId,\n telegramMessageId: messageId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId ?? userId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n replyToMessageId: message.replyToMessageId,\n },\n 'Telegram outbound delivered to recipient'\n );\n }\n }\n\n // Track pending requests for interaction responses\n if (isInteractionRequest && requestId) {\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Map());\n }\n for (const [uid, msgId] of sentMessageIds) {\n this.pendingRequests.get(requestId)!.set(uid, msgId);\n }\n }\n\n this.logger.info(\n {\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Telegram message sent'\n );\n }\n\n /**\n * 发送带按钮的消息\n * @param message - 出站消息\n * @param buttons - 按钮二维数组\n */\n async sendWithButtons(message: OutboundMessage, buttons: Button[][]): Promise<void> {\n // Skip broadcast question requests - NotificationHandler routes to the bound channel via onOutbound\n if (message.metadata?.eventType === 'question:request' && message.chatId === 'broadcast') {\n return;\n }\n\n // 优先使用 context 进行格式化,否则使用 text(向后兼容)\n let text: string;\n if (message.context) {\n text = this.format(message.context);\n } else if (message.text) {\n text = message.text;\n } else {\n this.logger.warn('No content to send in Telegram message with buttons');\n return;\n }\n\n // 构建内联键盘\n const inlineKeyboard = buttons.map((row) =>\n row.map((btn) => ({\n text: btn.text,\n callback_data: btn.data,\n }))\n );\n\n const isInteractionRequest = buttons.some((row) =>\n row.some((btn) => btn.data.startsWith('allow:') || btn.data.startsWith('deny:') || btn.data.startsWith('select:'))\n );\n const sentMessageIds = new Map<string, number>();\n\n // 发送给所有允许的用户\n for (const userId of this.allowedUsers) {\n if (userId === '*') continue;\n\n let messageId: number | undefined;\n try {\n const result = await this.bot.sendMessage(userId, text, {\n parseMode: 'HTML',\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup: { inline_keyboard: inlineKeyboard },\n });\n messageId = result.message_id;\n } catch (error) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n textLength: text.length,\n },\n 'Failed to send HTML message with buttons to user, falling back to plain text'\n );\n try {\n const result = await this.bot.sendMessage(userId, TelegramFormatter.stripHtml(text), {\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup: { inline_keyboard: inlineKeyboard },\n });\n messageId = result.message_id;\n } catch (fallbackError) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error: fallbackError,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Failed to send plain text message with buttons to user'\n );\n }\n }\n\n if (messageId !== undefined) {\n sentMessageIds.set(userId, messageId);\n this.logger.debug(\n {\n userId,\n telegramMessageId: messageId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId ?? userId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Telegram outbound with buttons delivered to recipient'\n );\n }\n }\n\n // 跟踪交互请求相关的消息 ID(用于后续移除按钮)\n if (isInteractionRequest) {\n for (const row of buttons) {\n for (const btn of row) {\n if (btn.data.startsWith('allow:') || btn.data.startsWith('deny:') || btn.data.startsWith('select:')) {\n const requestId = btn.data.split(':')[1];\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Map());\n }\n for (const [uid, msgId] of sentMessageIds) {\n this.pendingRequests.get(requestId)!.set(uid, msgId);\n }\n }\n }\n }\n }\n }\n\n /**\n * 处理统一交互响应事件(清理按钮等)\n * @param event - 交互响应事件\n */\n private async handleInteractionResponse(event: InteractionResponseEvent): Promise<void> {\n const userMessages = this.pendingRequests.get(event.requestId);\n if (userMessages) {\n for (const [userId, messageId] of userMessages) {\n try {\n await this.bot.api.editMessageReplyMarkup(userId, messageId, { reply_markup: { inline_keyboard: [] } });\n } catch (error) {\n this.logger.debug(\n { userId, messageId, error: error instanceof Error ? error.message : String(error) },\n 'Failed to remove buttons'\n );\n }\n }\n }\n // 清理已处理的请求记录\n this.pendingRequests.delete(event.requestId);\n this.pendingOptions.delete(event.requestId);\n this.pendingSelections.delete(event.requestId);\n }\n\n /**\n * 处理按钮回调\n * @param ctx - grammy Context\n */\n private async handleCallbackQuery(ctx: Context): Promise<void> {\n const data = ctx.update.callback_query?.data;\n const userId = ctx.from?.id.toString();\n\n if (!data || !userId) {\n this.logger.warn('Invalid callback query: missing data or userId');\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n\n this.logger.debug({ userId, data }, 'Received callback query');\n\n // 解析回调数据(仅在第一个冒号处分割,防止 requestId 含冒号被错误解析)\n const colonIndex = data.indexOf(':');\n if (colonIndex === -1) {\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n const action = data.slice(0, colonIndex);\n const rest = data.slice(colonIndex + 1);\n\n if (!action || !['allow', 'deny', 'always_allow', 'select', 'confirm'].includes(action)) {\n await ctx.answerCallbackQuery({ text: 'Invalid action' });\n return;\n }\n\n // 处理选择动作(question request)\n if (action === 'select') {\n const secondColonIndex = rest.indexOf(':');\n if (secondColonIndex === -1) {\n await ctx.answerCallbackQuery({ text: 'Invalid request format' });\n return;\n }\n const requestId = rest.slice(0, secondColonIndex);\n const optionId = rest.slice(secondColonIndex + 1);\n\n if (!optionId) {\n await ctx.answerCallbackQuery({ text: 'Invalid option ID' });\n return;\n }\n\n // 校验 requestId 格式\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 验证用户是否有权限响应此请求\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n // Check if this is a multi-select request\n const isMultiSelect = this.pendingSelections.has(requestId);\n\n if (isMultiSelect) {\n // Multi-select: toggle option, update buttons, do NOT submit yet\n let userSelections = this.pendingSelections.get(requestId)!.get(userId);\n if (!userSelections) {\n userSelections = new Set();\n this.pendingSelections.get(requestId)!.set(userId, userSelections);\n }\n\n // Toggle this option\n if (userSelections.has(optionId)) {\n userSelections.delete(optionId);\n } else {\n userSelections.add(optionId);\n }\n\n // 1. Acknowledge immediately — removes loading spinner right away\n const options = this.pendingOptions.get(requestId);\n const selectedLabels = Array.from(userSelections).map((id) => {\n const opt = options?.find((o) => o.id === id);\n return opt?.label ?? id;\n });\n await ctx.answerCallbackQuery({\n text: selectedLabels.length > 0 ? `Selected: ${selectedLabels.join(', ')}` : 'No selection',\n });\n\n // 2. Then update UI asynchronously (fire-and-forget)\n const updatedKeyboard = this.buildQuestionKeyboard(requestId, options ?? [], userSelections);\n const chatId = ctx.callbackQuery?.message?.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n this.bot.api.editMessageReplyMarkup(chatId, messageId, {\n reply_markup: { inline_keyboard: updatedKeyboard },\n }).catch((err) => {\n this.logger.warn({ err, requestId, optionId }, 'Failed to update multi-select keyboard');\n });\n }\n return;\n }\n\n // Single-select: submit immediately (existing behavior)\n // 查找选项值\n const options = this.pendingOptions.get(requestId);\n const selectedOption = options?.find(opt => opt.id === optionId);\n if (!selectedOption) {\n this.logger.warn({ userId, requestId, optionId }, 'Selected option not found');\n await ctx.answerCallbackQuery({ text: 'Invalid option selected' });\n return;\n }\n\n // 发布交互响应事件,返回选项值\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues: [selectedOption.value],\n },\n reason: `User selected option ${optionId} via Telegram`,\n });\n\n // 立即为当前用户移除按钮,提供即时视觉反馈\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch {\n // 忽略失败\n }\n\n // 回复用户\n await ctx.answerCallbackQuery({\n text: 'Selection confirmed',\n });\n\n this.logger.info({ requestId, userId, action: 'select', optionId }, '[Channel] User response received');\n return;\n }\n\n // 处理确认动作(multi-select Done 按钮)\n if (action === 'confirm') {\n const requestId = rest;\n\n if (!requestId) {\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to confirm request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n const userSelections = this.pendingSelections.get(requestId)?.get(userId);\n if (!userSelections || userSelections.size === 0) {\n await ctx.answerCallbackQuery({ text: 'No options selected' });\n return;\n }\n\n // Build selectedValues from all selected optionIds\n const options = this.pendingOptions.get(requestId);\n const selectedValues = Array.from(userSelections).map(id => {\n const opt = options?.find(o => o.id === id);\n return opt?.value;\n }).filter(v => v !== undefined);\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues,\n },\n reason: `User confirmed multi-select via Telegram: ${Array.from(userSelections).join(', ')}`,\n });\n\n // Cleanup\n const selectionMap = this.pendingSelections.get(requestId);\n if (selectionMap) {\n selectionMap.delete(userId);\n if (selectionMap.size === 0) {\n this.pendingSelections.delete(requestId);\n }\n }\n\n // Remove buttons\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch { /* ignore */ }\n\n await ctx.answerCallbackQuery({ text: `Confirmed: ${selectedValues.length} option(s)` });\n this.logger.info({ requestId, userId, selectedValues }, '[Channel] Multi-select confirmed');\n return;\n }\n\n // 处理权限决策动作\n const requestId = rest;\n\n if (!requestId) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 校验 requestId 格式,防止注入或畸形数据\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 验证用户是否有权限响应此请求\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n // Build response with permission updates for always_allow\n const isAlwaysAllow = action === 'always_allow';\n const permissionUpdates = isAlwaysAllow ? [{\n type: 'addRules' as const,\n rules: [{ toolName: this.pendingToolNames.get(requestId) ?? '*', ruleContent: '*' }],\n behavior: 'allow' as const,\n destination: 'localSettings' as const, // Project's settings.local.json\n }] : undefined;\n\n // 发布交互响应事件\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: isAlwaysAllow ? 'allow' : (action as 'allow' | 'deny'),\n ...(permissionUpdates && { permissionUpdates }),\n },\n reason: `User clicked ${action} button via Telegram`,\n });\n\n // Cleanup pending tool name for all permission responses\n this.pendingToolNames.delete(requestId);\n\n // 立即为当前用户移除按钮,提供即时视觉反馈\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch {\n // 忽略失败,handlePermissionDecision 会负责其他用户及兜底\n }\n\n // 回复用户\n await ctx.answerCallbackQuery({\n text: `Permission ${action === 'allow' ? 'granted' : action === 'always_allow' ? 'always allowed' : 'denied'}`,\n });\n\n this.logger.info({ requestId, userId, action }, '[Channel] User response received');\n }\n\n /**\n * 处理文本消息\n * @param ctx - grammy Context\n */\n private async handleTextMessage(ctx: Context): Promise<void> {\n const userId = ctx.from?.id.toString();\n const username = ctx.from?.username;\n const text = ctx.message?.text;\n const chatId = ctx.chat?.id.toString();\n const messageId = ctx.message?.message_id.toString();\n\n if (!userId || !text || !chatId || !messageId) {\n this.logger.warn('Invalid message: missing required fields');\n return;\n }\n\n this.logger.info(\n {\n userId,\n username,\n chatId,\n messageId,\n channelInstanceId: this.channelInstanceId,\n textLength: text.length,\n textPreview: text.slice(0, 120),\n },\n 'Telegram text message received'\n );\n\n // 检查用户权限\n if (!this.isAllowed(userId)) {\n this.logger.warn({ userId }, 'Telegram message from unauthorized user ignored');\n await ctx.reply('⛔ You are not authorized to use this bot.');\n return;\n }\n\n // 检查是否正在等待自定义输入\n const requestId = this.waitingForCustomInput.get(userId);\n if (requestId && text) {\n // 用户发送了自定义输入,提交作为答案\n this.waitingForCustomInput.delete(userId);\n\n // 验证请求仍然有效\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'Request no longer valid for custom input');\n return;\n }\n\n // 发布交互响应,使用用户输入的文本\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'input',\n customInput: text, // 使用用户输入的文本作为自定义答案\n },\n reason: `User provided custom input via Telegram`,\n });\n\n this.logger.info({ requestId, userId, action: 'input', customInput: text }, '[Channel] User response received');\n return;\n }\n\n // 转发消息到 EventBus\n this.receiveMessage(chatId, messageId, text, {\n id: userId,\n username,\n firstName: ctx.from?.first_name,\n lastName: ctx.from?.last_name,\n });\n // Note: 不再发送固定确认消息,命令响应通过 CommandHandler 发送\n }\n\n /**\n * Build inline keyboard for multi-select question with selection state\n */\n private buildQuestionKeyboard(\n requestId: string,\n options: Array<{ id: string; label: string; value: unknown }>,\n selectedIds: Set<string>\n ): Array<Array<{ text: string; callback_data: string }>> {\n const optionRows = options.map((opt) => [\n {\n text: selectedIds.has(opt.id) ? `✅ ${opt.label}` : opt.label,\n callback_data: `select:${requestId}:${opt.id}`,\n },\n ]);\n const doneRow = [[{ text: '✅ Done', callback_data: `confirm:${requestId}` }]];\n return [...optionRows, ...doneRow];\n }\n\n /**\n * 注册消息处理器\n */\n private registerMessageHandlers(): void {\n // 注册回调查询处理器\n this.bot.onCallbackQuery(this.handleCallbackQuery.bind(this));\n\n // 注册文本消息处理器\n this.bot.onTextMessage(this.handleTextMessage.bind(this));\n }\n}\n\nexport { TelegramBot, TelegramFormatter };\n","import type { Logger } from 'pino';\nimport { BaseChannel } from '../../../core/channel/base.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { ChannelConfig, ChannelCapabilities } from '../../../core/channel/types.js';\nimport type { OutboundMessage } from '../../../core/bus/events.js';\nimport { Channel } from '../../../core/channel/registry.js';\n\n/**\n * Logger Channel 实现\n *\n * 仅用于调试,将所有消息输出到日志。\n */\n@Channel('logger')\nexport class LoggerChannel extends BaseChannel {\n readonly name = 'logger';\n readonly displayName = 'Logger';\n readonly channelInstanceId = 'logger:default';\n readonly capabilities: ChannelCapabilities = {\n supportsButtons: false,\n supportsMarkdown: false,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private messageLogger: Logger;\n\n constructor(config: ChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n this.messageLogger = logger;\n }\n\n /**\n * Logger Channel 不接收消息,拒绝所有发送者\n */\n protected isAllowed(_senderId: string): boolean {\n return false;\n }\n\n async start(): Promise<void> {\n await super.start();\n this.logger.info('Logger channel started');\n }\n\n async stop(): Promise<void> {\n await super.stop();\n this.logger.info('Logger channel stopped');\n }\n\n async send(message: OutboundMessage): Promise<void> {\n this.messageLogger.info({\n chatId: message.chatId,\n text: message.text,\n }, '[Logger] Message');\n }\n}\n","/**\n * Feishu SDK 客户端封装\n * 支持 WebSocket 连接和自动重连\n */\n\nimport {\n Client,\n WSClient,\n EventDispatcher,\n AppType,\n LoggerLevel,\n} from '@larksuiteoapi/node-sdk';\nimport type { PostContent } from './formatter.js';\nimport type { FeishuChannelConfig } from './index.js';\nimport type { CardActionData } from './types.js';\n\nexport type ConnectionState = 'connected' | 'disconnected' | 'error';\n\nexport { type CardActionData } from './types.js';\n\nexport interface FeishuClientOptions {\n /** 状态变化回调 */\n onStateChange?: (state: ConnectionState, error?: Error) => void;\n /** 重连回调 */\n onReconnect?: (attempt: number) => void;\n /** 日志记录器 */\n logger?: import('pino').Logger;\n}\n\nexport type MessageHandler = (data: unknown) => void | Promise<void>;\nexport type CardActionHandler = (data: CardActionData) => void | Promise<void>;\n\nexport class FeishuClient {\n private client: Client;\n private wsClient: WSClient | null = null;\n private eventDispatcher: EventDispatcher | null = null;\n private config: FeishuChannelConfig;\n private options: FeishuClientOptions;\n private reconnectCount = 0;\n private isRunning = false;\n private messageHandler: MessageHandler | null = null;\n private cardActionHandler: CardActionHandler | null = null;\n /** 重连定时器 */\n private reconnectTimer: NodeJS.Timeout | null = null;\n\n constructor(config: FeishuChannelConfig, options: FeishuClientOptions = {}) {\n this.config = config;\n this.options = options;\n this.client = new Client({\n appId: config.app_id,\n appSecret: config.app_secret,\n appType: AppType.SelfBuild,\n });\n options.logger?.debug('FeishuClient created');\n }\n\n /**\n * 发送 post 消息(富文本)\n */\n async sendPost(\n receiveId: string,\n receiveIdType: 'open_id' | 'chat_id',\n postContent: PostContent\n ): Promise<string | null> {\n const response = await this.client.im.message.create({\n params: { receive_id_type: receiveIdType },\n data: {\n receive_id: receiveId,\n msg_type: 'post',\n content: JSON.stringify(postContent),\n },\n });\n\n if (response.code !== 0) {\n throw new Error(`Feishu API error: ${response.msg}`);\n }\n return response.data?.message_id || null;\n }\n\n /**\n * 发送卡片消息(交互式)\n */\n async sendCard(\n receiveId: string,\n receiveIdType: 'open_id' | 'chat_id',\n cardContent: string\n ): Promise<string | null> {\n const response = await this.client.im.message.create({\n params: { receive_id_type: receiveIdType },\n data: {\n receive_id: receiveId,\n msg_type: 'interactive',\n content: cardContent,\n },\n });\n\n if (response.code !== 0) {\n throw new Error(`Feishu API error: ${response.msg}`);\n }\n return response.data?.message_id || null;\n }\n\n /**\n * 启动 WebSocket 连接(带自动重连)\n */\n startWebSocket(messageHandler: MessageHandler, cardActionHandler?: CardActionHandler): void {\n if (this.isRunning) {\n this.options.logger?.warn('startWebSocket called but already running');\n return;\n }\n\n this.isRunning = true;\n this.messageHandler = messageHandler;\n this.cardActionHandler = cardActionHandler || null;\n this.options.logger?.debug('FeishuClient starting WebSocket...');\n this.connectWebSocket();\n }\n\n /**\n * 连接 WebSocket\n */\n private connectWebSocket(): void {\n try {\n this.eventDispatcher = new EventDispatcher({\n encryptKey: this.config.encrypt_key || '',\n verificationToken: this.config.verification_token || '',\n });\n\n // 注册消息处理器\n this.eventDispatcher.register({\n 'im.message.receive_v1': async (data: unknown) => {\n this.options.logger?.info('Feishu WS received im.message.receive_v1');\n this.options.logger?.debug({ data }, 'Feishu WS im.message.receive_v1 payload');\n await this.messageHandler?.(data);\n },\n // Catch-all: log any other event to aid debugging\n '*': async (eventType: string, data: unknown) => {\n this.options.logger?.info({ eventType }, 'Feishu WS received other event');\n this.options.logger?.debug({ eventType, data }, 'Feishu WS other event payload');\n },\n 'card.action.trigger': async (data: unknown) => {\n // 必须返回响应(toast/card),否则飞书会在3秒后超时\n await this.handleCardAction(data);\n // 返回 toast 响应表示成功处理\n return {\n toast: {\n type: 'success',\n content: '已处理',\n },\n };\n },\n });\n\n this.wsClient = new WSClient({\n appId: this.config.app_id,\n appSecret: this.config.app_secret,\n loggerLevel: LoggerLevel.debug,\n autoReconnect: true,\n });\n\n // 启动连接\n this.wsClient\n .start({ eventDispatcher: this.eventDispatcher })\n .then(() => {\n // 检查是否仍在运行,防止 stop 后的状态更新\n if (!this.isRunning) {\n this.wsClient?.close({ force: true });\n return;\n }\n this.reconnectCount = 0;\n this.options.logger?.info('Feishu WebSocket connected');\n this.options.onStateChange?.('connected');\n })\n .catch((error: Error) => {\n this.options.logger?.error({ error: error.message }, 'Feishu WebSocket connection failed');\n this.options.onStateChange?.('error', error);\n this.handleDisconnect();\n });\n\n // 注意:WSClient 内部有自动重连机制,但我们无法直接监听 connect/disconnect 事件\n // 我们通过定期检查和重连回调来跟踪状态\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.options.onStateChange?.('error', err);\n this.handleDisconnect();\n }\n }\n\n /**\n * 处理卡片按钮回调\n */\n private async handleCardAction(data: unknown): Promise<void> {\n if (!this.cardActionHandler) {\n return;\n }\n\n try {\n const eventData = data as Record<string, unknown>;\n\n // 回调结构:\n // {\n // operator: { open_id: \"ou_xxx\" },\n // action: { value: { action: \"agree\", requestId: \"xxx\" } },\n // context: { open_message_id: \"om_xxx\", open_chat_id: \"oc_xxx\" }\n // }\n const operator = eventData.operator as Record<string, unknown> | undefined;\n const actionObj = eventData.action as Record<string, unknown> | undefined;\n const value = actionObj?.value as Record<string, unknown> | undefined;\n const context = eventData.context as Record<string, unknown> | undefined;\n\n const cardAction: CardActionData = {\n action: String(value?.action || ''),\n requestId: value?.requestId as string | undefined,\n userId: operator?.open_id as string | undefined,\n messageId: context?.open_message_id as string | undefined,\n chatId: context?.open_chat_id as string | undefined,\n optionId: value?.optionId as string | undefined,\n };\n\n await this.cardActionHandler(cardAction);\n } catch (error) {\n this.options.logger?.error({ error }, 'Feishu handleCardAction error');\n }\n }\n /**\n * 处理连接断开(自动重连)\n */\n private handleDisconnect(): void {\n if (!this.isRunning) {\n return;\n }\n\n this.reconnectCount++;\n this.options.onReconnect?.(this.reconnectCount);\n this.options.onStateChange?.('disconnected');\n\n // 指数退避:1s, 2s, 4s, 8s, 最大30s\n const delay = Math.min(1000 * Math.pow(2, this.reconnectCount - 1), 30000);\n\n this.reconnectTimer = setTimeout(() => {\n if (this.isRunning) {\n this.connectWebSocket();\n }\n }, delay);\n }\n\n /**\n * 停止 WebSocket 连接\n */\n stopWebSocket(): void {\n this.isRunning = false;\n\n // 清理重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.wsClient) {\n this.wsClient.close({ force: false });\n this.wsClient = null;\n }\n this.eventDispatcher = null;\n }\n\n /**\n * 获取重连次数\n */\n getReconnectCount(): number {\n return this.reconnectCount;\n }\n}\n","import type { InteractionRequestEvent } from '../../../core/bus/events.js';\nimport type { CardButton, CardContent } from './types.js';\n\n/**\n * Feishu 消息格式转换器\n * Markdown/HTML → Post 格式\n * 参考 nanobot _markdown_to_post 实现\n */\n\nexport interface PostContent {\n zh_cn: {\n title?: string;\n content: PostElement[][];\n };\n}\n\nexport type PostElement =\n | { tag: 'text'; text: string; style?: ('bold' | 'italic' | 'underline' | 'line_through')[] }\n | { tag: 'a'; text: string; href: string }\n | { tag: 'at'; user_id: string; user_name?: string };\n\ninterface Segment {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n type?: 'text' | 'link';\n href?: string;\n}\n\nexport class FeishuFormatter {\n /**\n * 将内容转换为飞书 post 格式\n * 支持 Markdown 和简单的 HTML 标签\n */\n markdownToPost(content: string): PostContent {\n // 先处理 HTML 标签,转换为飞书支持的格式\n const normalized = this.normalizeHtml(content);\n const lines = normalized.trim().split('\\n');\n const paragraphs: PostElement[][] = [];\n\n for (const line of lines) {\n const elements = this.parseLine(line);\n if (elements.length > 0) {\n paragraphs.push(elements);\n }\n }\n\n return {\n zh_cn: {\n content: paragraphs,\n },\n };\n }\n\n /**\n * 格式化统一交互请求事件为卡片内容\n */\n formatInteractionRequest(event: InteractionRequestEvent): string {\n const { content, interactionType } = event;\n\n let markdown = '';\n\n if (interactionType === 'permission' && content.permission) {\n const toolName = content.title?.replace(/^Permission Required: /, '') ?? '';\n markdown += `**🔐 ${content.title}**\\n\\n`;\n markdown += `**Tool:** \\`${toolName}\\`\\n`;\n if (content.description) {\n markdown += `\\n${content.description}\\n`;\n }\n if (content.permission.args && Object.keys(content.permission.args).length > 0) {\n markdown += `\\n**Args:**\\n`;\n markdown += `\\`\\`\\`json\\n${JSON.stringify(content.permission.args, null, 2)}\\n\\`\\`\\`\\n`;\n }\n } else if (interactionType === 'question' && content.question) {\n const q = content.question;\n markdown += `**❓ ${content.title}**\\n\\n`;\n if (q.header) {\n markdown += `**${q.header}**\\n\\n`;\n }\n markdown += `${q.text}\\n\\n`;\n if (q.options.length > 0) {\n markdown += `**Options:**\\n`;\n q.options.forEach((opt, idx) => {\n markdown += `${idx + 1}. \\`${opt.label}\\``;\n if (opt.description) {\n markdown += ` - ${opt.description}`;\n }\n markdown += '\\n';\n });\n }\n } else {\n markdown += `**${content.title}**\\n\\n`;\n if (content.description) {\n markdown += `${content.description}`;\n }\n }\n\n return markdown;\n }\n\n /**\n * 将 HTML 标签规范化,提取纯文本和格式信息\n * 飞书 post 格式不支持 HTML,需要转换\n */\n private normalizeHtml(content: string): string {\n return content\n // 代码块: <pre><code>...</code></pre> -> ```...```\n .replace(/<pre><code[^>]*>([\\s\\S]*?)<\\/code><\\/pre>/g, '```\\n$1\\n```')\n // 行内代码: <code>...</code> -> `...`\n .replace(/<code>(.*?)<\\/code>/g, '`$1`')\n // 粗体: <b>...</b> 或 <strong>...</strong> -> **...**\n .replace(/<(b|strong)>(.*?)<\\/(b|strong)>/g, '**$2**')\n // 斜体: <i>...</i> 或 <em>...</em> -> *...*\n .replace(/<(i|em)>(.*?)<\\/(i|em)>/g, '*$2*')\n // 下划线: <u>...</u> -> __...__\n .replace(/<u>(.*?)<\\/u>/g, '__$1__')\n // 删除线: <s>...</s> 或 <del>...</del> -> ~~...~~\n .replace(/<(s|del)>(.*?)<\\/(s|del)>/g, '~~$2~~')\n // 换行标签\n .replace(/<br\\s*\\/?>/g, '\\n')\n // 段落标签\n .replace(/<p>(.*?)<\\/p>/g, '$1\\n')\n // 移除其他 HTML 标签但保留内容\n .replace(/<[^>]+>/g, '');\n }\n\n /**\n * 解析单行 Markdown(支持粗体、斜体、行内代码、链接)\n */\n private parseLine(line: string): PostElement[] {\n const elements: PostElement[] = [];\n\n // 处理代码块开始/结束标记\n if (line.trim() === '```') {\n return [];\n }\n\n // 处理行内格式:粗体、斜体、行内代码、链接\n const segments = this.parseInlineFormats(line);\n\n for (const seg of segments) {\n if (seg.type === 'link') {\n elements.push({ tag: 'a', text: seg.text, href: seg.href! });\n } else {\n const style: ('bold' | 'italic' | 'underline' | 'line_through')[] = [];\n if (seg.bold) style.push('bold');\n if (seg.italic) style.push('italic');\n if (seg.underline) style.push('underline');\n if (seg.strikethrough) style.push('line_through');\n\n elements.push({\n tag: 'text',\n text: seg.text,\n ...(style.length > 0 ? { style } : {}),\n });\n }\n }\n\n // 空行处理\n if (elements.length === 0 && line.trim() === '') {\n elements.push({ tag: 'text', text: '' });\n }\n\n return elements;\n }\n\n /**\n * 解析行内格式(粗体、斜体、行内代码、链接)\n */\n private parseInlineFormats(line: string): Segment[] {\n const segments: Segment[] = [];\n let remaining = line;\n\n // 匹配优先级:链接 > 行内代码 > 粗体 > 斜体\n const patterns = [\n { regex: /\\[([^\\]]+)\\]\\((https?:\\/\\/[^)]+)\\)/, type: 'link' as const },\n { regex: /`([^`]+)`/, type: 'code' as const },\n { regex: /\\*\\*([^*]+)\\*\\*/, type: 'bold' as const },\n { regex: /\\*([^*]+)\\*/, type: 'italic' as const },\n { regex: /__([^_]+)__/, type: 'underline' as const },\n { regex: /~~([^~]+)~~/, type: 'strikethrough' as const },\n ];\n\n while (remaining.length > 0) {\n let matched = false;\n\n for (const pattern of patterns) {\n const match = remaining.match(pattern.regex);\n if (match && match.index !== undefined) {\n // 匹配前的文本\n if (match.index > 0) {\n const before = remaining.slice(0, match.index);\n if (before) {\n segments.push({ text: before });\n }\n }\n\n // 处理匹配内容\n if (pattern.type === 'link') {\n segments.push({\n text: match[1],\n type: 'link',\n href: match[2],\n });\n } else {\n const segment: Segment = { text: match[1] };\n if (pattern.type === 'bold') segment.bold = true;\n if (pattern.type === 'italic') segment.italic = true;\n if (pattern.type === 'underline') segment.underline = true;\n if (pattern.type === 'strikethrough') segment.strikethrough = true;\n // 代码特殊处理:保留反引号\n if (pattern.type === 'code') {\n segment.text = match[0]; // 保留完整的 `code`\n }\n segments.push(segment);\n }\n\n remaining = remaining.slice(match.index + match[0].length);\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n // 没有匹配到任何模式,剩余部分作为纯文本\n segments.push({ text: remaining });\n break;\n }\n }\n\n return segments.length > 0 ? segments : [{ text: line }];\n }\n\n /**\n * 生成卡片 JSON\n * 根据按钮数量动态生成元素,无按钮时隐藏 hr 和 column_set\n */\n formatCard(card: CardContent): string {\n const elements: unknown[] = [\n {\n tag: 'markdown',\n content: card.content,\n text_size: 'normal',\n margin: '0px',\n },\n ];\n\n // 有按钮时添加分割线和按钮组\n if (card.buttons && card.buttons.length > 0) {\n elements.push({ tag: 'hr', margin: '0px' });\n\n const columns = card.buttons.map((btn: CardButton, index: number) => ({\n tag: 'column' as const,\n horizontal_align: 'left' as const,\n vertical_align: 'top' as const,\n vertical_spacing: '8px',\n width: 'auto' as const,\n elements: [\n {\n tag: 'button' as const,\n text: {\n content: btn.text,\n tag: 'plain_text' as const,\n },\n type: btn.type,\n size: 'small' as const,\n margin: '4px 0px 4px 0px',\n width: 'default' as const,\n element_id: `btn_${index}_${Date.now()}`,\n behaviors: [\n {\n type: 'callback' as const,\n value: btn.callbackValue,\n },\n ],\n },\n ],\n }));\n\n elements.push({\n tag: 'column_set' as const,\n flex_mode: 'stretch' as const,\n horizontal_align: 'left' as const,\n horizontal_spacing: '8px',\n margin: '0px',\n columns,\n });\n }\n\n const cardJson = {\n schema: '2.0',\n config: {\n update_multi: true,\n },\n header: {\n title: {\n content: card.title,\n tag: 'plain_text' as const,\n },\n template: 'blue',\n padding: '12px 8px 12px 8px',\n subtitle: {\n content: '',\n tag: 'plain_text' as const,\n },\n },\n body: {\n direction: 'vertical',\n elements,\n },\n };\n\n return JSON.stringify(cardJson);\n }\n}\n","import type { Logger } from 'pino';\nimport { BaseChannel } from '../../../core/channel/base.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { ChannelConfig, ChannelCapabilities } from '../../../core/channel/types.js';\nimport type { OutboundMessage, InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { NotificationContext } from '../../../gateway/notification-context.js';\nimport { getEventTitle } from '../../../gateway/notification-context.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport { FeishuClient, type CardActionData } from './client.js';\nimport { FeishuFormatter, type PostContent } from './formatter.js';\nimport type { CardButton } from './types.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\n\nconst REQUEST_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nexport interface FeishuChannelConfig extends ChannelConfig {\n /** 飞书应用 ID */\n app_id: string;\n /** 飞书应用密钥 */\n app_secret: string;\n /** 消息加密密钥(可选) */\n encrypt_key?: string;\n /** 验证 Token(可选) */\n verification_token?: string;\n /** 允许访问的用户列表,[\"*\"] 表示允许所有 */\n allowed_users?: string[];\n}\n\n/**\n * 飞书卡片结构(预留 V3 使用)\n * 参考:https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/send-feishu-cards\n */\nexport interface FeishuCard {\n config?: { wide_screen_mode?: boolean };\n header?: {\n title: { tag: 'plain_text'; content: string };\n };\n elements: unknown[];\n}\n\n/**\n * Feishu Channel 实现\n *\n * V2:实现完整消息收发\n * V3+:交互卡片、流式输出\n */\n@Channel('feishu')\nexport class FeishuChannel extends BaseChannel {\n readonly name = 'feishu';\n readonly displayName = 'Feishu';\n\n readonly capabilities: ChannelCapabilities = {\n supportsButtons: true, // V3:交互卡片\n supportsMarkdown: true, // V2:支持 Markdown\n supportsImages: false, // V3:图片消息\n supportsStreaming: false, // V3:流式输出\n };\n\n private feishuConfig: FeishuChannelConfig;\n private allowedUsers: Set<string>;\n private client: FeishuClient | null = null;\n private pendingRequests: Map<string, Set<string>> = new Map();\n private pendingOptions: Map<string, Array<{ id: string; value: unknown }>> = new Map();\n private pendingToolNames: Map<string, string> = new Map(); // requestId -> toolName for always_allow\n private unsubscribeInteractionResponse?: () => void;\n private formatter = new FeishuFormatter();\n\n constructor(config: ChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n\n this.feishuConfig = config as FeishuChannelConfig;\n this.allowedUsers = new Set(this.feishuConfig.allowed_users || []);\n\n if (!this.feishuConfig.app_id || !this.feishuConfig.app_secret) {\n throw new Error('FeishuChannel requires app_id and app_secret in config');\n }\n\n this.logger.debug(\n { appId: this.feishuConfig.app_id },\n 'FeishuChannel initialized'\n );\n }\n\n get channelInstanceId(): string {\n return getChannelInstanceId('feishu', this.feishuConfig.app_id);\n }\n\n /**\n * 获取默认配置\n * 参考 nanobot default_config 类方法\n */\n static defaultConfig(): Partial<FeishuChannelConfig> {\n return {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [], // 默认拒绝所有,需要显式配置\n };\n }\n\n /**\n * 启动 Channel\n * V2:启动 WebSocket 连接\n */\n async start(): Promise<void> {\n await super.start();\n\n this.client = new FeishuClient(this.feishuConfig, {\n logger: this.logger,\n onStateChange: (state, error) => {\n this.updateConnectionState(state, error?.message);\n },\n onReconnect: (attempt) => {\n this.recordReconnectAttempt();\n this.logger.warn({ attempt }, 'Feishu WebSocket reconnecting');\n },\n });\n\n this.client.startWebSocket(\n this.handleMessage.bind(this),\n this.handleCardAction.bind(this)\n );\n\n this.unsubscribeInteractionResponse = this.bus.onInteractionResponse(\n this.handleInteractionResponse.bind(this)\n );\n\n this.logger.info({ channel: this.name }, '[Channel] Started');\n }\n\n /**\n * 停止 Channel\n */\n async stop(): Promise<void> {\n this.unsubscribeInteractionResponse?.();\n this.pendingRequests.clear();\n this.pendingOptions.clear();\n this.pendingToolNames.clear();\n this.client?.stopWebSocket();\n await super.stop();\n this.logger.info({ channel: this.name }, '[Channel] Stopped');\n }\n\n /**\n * 格式化通知上下文为飞书 PostContent\n * 覆写 BaseChannel.format() 以支持富文本格式\n */\n format(context: NotificationContext): PostContent {\n // Use the channel's inline formatter for NotificationContext\n const markdown = this.formatContextToMarkdown(context);\n return this.formatter.markdownToPost(markdown);\n }\n\n /**\n * 发送消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission/question requests - NotificationHandler routes to the bound channel via onOutbound\n if (\n (message.metadata?.eventType === 'permission:request' ||\n message.metadata?.eventType === 'question:request') &&\n message.channel === 'broadcast'\n ) {\n return;\n }\n\n if (!this.client) {\n throw new Error('Feishu client not initialized');\n }\n\n const eventType = message.metadata?.eventType;\n const ctx = message.context as Record<string, unknown> | undefined;\n const interaction = ctx?.interaction as import('../../../gateway/notification-context.js').InteractionContext | undefined;\n const requestId = ctx?.requestId as string | undefined;\n let buttons: CardButton[] | undefined;\n let isInteractionRequest = false;\n\n // Build interactive card buttons for permission/question requests\n if ((eventType === 'permission:request' || eventType === 'question:request') && requestId && interaction) {\n isInteractionRequest = true;\n if (eventType === 'permission:request') {\n const toolName = (ctx?.toolName as string) || '';\n this.pendingToolNames.set(requestId, toolName);\n buttons = [\n { text: '✅ Allow', type: 'primary_filled', callbackValue: { action: 'agree', requestId } },\n { text: '❌ Deny', type: 'danger_filled', callbackValue: { action: 'reject', requestId } },\n { text: '🔓 Always Allow', type: 'primary', callbackValue: { action: 'always_allow', requestId } },\n ];\n } else if (eventType === 'question:request' && interaction.question) {\n const question = interaction.question;\n this.pendingOptions.set(\n requestId,\n question.options.map((opt: { id: string; value: unknown }) => ({ id: opt.id, value: opt.value }))\n );\n buttons = question.options.map((opt: { id: string; label: string }) => ({\n text: opt.label,\n type: 'primary',\n callbackValue: { action: 'select', requestId, optionId: opt.id },\n }));\n }\n }\n\n await this.sendCard(message, buttons);\n\n // Track pending requests so card actions can be validated\n if (isInteractionRequest && requestId) {\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Set());\n }\n const targetUsers = this.feishuConfig.allowed_users || [];\n for (const userId of targetUsers) {\n if (userId !== '*') {\n this.pendingRequests.get(requestId)!.add(userId);\n }\n }\n }\n\n this.logger.info({ chatId: message.chatId, eventType: message.context?.eventType }, 'Feishu message sent');\n }\n\n /**\n * 处理接收到的消息\n */\n private async handleMessage(data: unknown): Promise<void> {\n const message = this.parseMessage(data);\n if (!message) return;\n\n if (!this.isAllowed(message.senderId)) {\n this.logger.warn({ senderId: message.senderId }, 'Unauthorized message');\n return;\n }\n\n this.receiveMessage(\n message.chatId,\n message.messageId,\n message.content,\n {\n id: message.senderId,\n username: message.senderName,\n }\n );\n this.logger.info({ senderId: message.senderId, chatId: message.chatId, contentPreview: message.content.slice(0, 60) }, 'Feishu message received');\n }\n\n /**\n * 解析飞书消息\n * TODO: 实现完整的消息解析\n */\n private parseMessage(data: unknown): FeishuMessage | null {\n // 基础实现,需要根据实际情况完善\n try {\n const event = data as Record<string, unknown>;\n const message = event.message as Record<string, unknown>;\n const sender = event.sender as Record<string, unknown>;\n\n if (!message || !sender) {\n this.logger.warn({ hasMessage: !!message, hasSender: !!sender }, 'Feishu parseMessage: missing message or sender');\n return null;\n }\n\n const content = this.extractContent(message);\n if (!content) {\n this.logger.warn({ msgType: message.message_type || message.msg_type, rawContent: message.content }, 'Feishu parseMessage: no content extracted');\n return null;\n }\n\n const senderIdObj = sender.sender_id as Record<string, unknown> | undefined;\n\n return {\n messageId: String(message.message_id || ''),\n chatId: String(message.chat_id || ''),\n senderId: String(senderIdObj?.open_id || ''),\n senderName: String(senderIdObj?.union_id || 'unknown'),\n content,\n };\n } catch (error) {\n this.logger.error({ error }, 'Failed to parse Feishu message');\n return null;\n }\n }\n\n /**\n * 提取消息内容\n */\n private extractContent(message: Record<string, unknown>): string | null {\n const msgType = String(message.message_type || message.msg_type || '');\n const contentStr = String(message.content || '{}');\n\n try {\n const content = JSON.parse(contentStr);\n\n if (msgType === 'text') {\n return content.text || '';\n }\n\n // TODO: 支持其他消息类型\n return `[${msgType}]`;\n } catch {\n return contentStr;\n }\n }\n\n /**\n * 权限检查\n * 安全默认:空列表 = 拒绝所有\n *\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected isAllowed(senderId: string): boolean {\n // 安全默认:空列表 = 拒绝所有\n if (this.allowedUsers.size === 0) {\n this.logger.warn(\n { senderId },\n 'Feishu: allowed_users is empty — all access denied'\n );\n return false;\n }\n\n // \"*\" = 允许所有\n if (this.allowedUsers.has('*')) {\n return true;\n }\n\n return this.allowedUsers.has(senderId);\n }\n\n /**\n * 处理统一交互响应事件\n */\n private async handleInteractionResponse(event: InteractionResponseEvent): Promise<void> {\n const userMessages = this.pendingRequests.get(event.requestId);\n if (userMessages) {\n const action = event.response.action;\n const decisionText = action === 'allow' ? '✅ Approved' : action === 'deny' ? '❌ Denied' : `✓ ${action}`;\n this.logger.info(\n { requestId: event.requestId, action },\n `Interaction ${decisionText}`\n );\n }\n this.pendingRequests.delete(event.requestId);\n this.pendingOptions.delete(event.requestId);\n }\n\n /**\n * 处理卡片按钮回调\n */\n private async handleCardAction(data: CardActionData): Promise<void> {\n const { action, requestId, userId, optionId } = data;\n\n if (!requestId || !userId) {\n this.logger.warn({ data }, 'Invalid card action: missing requestId or userId');\n return;\n }\n\n if (!REQUEST_ID_REGEX.test(requestId)) {\n this.logger.warn({ requestId }, 'Invalid request ID format');\n return;\n }\n\n if (!['agree', 'reject', 'always_allow', 'select'].includes(action)) {\n this.logger.warn({ action }, 'Invalid card action');\n return;\n }\n\n if (!this.isAllowed(userId)) {\n this.logger.warn({ userId, requestId }, 'Unauthorized user tried to respond to request');\n return;\n }\n\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to unknown request');\n return;\n }\n // Empty set means \"*\" (all users allowed); otherwise check specific user\n if (allowedUsersForRequest.size > 0 && !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n return;\n }\n\n // Handle permission actions\n if (action === 'agree' || action === 'reject' || action === 'always_allow') {\n const decision = action === 'reject' ? 'deny' : 'allow';\n const isAlwaysAllow = action === 'always_allow';\n\n // Build permission updates for always_allow\n const permissionUpdates = isAlwaysAllow ? [{\n type: 'addRules' as const,\n rules: [{ toolName: this.pendingToolNames.get(requestId) ?? '*', ruleContent: '*' }],\n behavior: 'allow' as const,\n destination: 'localSettings' as const, // Project's settings.local.json\n }] : undefined;\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: decision,\n ...(permissionUpdates && { permissionUpdates }),\n },\n reason: `User clicked ${action} button via Feishu`,\n });\n\n // Cleanup pending tool name for all permission responses\n this.pendingToolNames.delete(requestId);\n\n this.logger.info({ requestId, userId, action: decision }, '[Channel] User response received');\n return;\n }\n\n // Handle question select action\n if (action === 'select') {\n if (!optionId) {\n this.logger.warn({ requestId, userId }, '[Channel] Select missing optionId');\n return;\n }\n\n const options = this.pendingOptions.get(requestId);\n const selectedOption = options?.find(opt => opt.id === optionId);\n if (!selectedOption) {\n this.logger.warn({ requestId, userId, optionId }, 'Selected option not found');\n return;\n }\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues: [selectedOption.value],\n },\n reason: `User selected option ${optionId} via Feishu`,\n });\n\n this.logger.info({ requestId, userId, action: 'select', optionId }, '[Channel] User response received');\n return;\n }\n }\n\n /**\n * 发送带按钮的卡片消息\n */\n async sendCard(message: OutboundMessage, buttons?: CardButton[]): Promise<void> {\n if (!this.client) {\n this.logger.error('Feishu client not initialized');\n throw new Error('Feishu client not initialized');\n }\n\n let content: string;\n if (message.context) {\n content = this.formatContextToMarkdown(message.context);\n } else if (message.text) {\n content = message.text;\n } else {\n this.logger.warn('No content to send in Feishu card message');\n return;\n }\n\n const title = this.getTitleForContext(message.context);\n const cardContent = this.formatter.formatCard({ title, content, buttons });\n\n const targetUsers = this.feishuConfig.allowed_users || [];\n\n for (const userId of targetUsers) {\n if (userId === '*') continue;\n\n const receiveIdType = userId.startsWith('oc_') ? 'chat_id' : 'open_id';\n\n try {\n await this.client.sendCard(userId, receiveIdType, cardContent);\n } catch (error) {\n this.logger.error(\n { userId, error: error instanceof Error ? error.message : String(error) },\n 'Failed to send Feishu card message'\n );\n }\n }\n }\n\n /**\n * 将 NotificationContext 转换为 Markdown 字符串\n */\n private formatContextToMarkdown(context: NotificationContext): string {\n let md = '';\n switch (context.eventType) {\n case 'session:start':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**User:** ${context.userId || 'Unknown'}\\n`;\n md += `**Status:** Session started`;\n if (context.cwd) {\n md += `\\n**WorkDir:** ${context.cwd}`;\n }\n break;\n case 'session:end':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Status:** Session ended`;\n if (context.reason) {\n md += `\\n**Reason:** ${context.reason}`;\n }\n break;\n case 'agent:message':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Agent Message:**\\n${context.messageContent || ''}`;\n break;\n case 'turn:thinking':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Status:** Thinking...`;\n if (context.thinking) {\n md += `\\n\\n${context.thinking}`;\n }\n break;\n case 'turn:finished':\n md = `**Session:** ${context.sessionId}\\n`;\n if (context.cwd) {\n md += `**WorkDir:** ${context.cwd}\\n`;\n }\n md += `**Status:** Turn finished\\n`;\n if (context.durationMs) {\n md += `**Duration:** ${(context.durationMs / 1000).toFixed(1)}s\\n`;\n }\n if (context.usage?.inputTokens !== undefined && context.usage?.outputTokens !== undefined) {\n md += `**Tokens:** in ${context.usage.inputTokens} / out ${context.usage.outputTokens}\\n`;\n }\n if (context.lastAssistantMessage) {\n md += `**Message:** ${context.lastAssistantMessage}`;\n }\n break;\n case 'tool:post':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Starting`;\n if (context.toolInput) {\n md += `\\n**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n }\n break;\n case 'tool:executed':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Completed`;\n if (context.summary) {\n md += `\\n\\n${context.summary}`;\n }\n if (context.isTimeout) {\n md += `\\n\\n⚠️ **Timeout**`;\n }\n break;\n case 'tool:failure':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Failed`;\n if (context.error) {\n md += `\\n**Error:** ${context.error}`;\n }\n break;\n case 'permission:request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**${getEventTitle('permission:request')}**\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n if (context.cwd) {\n md += `**Working Dir:** ${context.cwd}\\n`;\n }\n if (context.toolInput) {\n md += `\\n**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n }\n break;\n case 'question:request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**${getEventTitle('question:request')}**\\n`;\n if (context.interaction?.question) {\n md += `\\n${context.interaction.question.question}`;\n }\n break;\n case 'error':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Error**\\n`;\n if (context.error) {\n md += context.error;\n }\n break;\n default:\n md = `**Event:** ${(context as any).eventType}\\n**Session:** ${(context as any).sessionId}`;\n }\n return md;\n }\n\n /**\n * 根据上下文获取标题\n */\n private getTitleForContext(context?: NotificationContext): string {\n if (!context) return getEventTitle('error');\n return getEventTitle(context.eventType);\n }\n}\n\n// 消息类型定义\ninterface FeishuMessage {\n messageId: string;\n chatId: string;\n senderId: string;\n senderName: string;\n content: string;\n}\n","import type { OutboundMessage } from '../../../core/bus/events.js';\nimport type { NotificationContext, PermissionRequestContext, QuestionRequestContext } from '../../../gateway/notification-context.js';\nimport type { AppProtocolEventFrame } from './types.js';\n\nexport interface AppChannelMapperOptions {\n createEventId?: () => string;\n createMessageId?: () => string;\n}\n\nexport type AppMappedOutboundEvent =\n | AppProtocolEventFrame<'message.created'>\n | AppProtocolEventFrame<'interaction.requested'>\n | AppProtocolEventFrame<'agent.finished'>;\n\nexport function mapOutboundMessageToAppEvent(\n message: OutboundMessage,\n options: AppChannelMapperOptions = {},\n): AppMappedOutboundEvent | null {\n const context = message.context;\n if (!context) {\n return null;\n }\n\n const timestamp = message.timestamp.toISOString();\n const eventId = options.createEventId?.() ?? createId('evt');\n\n switch (context.eventType) {\n case 'agent:message':\n return {\n type: 'event',\n eventId,\n name: 'message.created' as const,\n timestamp,\n payload: {\n sessionId: context.sessionId,\n message: {\n id: options.createMessageId?.() ?? createId('msg'),\n sessionId: context.sessionId,\n role: 'assistant' as const,\n type: 'text' as const,\n text: context.messageContent ?? '',\n createdAt: timestamp,\n status: 'completed' as const,\n metadata: {},\n },\n },\n };\n\n case 'turn:finished':\n return {\n type: 'event',\n eventId,\n name: 'agent.finished' as const,\n timestamp,\n payload: {\n sessionId: context.sessionId,\n reason: context.reason,\n lastAssistantMessage: context.lastAssistantMessage,\n summary: context.summary,\n },\n };\n\n case 'permission:request':\n case 'question:request':\n return mapInteractionRequested(context, eventId, timestamp);\n\n default:\n return null;\n }\n}\n\nfunction mapInteractionRequested(\n context: PermissionRequestContext | QuestionRequestContext,\n eventId: string,\n timestamp: string,\n): AppProtocolEventFrame<'interaction.requested'> | null {\n const interaction = context.interaction;\n const requestId = context.requestId ?? interaction?.requestId;\n const interactionType = interaction?.type;\n\n if (!interaction || !requestId || !interactionType) {\n return null;\n }\n\n return {\n type: 'event',\n eventId,\n name: 'interaction.requested',\n timestamp,\n payload: {\n interaction: {\n id: requestId,\n sessionId: context.sessionId,\n type: interactionType,\n title: interaction.title,\n description: interaction.description,\n status: 'pending',\n createdAt: timestamp,\n toolName: context.toolName,\n toolInput: context.toolInput,\n riskLevel: interaction.permission?.riskLevel,\n cwd: context.cwd,\n },\n },\n };\n}\n\nfunction createId(prefix: string): string {\n return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n","import type { Logger } from 'pino';\nimport { BaseChannel, type ExtendedChannelConfig } from '../../../core/channel/base.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { OutboundMessage } from '../../../core/bus/events.js';\nimport {\n mapOutboundMessageToAppEvent,\n type AppMappedOutboundEvent,\n} from './mapper.js';\n\nexport interface AppChannelTransport {\n sendEvent(channelId: string, event: AppMappedOutboundEvent): Promise<void> | void;\n}\n\nexport interface AppChannelConfig extends ExtendedChannelConfig {\n channel_id: string;\n transport?: AppChannelTransport;\n}\n\n@Channel('app')\nexport class AppChannel extends BaseChannel {\n readonly name = 'app';\n readonly displayName = 'App';\n readonly capabilities = {\n supportsButtons: false,\n supportsMarkdown: false,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private readonly appConfig: AppChannelConfig;\n\n constructor(config: AppChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n this.appConfig = config;\n\n if (!this.appConfig.channel_id) {\n throw new Error('AppChannel requires channel_id in config');\n }\n }\n\n get channelInstanceId(): string {\n return this.appConfig.channel_id;\n }\n\n async start(): Promise<void> {\n await super.start();\n this.updateConnectionState('connected');\n }\n\n async stop(): Promise<void> {\n this.updateConnectionState('disconnected');\n await super.stop();\n }\n\n async send(message: OutboundMessage): Promise<void> {\n const targetChannelInstanceId = readChannelInstanceId(message);\n if (targetChannelInstanceId && targetChannelInstanceId !== this.channelInstanceId) {\n this.logger.debug(\n {\n channelInstanceId: this.channelInstanceId,\n targetChannelInstanceId,\n sessionId: message.context?.sessionId,\n },\n '[AppChannel] Skipping outbound message for another channel instance',\n );\n return;\n }\n\n const event = mapOutboundMessageToAppEvent(message);\n if (!event) {\n this.logger.debug(\n {\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType,\n sessionId: message.context?.sessionId,\n },\n '[AppChannel] No outbound app event mapping for message',\n );\n return;\n }\n\n if (!this.appConfig.transport) {\n this.logger.warn(\n { channelInstanceId: this.channelInstanceId, eventName: event.name },\n '[AppChannel] Transport unavailable, dropping outbound event',\n );\n return;\n }\n\n await this.appConfig.transport.sendEvent(this.channelInstanceId, event);\n }\n\n protected isAllowed(_senderId: string): boolean {\n return false;\n }\n}\n\nfunction readChannelInstanceId(message: OutboundMessage): string | undefined {\n const channelInstanceId = message.metadata?.channelInstanceId;\n return typeof channelInstanceId === 'string' && channelInstanceId.length > 0\n ? channelInstanceId\n : undefined;\n}\n","import { WebSocketServer as NodeWebSocketServer, WebSocket } from 'ws';\nimport type { IncomingMessage } from 'http';\nimport { getLogger } from '../../../shared/logger.js';\nimport type { HttpServer } from '../../../server/http.js';\nimport type { AgentType } from '../../../core/adapter/types.js';\nimport type { AppProtocolErrorResponseFrame, AppProtocolEventFrame } from './types.js';\nimport type {\n AppChannelBusinessCommandFrame,\n AppChannelBusinessResponseFrame,\n AppChannelCommandHandler,\n AppChannelProtocolHandler,\n} from './protocol.js';\n\nconst logger = getLogger();\nconst DEFAULT_PATH = '/ws/channels/app';\nconst DEFAULT_PROTOCOL_VERSION = '1';\n\nexport interface AppChannelGateway {\n listRegisteredAgents(): Array<{ token: string; agentType: string }>;\n}\n\nexport interface AppChannelConnection {\n clientId: string;\n connectionId: string;\n channel: 'app';\n channelId: string;\n token: string;\n agentId: AgentType;\n protocolVersion: string;\n clientInfo?: Record<string, unknown>;\n authenticatedAt: string;\n}\n\ninterface AppChannelTransportCommandFrame {\n type: 'cmd';\n id: string;\n name: string;\n payload?: Record<string, unknown>;\n}\n\nexport interface AppChannelCommandContext {\n frame: AppChannelBusinessCommandFrame;\n connection: AppChannelConnection;\n request: IncomingMessage;\n}\n\nexport interface AppChannelWebSocketServerOptions {\n path?: string;\n protocolVersion?: string;\n commandHandler?: AppChannelCommandHandler;\n protocolHandler?: AppChannelProtocolHandler;\n}\n\ninterface ConnectedClient {\n clientId: string;\n ws: WebSocket;\n request: IncomingMessage;\n}\n\ninterface AuthPayload {\n channel?: unknown;\n channelId?: unknown;\n token?: unknown;\n protocolVersion?: unknown;\n clientInfo?: unknown;\n}\n\ninterface PingPayload {\n ts?: unknown;\n}\n\nexport class AppChannelWebSocketServer {\n private readonly path: string;\n private readonly protocolVersion: string;\n private readonly clients = new Map<string, ConnectedClient>();\n private readonly connections = new Map<string, AppChannelConnection>();\n private wss: NodeWebSocketServer | null = null;\n private unregisterUpgradeHandler: (() => void) | null = null;\n private clientIdCounter = 0;\n private connectionIdCounter = 0;\n\n constructor(\n private readonly httpServer: HttpServer,\n private readonly gateway: AppChannelGateway,\n private readonly options: AppChannelWebSocketServerOptions = {},\n ) {\n this.path = options.path ?? DEFAULT_PATH;\n this.protocolVersion = options.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;\n }\n\n async start(): Promise<void> {\n const server = this.httpServer.getServer();\n if (!server) {\n throw new Error('HTTP server must be started before app channel WebSocket server');\n }\n\n this.wss = new NodeWebSocketServer({ noServer: true });\n this.wss.on('connection', (ws, request) => {\n this.addClient(ws, request);\n });\n\n this.unregisterUpgradeHandler = this.httpServer.onUpgrade(this.path, (request, socket, head) => {\n this.wss?.handleUpgrade(request, socket, head, (ws) => {\n this.wss?.emit('connection', ws, request);\n });\n });\n\n logger.info({ path: this.path }, '[AppChannel] WebSocket server registered');\n }\n\n async stop(): Promise<void> {\n this.unregisterUpgradeHandler?.();\n this.unregisterUpgradeHandler = null;\n\n for (const client of this.clients.values()) {\n client.ws.close();\n }\n\n this.clients.clear();\n this.connections.clear();\n\n if (!this.wss) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n this.wss?.close(() => resolve());\n });\n\n this.wss = null;\n }\n\n listConnections(): AppChannelConnection[] {\n return Array.from(this.connections.values());\n }\n\n broadcastToChannel(channelId: string, event: AppProtocolEventFrame): void {\n for (const [clientId, connection] of this.connections) {\n if (connection.channelId === channelId) {\n this.send(clientId, event);\n }\n }\n }\n\n connectClientForTest(ws: WebSocket, request: IncomingMessage): void {\n this.addClient(ws, request);\n }\n\n private addClient(ws: WebSocket, request: IncomingMessage): void {\n const clientId = `app-client-${++this.clientIdCounter}`;\n this.clients.set(clientId, { clientId, ws, request });\n\n ws.on('message', (raw) => {\n void this.handleRawMessage(clientId, raw.toString());\n });\n\n ws.on('close', () => {\n this.removeClient(clientId);\n });\n\n ws.on('error', (error) => {\n logger.warn({ clientId, error }, '[AppChannel] WebSocket client error');\n this.removeClient(clientId);\n });\n }\n\n private removeClient(clientId: string): void {\n this.clients.delete(clientId);\n this.connections.delete(clientId);\n }\n\n private async handleRawMessage(clientId: string, raw: string): Promise<void> {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n this.sendError(clientId, 'invalid_json', 'INVALID_JSON', 'Invalid JSON frame');\n return;\n }\n\n if (!isCommandFrame(frame)) {\n const id = readFrameId(frame);\n this.sendError(clientId, id, 'INVALID_FRAME', 'Expected a command frame');\n return;\n }\n\n await this.handleCommand(clientId, frame);\n }\n\n private async handleCommand(clientId: string, frame: AppChannelTransportCommandFrame): Promise<void> {\n if (frame.name === 'auth') {\n this.handleAuth(clientId, frame);\n return;\n }\n\n if (frame.name === 'ping') {\n this.handlePing(clientId, frame);\n return;\n }\n\n const connection = this.connections.get(clientId);\n if (!connection) {\n this.sendError(\n clientId,\n frame.id,\n 'UNAUTHORIZED',\n `Authenticate with auth before sending ${frame.name}`,\n );\n return;\n }\n\n const client = this.clients.get(clientId);\n if (!client) {\n return;\n }\n\n const commandHandler = this.options.commandHandler ?? this.options.protocolHandler?.handleCommand;\n if (!commandHandler) {\n this.sendError(clientId, frame.id, 'NOT_IMPLEMENTED', `Unhandled command: ${frame.name}`);\n return;\n }\n\n try {\n const response = await commandHandler({\n frame: frame as AppChannelBusinessCommandFrame,\n connection,\n request: client.request,\n });\n\n if (response) {\n this.send(clientId, response);\n }\n } catch (error) {\n logger.error({ clientId, frameName: frame.name, error }, '[AppChannel] Command handler failed');\n this.sendError(clientId, frame.id, 'INTERNAL_ERROR', 'Failed to process command');\n }\n }\n\n private handleAuth(clientId: string, frame: AppChannelTransportCommandFrame): void {\n const payload = (frame.payload ?? {}) as AuthPayload;\n\n if (payload.channel !== 'app') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.channel must be app');\n return;\n }\n\n if (typeof payload.channelId !== 'string' || payload.channelId.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.channelId is required');\n return;\n }\n\n if (typeof payload.token !== 'string' || payload.token.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.token is required');\n return;\n }\n\n if (payload.protocolVersion !== this.protocolVersion) {\n this.sendError(\n clientId,\n frame.id,\n 'UNSUPPORTED_PROTOCOL_VERSION',\n `Unsupported protocol version: ${String(payload.protocolVersion ?? '')}`,\n );\n return;\n }\n\n const registration = this.gateway\n .listRegisteredAgents()\n .find((candidate) => candidate.token === payload.token);\n\n if (!registration) {\n this.sendError(clientId, frame.id, 'AUTH_INVALID', 'Invalid app channel token');\n return;\n }\n\n const connectionId = `conn_${String(++this.connectionIdCounter).padStart(3, '0')}`;\n const connection: AppChannelConnection = {\n clientId,\n connectionId,\n channel: 'app',\n channelId: payload.channelId,\n token: payload.token,\n agentId: registration.agentType as AgentType,\n protocolVersion: this.protocolVersion,\n clientInfo: isRecord(payload.clientInfo) ? payload.clientInfo : undefined,\n authenticatedAt: new Date().toISOString(),\n };\n\n this.connections.set(clientId, connection);\n\n this.send(clientId, {\n type: 'res',\n id: frame.id,\n ok: true,\n result: {\n channel: 'app',\n channelId: connection.channelId,\n connectionId: connection.connectionId,\n protocolVersion: connection.protocolVersion,\n serverTime: new Date().toISOString(),\n defaultAgentId: connection.agentId,\n },\n });\n }\n\n private handlePing(clientId: string, frame: AppChannelTransportCommandFrame): void {\n const payload = (frame.payload ?? {}) as PingPayload;\n\n if (typeof payload.ts !== 'string' || payload.ts.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'ping payload.ts is required');\n return;\n }\n\n this.send(clientId, {\n type: 'res',\n id: frame.id,\n ok: true,\n result: {\n ts: payload.ts,\n serverTime: new Date().toISOString(),\n },\n });\n }\n\n private send(clientId: string, frame: AppChannelBusinessResponseFrame | AuthSuccessResponseFrame | PingSuccessResponseFrame | AppProtocolEventFrame): void {\n const client = this.clients.get(clientId);\n if (!client || client.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n\n client.ws.send(JSON.stringify(frame));\n }\n\n private sendError(clientId: string, id: string, code: string, message: string): void {\n this.send(clientId, {\n type: 'res',\n id,\n ok: false,\n error: { code, message },\n } satisfies AppProtocolErrorResponseFrame);\n }\n}\n\nfunction isCommandFrame(value: unknown): value is AppChannelTransportCommandFrame {\n return (\n isRecord(value) &&\n value.type === 'cmd' &&\n typeof value.id === 'string' &&\n value.id.length > 0 &&\n typeof value.name === 'string' &&\n value.name.length > 0 &&\n (value.payload === undefined || isRecord(value.payload))\n );\n}\n\ninterface AuthSuccessResponseFrame {\n type: 'res';\n id: string;\n ok: true;\n result: {\n channel: 'app';\n channelId: string;\n connectionId: string;\n protocolVersion: string;\n serverTime: string;\n defaultAgentId: string;\n };\n}\n\ninterface PingSuccessResponseFrame {\n type: 'res';\n id: string;\n ok: true;\n result: {\n ts: string;\n serverTime: string;\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readFrameId(frame: unknown): string {\n if (isRecord(frame) && typeof frame.id === 'string' && frame.id.length > 0) {\n return frame.id;\n }\n\n return 'unknown';\n}\n","import { randomUUID } from 'crypto';\nimport type { InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { AgentType, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport type { InteractionResponse } from '../../../core/interaction/types.js';\nimport { AppQueryService, type AppQueryGateway, type AppQueryPendingInteraction } from './query-service.js';\nimport type {\n AppProtocolCommandFrame,\n AppProtocolErrorResponseFrame,\n AppProtocolSuccessResponseFrame,\n} from './types.js';\nimport type { AppChannelConnection, AppChannelCommandContext } from './server.js';\n\nexport interface AppProtocolGateway extends AppQueryGateway {\n createSession(\n token: string,\n sessionId: string,\n options?: CreateSessionOptions,\n ): Promise<AppSession>;\n}\n\nexport interface AppProtocolBus {\n publishInteractionResponse(\n response: Omit<InteractionResponseEvent, 'type' | 'timestamp'>,\n ): void;\n}\n\nexport interface AppChannelCommandHandlerOptions {\n gateway: AppProtocolGateway;\n queryService?: AppQueryService;\n bus?: AppProtocolBus;\n createSessionId?: () => string;\n createMessageId?: () => string;\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[];\n}\n\nexport type AppChannelBusinessCommandFrame =\n | AppProtocolCommandFrame<'session.create'>\n | AppAgentListCommandFrame\n | AppSessionListCommandFrame\n | AppMessageSendCommandFrame\n | AppInteractionRespondCommandFrame;\n\nexport type AppChannelBusinessResponseFrame =\n | AppProtocolSuccessResponseFrame\n | AppProtocolErrorResponseFrame;\n\nexport type AppChannelCommandHandler =\n (context: AppChannelCommandContext) => Promise<AppChannelBusinessResponseFrame | void> | AppChannelBusinessResponseFrame | void;\n\nexport interface AppChannelProtocolHandler {\n handleCommand: AppChannelCommandHandler;\n}\n\nconst MAX_SUCCESSFUL_MESSAGE_SEND_RESULTS = 32;\n\nexport function createAppChannelProtocolHandler(\n options: AppChannelCommandHandlerOptions,\n): AppChannelProtocolHandler {\n return {\n handleCommand: createAppChannelCommandHandler(options),\n };\n}\n\nexport function createAppChannelCommandHandler(\n options: AppChannelCommandHandlerOptions,\n): AppChannelCommandHandler {\n const queryService =\n options.queryService ??\n new AppQueryService(options.gateway, {\n listPendingInteractions: options.listPendingInteractions,\n });\n const sentMessageResults = new Map<string, AppMessageSendRecord>();\n const inFlightMessageResults = new Map<string, AppMessageSendInFlight>();\n\n return async ({ frame, connection }) => {\n switch (frame.name) {\n case 'agent.list':\n return ok(frame.id, {\n items: queryService.listAgents(),\n });\n\n case 'session.list':\n return handleSessionList(frame, connection, options.gateway, queryService);\n\n case 'session.create':\n return handleSessionCreate(frame, connection, options.gateway, queryService, options.createSessionId);\n\n case 'message.send':\n return handleMessageSend(\n frame,\n connection,\n options.gateway,\n sentMessageResults,\n inFlightMessageResults,\n options.createMessageId,\n );\n\n case 'interaction.respond':\n return handleInteractionRespond(frame, connection, options);\n\n default: {\n const fallback = frame as { id: string; name?: string };\n return error(fallback.id, 'NOT_IMPLEMENTED', `Unhandled command: ${String(fallback.name)}`);\n }\n }\n };\n}\n\nasync function handleSessionList(\n frame: AppSessionListCommandFrame,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n queryService: AppQueryService,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (!isAgentId(payload.agentId)) {\n return error(frame.id, 'INVALID_PAYLOAD', 'session.list payload.agentId is required');\n }\n\n const sessions = queryService\n .listSessions(payload.agentId)\n .filter((session) => isOwnedSession(gateway.getSession(session.id), connection));\n const limit = typeof payload.limit === 'number' && payload.limit > 0 ? payload.limit : sessions.length;\n\n return ok(frame.id, {\n items: sessions.slice(0, limit),\n pageInfo: {\n nextCursor: null,\n hasMore: false,\n },\n });\n}\n\nasync function handleSessionCreate(\n frame: AppProtocolCommandFrame<'session.create'>,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n queryService: AppQueryService,\n createSessionId?: () => string,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n\n if (!isAgentId(payload.agentId)) {\n return error(frame.id, 'INVALID_PAYLOAD', 'session.create payload.agentId is required');\n }\n\n if (payload.agentId !== connection.agentId) {\n return error(\n frame.id,\n 'INVALID_PAYLOAD',\n 'session.create payload.agentId must match the authenticated agent',\n );\n }\n\n const sessionId = createSessionId?.() ?? randomUUID();\n const metadata: Record<string, unknown> = {\n channel: connection.channel,\n channelId: connection.channelId,\n channelInstanceId: connection.channelId,\n };\n\n if (typeof payload.title === 'string' && payload.title.trim() !== '') {\n metadata.title = payload.title;\n }\n\n await gateway.createSession(connection.token, sessionId, { metadata, cwd: payload.cwd });\n const session = queryService.getSessionSummary(sessionId);\n if (!session) {\n return error(frame.id, 'INTERNAL_ERROR', `Created session could not be loaded: ${sessionId}`);\n }\n\n return ok(frame.id, { session });\n}\n\nasync function handleMessageSend(\n frame: AppMessageSendCommandFrame,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n sentMessageResults: Map<string, AppMessageSendRecord>,\n inFlightMessageResults: Map<string, AppMessageSendInFlight>,\n createMessageId?: () => string,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (typeof payload.sessionId !== 'string' || payload.sessionId.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'message.send payload.sessionId is required');\n }\n\n if (payload.message?.type !== 'text' || typeof payload.message.text !== 'string' || payload.message.text.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'message.send payload.message.text is required');\n }\n\n const session = gateway.getSession(payload.sessionId);\n if (!session || !isOwnedSession(session, connection)) {\n return error(frame.id, 'NOT_FOUND', `Unknown session: ${payload.sessionId}`);\n }\n\n const providedMessageId =\n typeof payload.message.id === 'string' && payload.message.id.trim() !== ''\n ? payload.message.id\n : undefined;\n const messageText = payload.message.text;\n const dedupeKey = providedMessageId ? `${payload.sessionId}:${providedMessageId}` : null;\n if (dedupeKey) {\n const existing = sentMessageResults.get(dedupeKey);\n if (existing) {\n if (existing.messageText !== messageText) {\n return error(\n frame.id,\n 'CONFLICT',\n 'message.send payload.message.text must match the original text for this message.id',\n );\n }\n\n return ok(frame.id, existing.outcome);\n }\n\n const inFlight = inFlightMessageResults.get(dedupeKey);\n if (inFlight) {\n if (inFlight.messageText !== messageText) {\n return error(\n frame.id,\n 'CONFLICT',\n 'message.send payload.message.text must match the original text for this message.id',\n );\n }\n\n const outcome = await inFlight.promise;\n return ok(frame.id, outcome);\n }\n }\n\n const messageId = providedMessageId ?? createMessageId?.() ?? randomUUID();\n const resultPromise = (async (): Promise<AppMessageSendOutcome> => {\n await session.sendCommand({\n type: 'user:message',\n content: messageText,\n });\n\n return {\n accepted: true,\n sessionId: payload.sessionId,\n messageId,\n };\n })();\n\n if (dedupeKey) {\n inFlightMessageResults.set(dedupeKey, {\n messageText,\n promise: resultPromise,\n });\n }\n\n try {\n const outcome = await resultPromise;\n if (dedupeKey) {\n inFlightMessageResults.delete(dedupeKey);\n sentMessageResults.set(dedupeKey, {\n messageText,\n outcome,\n });\n if (sentMessageResults.size > MAX_SUCCESSFUL_MESSAGE_SEND_RESULTS) {\n const oldestKey = sentMessageResults.keys().next().value as string | undefined;\n if (oldestKey) {\n sentMessageResults.delete(oldestKey);\n }\n }\n }\n\n return ok(frame.id, outcome);\n } catch (error) {\n if (dedupeKey) {\n inFlightMessageResults.delete(dedupeKey);\n }\n\n throw error;\n }\n}\n\nasync function handleInteractionRespond(\n frame: AppInteractionRespondCommandFrame,\n connection: AppChannelConnection,\n options: AppChannelCommandHandlerOptions,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (typeof payload.interactionId !== 'string' || payload.interactionId.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'interaction.respond payload.interactionId is required');\n }\n\n const response = toInteractionResponse(payload.interactionId, payload.response);\n if (!response) {\n return error(frame.id, 'INVALID_PAYLOAD', 'interaction.respond payload.response is invalid');\n }\n\n const pendingSessionId = findPendingInteractionSessionId(\n payload.interactionId,\n connection,\n options.gateway,\n options.listPendingInteractions,\n );\n if (!pendingSessionId) {\n return error(frame.id, 'NOT_FOUND', `Unknown interaction: ${payload.interactionId}`);\n }\n\n if (options.bus) {\n options.bus.publishInteractionResponse({\n requestId: payload.interactionId,\n response,\n reason: response.message,\n });\n } else {\n return error(frame.id, 'NOT_IMPLEMENTED', 'Interaction response transport is unavailable');\n }\n\n return ok(frame.id, {\n accepted: true,\n interactionId: payload.interactionId,\n });\n}\n\nfunction findPendingInteractionSessionId(\n interactionId: string,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[],\n): string | null {\n if (!listPendingInteractions) {\n return null;\n }\n\n const sessions = gateway.listSessions({ agentType: connection.agentId, includeEnded: true });\n for (const sessionInfo of sessions) {\n const session = gateway.getSession(sessionInfo.id);\n if (!session || !isOwnedSession(session, connection)) {\n continue;\n }\n\n const pendingInteractions = listPendingInteractions(sessionInfo.id);\n if (pendingInteractions.some((interaction) => interaction.id === interactionId)) {\n return sessionInfo.id;\n }\n }\n\n return null;\n}\n\nfunction toInteractionResponse(\n interactionId: string,\n payload: AppInteractionRespondCommandFrame['payload']['response'],\n): InteractionResponse | null {\n if (!isInteractionAction(payload.action)) {\n return null;\n }\n\n return {\n requestId: interactionId,\n action: payload.action,\n message: typeof payload.message === 'string' ? payload.message : undefined,\n selectedValues: Array.isArray(payload.selectedValues) ? payload.selectedValues : undefined,\n customInput: typeof payload.customInput === 'string' ? payload.customInput : undefined,\n updatedInput: isRecord(payload.updatedInput) ? payload.updatedInput : undefined,\n permissionUpdates: Array.isArray(payload.permissionUpdates) ? payload.permissionUpdates : undefined,\n permanent: typeof payload.permanent === 'boolean' ? payload.permanent : undefined,\n };\n}\n\nfunction isOwnedSession(\n session: AppSession | undefined,\n connection: AppChannelConnection,\n): boolean {\n if (!session) {\n return false;\n }\n\n if (session.token && session.token !== connection.token) {\n return false;\n }\n\n const metadata = session.metadata ?? {};\n const channelId = readString(metadata.channelId) ?? readString(metadata.channelInstanceId);\n return channelId ? channelId === connection.channelId : true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\nfunction isAgentId(value: unknown): value is AgentType {\n return value === 'claude' || value === 'codex';\n}\n\nfunction isInteractionAction(value: unknown): value is InteractionResponse['action'] {\n return value === 'allow' || value === 'deny' || value === 'select' || value === 'input';\n}\n\nfunction ok<Result>(id: string, result: Result): AppProtocolSuccessResponseFrame {\n return {\n type: 'res',\n id,\n ok: true,\n result: result as unknown,\n } as AppProtocolSuccessResponseFrame;\n}\n\nfunction error(id: string, code: string, message: string): AppProtocolErrorResponseFrame {\n return {\n type: 'res',\n id,\n ok: false,\n error: { code, message },\n };\n}\n\ntype AppSession = NonNullable<ReturnType<AppQueryGateway['getSession']>>;\n\nexport type AppAgentListCommandFrame = AppProtocolCommandFrame<'agent.list'>;\nexport type AppSessionListCommandFrame = AppProtocolCommandFrame<'session.list'>;\nexport type AppMessageSendCommandFrame = AppProtocolCommandFrame<'message.send'>;\n\ntype AppMessageSendOutcome = {\n accepted: true;\n sessionId: string;\n messageId: string;\n};\ntype AppMessageSendRecord = {\n messageText: string;\n outcome: AppMessageSendOutcome;\n};\ntype AppMessageSendInFlight = {\n messageText: string;\n promise: Promise<AppMessageSendOutcome>;\n};\nexport type AppInteractionRespondCommandFrame = AppProtocolCommandFrame<'interaction.respond'>;\n\nexport type AppProtocolSessionCreateResponseFrame = AppProtocolSuccessResponseFrame<'session.create'>;\nexport type AppAgentListResponseFrame = AppProtocolSuccessResponseFrame<'agent.list'>;\nexport type AppSessionListResponseFrame = AppProtocolSuccessResponseFrame<'session.list'>;\nexport type AppMessageSendResponseFrame = AppProtocolSuccessResponseFrame<'message.send'>;\nexport type AppInteractionRespondResponseFrame = AppProtocolSuccessResponseFrame<'interaction.respond'>;\n","import type { AgentType } from '../../../core/adapter/types.js';\nimport type { Session } from '../../../core/session/Session.js';\nimport type { SessionInfo } from '../../../core/session/types.js';\n\nexport interface AppQueryAgent {\n id: AgentType;\n type: AgentType;\n title: string;\n enabled: boolean;\n available: boolean;\n default: boolean;\n capabilities: {\n chat: boolean;\n multiTurn: boolean;\n permission: boolean;\n question: boolean;\n streaming: boolean;\n };\n}\n\nexport interface AppQueryPendingInteraction {\n id: string;\n kind: string;\n title: string | null;\n}\n\nexport interface AppQueryMessage {\n id: string;\n role: string;\n content: string | null;\n createdAt: string | null;\n}\n\nexport interface AppQuerySessionSummary {\n id: string;\n agentId: AgentType;\n title: string | null;\n status: SessionInfo['status'];\n createdAt: string;\n updatedAt: string;\n lastMessageAt: string | null;\n messageCount: number | null;\n summary: string | null;\n pendingInteractionCount: number | null;\n metadata: {\n workspacePath: string | null;\n };\n}\n\nexport interface AppQuerySessionDetail {\n session: AppQuerySessionSummary;\n messages: AppQueryMessage[];\n pendingInteractions: AppQueryPendingInteraction[];\n}\n\nexport interface AppQueryGateway {\n listRegisteredAgents(): Array<{ token: string; agentType: AgentType }>;\n listSessions(filter?: { agentType?: AgentType; includeEnded?: boolean }): SessionInfo[];\n getSession(sessionId: string): Session | undefined;\n}\n\nexport interface AppQueryServiceDependencies {\n defaultAgentId?: AgentType;\n listMessages?: (sessionId: string) => AppQueryMessage[];\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[];\n}\n\nconst DEFAULT_CAPABILITIES = {\n chat: true,\n multiTurn: true,\n permission: true,\n question: true,\n streaming: false,\n} as const;\n\nexport class AppQueryService {\n constructor(\n private readonly gateway: AppQueryGateway,\n private readonly dependencies: AppQueryServiceDependencies = {},\n ) {}\n\n listAgents(): AppQueryAgent[] {\n const registrations = this.gateway.listRegisteredAgents();\n const agentTypes = [...new Set(registrations.map((registration) => registration.agentType))].sort() as AgentType[];\n const defaultAgentId = this.resolveDefaultAgentId(agentTypes);\n\n return agentTypes.map((agentType) => ({\n id: agentType,\n type: agentType,\n title: toAgentTitle(agentType),\n enabled: true,\n available: true,\n default: agentType === defaultAgentId,\n capabilities: { ...DEFAULT_CAPABILITIES },\n }));\n }\n\n listSessions(agentId: AgentType): AppQuerySessionSummary[] {\n return this.gateway\n .listSessions({ agentType: agentId, includeEnded: true })\n .slice()\n .sort((left, right) => right.updatedAt - left.updatedAt)\n .map((sessionInfo) => this.toSessionSummary(sessionInfo, this.gateway.getSession(sessionInfo.id)));\n }\n\n getSessionSummary(sessionId: string): AppQuerySessionSummary | null {\n return this.getSessionDetail(sessionId)?.session ?? null;\n }\n\n getSessionDetail(sessionId: string): AppQuerySessionDetail | null {\n const session = this.gateway.getSession(sessionId);\n const sessionInfo =\n (session ? session.toInfo() : undefined) ??\n this.gateway.listSessions({ includeEnded: true }).find((candidate) => candidate.id === sessionId);\n\n if (!sessionInfo) {\n return null;\n }\n\n const pendingInteractions = this.dependencies.listPendingInteractions?.(sessionId) ?? [];\n\n return {\n session: this.toSessionSummary(sessionInfo, session, pendingInteractions),\n messages: this.dependencies.listMessages?.(sessionId) ?? [],\n pendingInteractions,\n };\n }\n\n private toSessionSummary(\n sessionInfo: SessionInfo,\n session?: Session,\n pendingInteractions: AppQueryPendingInteraction[] = this.dependencies.listPendingInteractions?.(sessionInfo.id) ?? [],\n ): AppQuerySessionSummary {\n const metadata = session?.metadata ?? {};\n\n return {\n id: sessionInfo.id,\n agentId: sessionInfo.agentType,\n title: readString(metadata.title),\n status: session?.getStatus() ?? sessionInfo.status,\n createdAt: toIsoString(sessionInfo.createdAt),\n updatedAt: toIsoString(sessionInfo.updatedAt),\n lastMessageAt: null,\n messageCount: null,\n summary: readString(metadata.summary),\n pendingInteractionCount: this.dependencies.listPendingInteractions ? pendingInteractions.length : null,\n metadata: {\n workspacePath: readString(sessionInfo.cwd),\n },\n };\n }\n\n private resolveDefaultAgentId(agentTypes: AgentType[]): AgentType | undefined {\n if (this.dependencies.defaultAgentId && agentTypes.includes(this.dependencies.defaultAgentId)) {\n return this.dependencies.defaultAgentId;\n }\n\n if (agentTypes.length === 1) {\n return agentTypes[0];\n }\n\n return undefined;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction toIsoString(value: number): string {\n return new Date(value).toISOString();\n}\n\nfunction toAgentTitle(agentType: AgentType): string {\n return agentType\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join(' ');\n}\n","import { readdirSync, readFileSync } from 'fs';\nimport { join, extname, basename } from 'path';\nimport type { Logger } from 'pino';\nimport { getLogger } from '../../shared/logger.js';\nimport type { Gateway } from '../../gateway/index.js';\n\ninterface ClaudeSessionFile {\n pid: number;\n sessionId: string;\n cwd: string;\n startedAt: number;\n kind: string;\n entrypoint: string;\n}\n\nexport class SessionRecoveryService {\n private logger: Logger;\n private sessionsDir: string;\n\n constructor(sessionsDir: string = join(process.env.HOME || '', '.claude', 'sessions'), logger?: Logger) {\n this.sessionsDir = sessionsDir;\n this.logger = logger ?? getLogger();\n }\n\n /**\n * Scan Claude sessions directory and restore active sessions.\n * Only sessions with a live process (verified via kill -0) are restored.\n * Skip publish to avoid duplicate session:start notifications.\n */\n async recover(gateway: Gateway): Promise<void> {\n const files = this.listSessionFiles();\n if (files.length === 0) {\n this.logger.debug('No Claude session files found, nothing to recover');\n return;\n }\n\n this.logger.info({ count: files.length }, 'Scanning Claude sessions for recovery');\n let recovered = 0;\n let skippedDead = 0;\n\n for (const file of files) {\n const sessionData = this.parseSessionFile(file);\n if (!sessionData) {\n this.logger.warn({ file }, 'Failed to parse session file, skipping');\n continue;\n }\n\n if (!this.isProcessAlive(sessionData.pid)) {\n this.logger.debug({ sessionId: sessionData.sessionId, pid: sessionData.pid }, 'Claude process dead, skipping session recovery');\n skippedDead++;\n continue;\n }\n\n const existing = gateway.getSession(sessionData.sessionId);\n if (existing) {\n this.logger.debug({ sessionId: sessionData.sessionId }, 'Session already exists, skipping recovery');\n continue;\n }\n\n try {\n const agentRegistry = gateway.getAgentRegistry();\n const agents = agentRegistry.listRegisteredAgents();\n const claudeAgent = agents.find((a) => a.agentType === 'claude');\n if (!claudeAgent) {\n this.logger.warn('No claude agent registered, cannot recover sessions');\n continue;\n }\n\n await gateway.createSession(\n claudeAgent.token,\n sessionData.sessionId,\n { metadata: { kind: sessionData.kind, entrypoint: sessionData.entrypoint }, cwd: sessionData.cwd },\n true // skipPublishSessionStart — don't duplicate start notification\n );\n\n recovered++;\n this.logger.info(\n { sessionId: sessionData.sessionId, cwd: sessionData.cwd, pid: sessionData.pid },\n 'Session recovered from Claude sessions directory'\n );\n } catch (err) {\n this.logger.warn(\n { sessionId: sessionData.sessionId, error: err instanceof Error ? err.message : String(err) },\n 'Failed to recover session'\n );\n }\n }\n\n this.logger.info(\n { recovered, skippedDead, total: files.length },\n 'Session recovery complete'\n );\n }\n\n private listSessionFiles(): string[] {\n try {\n return readdirSync(this.sessionsDir)\n .filter((f) => extname(f) === '.json')\n .map((f) => join(this.sessionsDir, f));\n } catch (err) {\n this.logger.debug(\n { dir: this.sessionsDir, error: err instanceof Error ? err.message : String(err) },\n 'Could not read Claude sessions directory'\n );\n return [];\n }\n }\n\n private parseSessionFile(path: string): ClaudeSessionFile | null {\n try {\n const raw = readFileSync(path, 'utf-8');\n const data = JSON.parse(raw) as ClaudeSessionFile;\n if (!data.sessionId || typeof data.pid !== 'number') {\n return null;\n }\n return data;\n } catch (err) {\n this.logger.warn(\n { file: path, error: err instanceof Error ? err.message : String(err) },\n 'Failed to parse session file'\n );\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n if (pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n }\n}\n","#!/usr/bin/env node\n\nimport { writePidFile, removePidFile } from '../shared/pidfile.js';\nimport { setupFileLogging, getLogger, LogLevel, createAgentLogger, createChannelLogger } from '../shared/logger.js';\nimport { SessionLogger } from '../shared/session-logger.js';\nimport { type EventFrame, Gateway } from './index.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport { ClaudeHookAgentAdapter, ClaudeRemoteAgentAdapter } from '../adapters/agent/claude/index.js';\nimport { CodexAppAgentAdapter } from '../adapters/agent/codex/index.js';\nimport { AgentAdapterRegistry } from '../core/adapter/AgentAdapterRegistry.js';\nimport { Persistence } from '../shared/persistence.js';\nimport { HttpServer, setupRoutes } from '../server/http.js';\nimport { WebSocketServer, setupWebSocketHandlers, broadcastEvent } from '../server/websocket.js';\nimport { getHookToken } from '../shared/credentials.js';\n// Note: Old adapters removed - using new core/channel architecture via ChannelManager\nimport { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadConfig } from '../config.js';\n// Note: Notification system removed - using EventBus architecture now\nimport { EventBus } from '../core/bus/index.js';\nimport { ChannelManager } from '../core/channel/manager.js';\nimport { InboundRouter } from '../core/routing/index.js';\nimport { setupAllHandlers } from './handlers/index.js';\nimport { NotificationHandler } from './notification-handler.js';\nimport { BindingService } from '../core/binding/index.js';\nimport '../adapters/channels/index.js'; // Auto-register Channels\nimport { AppChannelWebSocketServer } from '../adapters/channels/app/server.js';\nimport { AppChannel } from '../adapters/channels/app/index.js';\nimport { createAppChannelProtocolHandler } from '../adapters/channels/app/protocol.js';\nimport { SessionRecoveryService } from '../core/session/SessionRecoveryService.js';\nimport { createRequire } from 'module';\n\nconst pkg = createRequire(import.meta.url)('../../package.json');\nconst VERSION = pkg.version as string;\n\nasync function main() {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n\n // Load configuration first\n const config = loadConfig();\n\n // Read environment variables (override config)\n const port = parseInt(process.env.HANDSOFF_PORT || String(config.general.hook_server_port), 10);\n const pidFilePath = process.env.HANDSOFF_PID_FILE || '';\n\n // Setup gateway file logging FIRST (before any other component initializes logger)\n const logLevel = (config.general.log_level as LogLevel) || LogLevel.INFO;\n const logFile = `${homedir}/.handsoff/logs/gateway.log`;\n setupFileLogging(logFile, logLevel);\n\n const logger = getLogger(logLevel);\n logger.info('Starting Handsoff Gateway...');\n\n try {\n // Load hook token from credentials\n const hookToken = getHookToken();\n if (!hookToken) {\n logger.error('Hook token not found. Please run \"handsoff init\" first.');\n process.exit(1);\n }\n logger.info(`Loaded hook token: ${hookToken.substring(0, 8)}...`);\n\n // Write PID file EARLY (right after token validation, before heavy initialization)\n // This allows parent process to detect that daemon has started\n if (pidFilePath) {\n writePidFile(pidFilePath, {\n pid: process.pid,\n port,\n startedAt: new Date().toISOString(),\n version: VERSION,\n token: hookToken,\n });\n logger.info(`PID file written to: ${pidFilePath}`);\n }\n\n // Create server components\n const httpServer = new HttpServer(port);\n const wsServer = new WebSocketServer(httpServer, { path: '/ws' });\n\n // Create gateway components\n const persistence = new Persistence(`${homedir}/.handsoff/sessions`);\n\n // Create InteractionQueue with config\n const interactionQueue = new InteractionQueue({\n timeoutMs: config.channel.permission?.timeout_ms,\n defaultOnTimeout: config.channel.permission?.default_on_timeout,\n });\n logger.info(`InteractionQueue initialized (timeout: ${config.channel.permission?.timeout_ms}ms, default: ${config.channel.permission?.default_on_timeout})`);\n\n // Create EventBus\n const bus = new EventBus();\n logger.info('EventBus initialized');\n\n bus.onInbound((message) => {\n if (message.targetAgent || message.systemCommand) {\n return;\n }\n\n logger.info(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n textPreview: message.text.slice(0, 120),\n senderId: message.sender.id,\n },\n '[Inbound] Message received from channel'\n );\n });\n\n // Start SessionLogger\n const sessionLogger = new SessionLogger(bus);\n sessionLogger.start();\n logger.info('SessionLogger started');\n\n // Create ChannelManager\n const channelManager = new ChannelManager(bus, logger);\n\n // Initialize Channels from config\n const channelsConfig: Record<string, { enabled: boolean; [key: string]: unknown }> = {};\n if (config.channel.logger) {\n channelsConfig.logger = {\n enabled: config.channel.logger.enabled !== false,\n notify_types: config.channel.logger.notify_types ?? ['permission_request', 'error'],\n };\n }\n if (config.channel.telegram) {\n channelsConfig.telegram = {\n enabled: config.channel.telegram.enabled && !!config.channel.telegram.bot_token,\n bot_token: config.channel.telegram.bot_token,\n allowed_users: config.channel.telegram.allowed_users,\n notify_types: config.channel.telegram.notify_types ?? ['permission_request', 'question_request', 'finished'],\n };\n }\n if (config.channel.feishu) {\n channelsConfig.feishu = {\n enabled: config.channel.feishu.enabled && !!config.channel.feishu.app_id,\n app_id: config.channel.feishu.app_id,\n app_secret: config.channel.feishu.app_secret,\n allowed_users: config.channel.feishu.allowed_users,\n notify_types: config.channel.feishu.notify_types ?? ['permission_request', 'question_request', 'finished', 'session_start', 'error'],\n };\n }\n channelManager.initializeFromConfig(channelsConfig);\n logger.info(`ChannelManager initialized with ${channelManager.count} channels`);\n\n // Start Channels\n await channelManager.startAll();\n logger.info('All channels started');\n\n // Start InboundRouter (after channels, before adapters)\n const inboundRouter = new InboundRouter(bus, logger);\n inboundRouter.start();\n logger.info('InboundRouter started');\n\n // Create InteractionService\n const interactionService = new InteractionService(interactionQueue, bus);\n\n // Create EventPublisher\n const eventPublisher = new EventPublisher(\n bus,\n (frame: EventFrame) => {\n broadcastEvent(wsServer, frame);\n },\n persistence\n );\n\n // Create Gateway\n const gateway = new Gateway(\n bus,\n interactionService,\n eventPublisher,\n logger\n );\n\n // Create shared BindingService instance (single source of truth for runtime binding lookups)\n const bindingService = new BindingService(logger);\n\n // Create NotificationHandler with lazy sessionAgentType lookup function\n let notificationHandler = new NotificationHandler(\n bus,\n logger,\n (id) => gateway.getSessionAgentType(id),\n bindingService\n );\n notificationHandler.start();\n logger.info('NotificationHandler started');\n\n gateway.getAgentRegistry().registerAgent('claude', hookToken);\n logger.info('Registered claude agent with persistent token');\n\n // Instantiate and initialize Codex adapter (conditional on config)\n let codexAdapter: CodexAppAgentAdapter | undefined;\n if (config.agent.codex?.enabled) {\n const codexToken = gateway.getAgentRegistry().registerAgent('codex');\n codexAdapter = new CodexAppAgentAdapter({\n bus,\n logger: createAgentLogger('codex'),\n bridge: gateway,\n token: codexToken,\n command: config.agent.codex.command,\n defaultWorkDir: config.agent.codex.work_dir || undefined,\n defaultModel: config.agent.codex.model || undefined,\n defaultApprovalPolicy: (config.agent.codex.approval_policy as import('../adapters/agent/codex/codexAppServerTypes.js').ApprovalPolicy) || undefined,\n });\n try {\n await codexAdapter.initialize();\n logger.info('Codex adapter initialized');\n } catch (err) {\n logger.warn({ error: err instanceof Error ? err.message : String(err) }, 'Codex adapter initialization failed, skipping');\n codexAdapter = undefined;\n }\n }\n\n // Setup handlers after gateway is created\n setupAllHandlers(bus, gateway, interactionQueue, logger);\n logger.info('Command and permission handlers setup complete');\n\n const claudeConfig = config.agent?.claude;\n const adapter = claudeConfig?.adapter === 'remote'\n ? new ClaudeRemoteAgentAdapter({\n logger: createAgentLogger('claude'),\n bus,\n bridge: gateway,\n token: hookToken,\n command: claudeConfig.binary ? [claudeConfig.binary] : undefined,\n defaultWorkDir: claudeConfig.work_dir,\n defaultModel: claudeConfig.model,\n defaultPermissionMode: claudeConfig.permission_mode as 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | undefined,\n })\n : new ClaudeHookAgentAdapter({\n logger: createAgentLogger('claude'),\n bus,\n bridge: gateway,\n token: hookToken,\n });\n try {\n await adapter.initialize();\n } catch (err) {\n logger.warn({ error: err instanceof Error ? err.message : String(err) }, 'Claude adapter initialization failed, skipping');\n // Continue without Claude adapter; routes and WS handlers will operate without it\n }\n // Register adapters in AgentAdapterRegistry so SessionManager can discover them\n AgentAdapterRegistry.getInstance().register(adapter);\n if (codexAdapter) {\n AgentAdapterRegistry.getInstance().register(codexAdapter);\n }\n logger.info('Adapters registered in AgentAdapterRegistry');\n\n // Recover active Claude sessions from ~/.claude/sessions/\n const recoveryService = new SessionRecoveryService();\n await recoveryService.recover(gateway);\n\n setupRoutes(httpServer, gateway, () => wsServer.getClientCount());\n setupWebSocketHandlers(wsServer, gateway, { interactionQueue });\n\n let appWebSocketServer: AppChannelWebSocketServer | undefined;\n\n // Setup signal handlers for graceful shutdown\n const shutdown = async (signal: string) => {\n logger.info(`Received ${signal}, shutting down gracefully...`);\n inboundRouter.stop();\n notificationHandler.stop();\n sessionLogger.stop();\n if (codexAdapter) {\n await codexAdapter.shutdown();\n }\n if (appWebSocketServer) {\n await appWebSocketServer.stop();\n }\n await adapter.shutdown();\n await channelManager.stopAll();\n await wsServer.stop();\n await httpServer.stop();\n if (pidFilePath) {\n removePidFile(pidFilePath);\n }\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n\n // Start servers\n await httpServer.start();\n await wsServer.start();\n\n // Start App Channel WebSocket server if enabled\n if (config.channel?.app?.enabled) {\n appWebSocketServer = new AppChannelWebSocketServer(httpServer, gateway, {\n protocolHandler: createAppChannelProtocolHandler({\n gateway: gateway as import('../adapters/channels/app/protocol.js').AppProtocolGateway,\n bus: {\n publishInteractionResponse: (response) => {\n bus.publishInteractionResponse(response);\n },\n },\n listPendingInteractions: (sessionId) =>\n interactionQueue\n .listPending()\n .filter((p) => p.sessionId === sessionId)\n .map((p) => ({\n id: p.requestId,\n kind: p.type,\n title: p.toolName,\n })),\n }),\n });\n await appWebSocketServer.start();\n\n const appChannel = new AppChannel(\n {\n enabled: true,\n channel_id: config.channel.app.channel_id,\n auth_token: config.channel.app.auth_token,\n heartbeat_interval_ms: config.channel.app.heartbeat_interval_ms,\n notify_types: config.channel.app.notify_types ?? ['*'],\n transport: {\n sendEvent: (channelId: string, event: import('../adapters/channels/app/mapper.js').AppMappedOutboundEvent) => {\n appWebSocketServer?.broadcastToChannel(channelId, event as import('../adapters/channels/app/types.js').AppProtocolEventFrame);\n },\n },\n },\n bus,\n createChannelLogger('app'),\n );\n await appChannel.start();\n channelManager.register(appChannel);\n logger.info('[AppChannel] App channel registered and started');\n }\n\n logger.info(`Handsoff Gateway running on port ${port}`);\n\n // Handle unhandled rejections to prevent silent crashes\n process.on('unhandledRejection', (reason, promise) => {\n // Ignore pino worker thread errors - they're benign\n const reasonStr = String(reason);\n if (reasonStr.includes('worker has exited') || reasonStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${reasonStr}`);\n return;\n }\n logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`);\n });\n\n // Handle uncaught exceptions\n process.on('uncaughtException', (error) => {\n // Ignore pino worker thread errors\n const errorStr = error.message || String(error);\n if (errorStr.includes('worker has exited') || errorStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${errorStr}`);\n return;\n }\n logger.error(`Uncaught Exception: ${error.message}`);\n if (error.stack) {\n logger.error(error.stack);\n }\n });\n\n // Keep process alive using setTimeout loop (not unref'd to keep event loop active)\n const keepProcessAlive = () => {\n setTimeout(keepProcessAlive, 60000);\n };\n keepProcessAlive();\n } catch (error) {\n logger.error({ error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }, 'Failed to start Gateway');\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","homedir","logger","readFileSync","existsSync","i","acc","ext","start","final","ext","qmark","star","regExpEscape","i","match","existsSync","readFileSync","error","path","logger","logger","filter","match","t","error","randomUUID","logger","join","resolve","existsSync","resolve","error","error","resolve","existsSync","resolve","randomUUID","randomUUID","spawn","createInterface","path","error","filter","defaults","resolve","match","randomUUID","readdir","readFile","join","existsSync","match","logger","path","resolve","error","match","URL","VERSION","logger","path","resolve","URL","error","filter","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","join","path","existsSync","readFileSync","error","randomUUID","randomUUID","resolve","error","readFileSync","existsSync","join","homedir","error","logger","error","resolve","writeFileSync","join","homedir","TOML","logger","logger","logger","error","logger","logger","oldChannelId","bindingService","bindingService","process","formatDuration","logger","logger","logger","logger","bindingService","logger","logger","error","resolve","_a","logger","error","requestId","allowedUsersForRequest","options","_init","_a","logger","error","match","REQUEST_ID_REGEX","_init","_a","logger","error","_init","_a","logger","WebSocket","logger","resolve","error","WebSocket","randomUUID","randomUUID","error","isRecord","readString","readdirSync","readFileSync","join","join","logger","readdirSync","path","readFileSync","VERSION","homedir","logger","bindingService","error"]}
1
+ {"version":3,"sources":["../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js","../../src/adapters/channels/feishu/templates/message.ts","../../src/adapters/channels/feishu/templates/permission.ts","../../src/adapters/channels/feishu/templates/question.ts","../../src/gateway/process.ts","../../src/shared/pidfile.ts","../../src/shared/logger.ts","../../src/shared/session-logger.ts","../../src/gateway/index.ts","../../src/core/agent/AgentRegistry.ts","../../src/core/session/SessionManager.ts","../../src/core/adapter/AgentAdapterRegistry.ts","../../src/core/session/Session.ts","../../src/gateway/events.ts","../../src/gateway/interaction-service.ts","../../src/shared/permissions.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/index.ts","../../node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/src/index.ts","../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/src/index.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/assert-valid-pattern.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/ast.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/brace-expressions.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/unescape.ts","../../node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/src/escape.ts","../../src/gateway/publisher.ts","../../src/adapters/agent/claude/index.ts","../../src/adapters/agent/claude/ClaudeHookAgentAdapter.ts","../../src/core/agent/BaseAgentAdapter.ts","../../src/core/agent/inbound-utils.ts","../../src/core/agent/EventNormalizer.ts","../../src/core/agent/interaction-utils.ts","../../src/adapters/agent/claude/jsonl-reader.ts","../../src/adapters/agent/claude/ClaudeRemoteAgentAdapter.ts","../../src/core/agent/TurnAggregator.ts","../../src/core/session-scanner/index.ts","../../src/core/session-scanner/types.ts","../../src/core/session-scanner/registry.ts","../../src/adapters/agent/claude/scanner.ts","../../src/adapters/agent/claude/sdk/query.ts","../../src/adapters/agent/claude/sdk/stream.ts","../../src/adapters/agent/claude/sdk/types.ts","../../src/adapters/agent/claude/hook-types.ts","../../src/adapters/agent/codex/index.ts","../../src/adapters/agent/codex/CodexAppAgentAdapter.ts","../../src/adapters/agent/codex/codexAppServerClient.ts","../../src/adapters/agent/codex/codexAppServerTypes.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/shared/credentials.ts","../../src/adapters/interaction/index.ts","../../src/adapters/interaction/types.ts","../../src/adapters/interaction/queue.ts","../../src/config.ts","../../src/core/bus/index.ts","../../src/core/bus/types.ts","../../src/core/bus/events.ts","../../src/core/channel/manager.ts","../../src/core/channel/registry.ts","../../src/core/routing/index.ts","../../src/core/routing/InboundRouter.ts","../../src/core/binding/index.ts","../../src/core/binding/BindingService.ts","../../src/core/command/routing.ts","../../src/gateway/handlers/index.ts","../../src/gateway/handlers/command.ts","../../src/core/command/index.ts","../../src/core/command/types.ts","../../src/core/command/executor.ts","../../src/core/command/parser.ts","../../src/core/command/builtin/index.ts","../../src/core/command/builtin/bind.ts","../../src/core/command/builtin/help.ts","../../src/core/command/builtin/session.ts","../../src/core/command/builtin/start.ts","../../src/core/command/builtin/system.ts","../../src/gateway/handlers/permission.ts","../../src/gateway/notification-handler.ts","../../src/adapters/channels/index.ts","../../src/adapters/channels/telegram/index.ts","../../src/core/channel/base.ts","../../src/adapters/channels/telegram/bot.ts","../../src/adapters/channels/telegram/formatter.ts","../../src/gateway/notification-context.ts","../../src/i18n/index.ts","../../src/i18n/types.ts","../../src/i18n/locales/en.ts","../../src/shared/format.ts","../../src/shared/channelInstance.ts","../../src/adapters/channels/logger/index.ts","../../src/adapters/channels/feishu/index.ts","../../src/adapters/channels/feishu/client.ts","../../src/adapters/channels/feishu/formatter.ts","../../src/adapters/channels/app/index.ts","../../src/adapters/channels/app/mapper.ts","../../src/adapters/channels/app/server.ts","../../src/adapters/channels/app/protocol.ts","../../src/adapters/channels/app/query-service.ts","../../src/core/session/SessionRecoveryService.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","/**\n * Message card builder\n * Header + content + hr + meta footer\n */\n\nexport interface MessageCardInput {\n title: string;\n content: string;\n meta?: string;\n thinking?: string;\n}\n\nexport function buildMessageCard(input: MessageCardInput): string {\n const elements: unknown[] = [];\n\n // TODO(future): Enable thinking collapsible panel when we decide to surface\n // thinking content separately from the main message. Currently thinking is\n // folded into content or ignored. The collapsible_panel tag below is the\n // correct Feishu schema — do NOT delete this block. When enabling:\n // 1. Uncomment the block\n // 2. Ensure input.thinking is populated from TurnFinishedContext.thinking\n // 3. Remove thinking from content so it doesn't duplicate\n // 4. Verify old Feishu clients silently ignore unknown tags (they do)\n //\n // Status: INTENTIONALLY DISABLED — not a bug, not a TODO to fix now.\n /*\n if (input.thinking?.trim()) {\n elements.push({\n tag: 'collapsible_panel',\n expanded: false,\n header: {\n title: { tag: 'plain_text', content: '🧠 Thinking' },\n vertical_align: 'center',\n icon: {\n tag: 'standard_icon',\n token: 'down-small-ccm_outlined',\n size: '16px 16px',\n },\n icon_position: 'follow_text',\n icon_expanded_angle: -180,\n },\n vertical_spacing: '8px',\n padding: '8px 8px 8px 8px',\n elements: [\n {\n tag: 'markdown',\n content: input.thinking,\n text_align: 'left',\n text_size: 'normal',\n margin: '0px 0px 0px 0px',\n },\n ],\n });\n }\n */\n\n elements.push({\n tag: 'markdown',\n content: input.content,\n text_align: 'left',\n text_size: 'normal',\n margin: '0px 0px 0px 0px',\n });\n\n if (input.meta) {\n elements.push({ tag: 'hr', margin: '0px 0px 0px 0px' });\n elements.push({\n tag: 'column_set',\n flex_mode: 'stretch',\n horizontal_spacing: '8px',\n horizontal_align: 'left',\n columns: [\n {\n tag: 'column',\n width: 'weighted',\n elements: [\n {\n tag: 'markdown',\n content: input.meta,\n text_align: 'left',\n text_size: 'notation',\n margin: '0px 0px 0px 0px',\n icon: {\n tag: 'standard_icon',\n token: 'ccm-filter_outlined',\n color: 'grey',\n },\n },\n ],\n vertical_spacing: '8px',\n horizontal_align: 'left',\n vertical_align: 'center',\n weight: 1,\n },\n ],\n margin: '0px 0px 0px 0px',\n });\n }\n\n const card = {\n schema: '2.0',\n config: { update_multi: true },\n body: {\n direction: 'vertical',\n elements,\n },\n header: {\n title: {\n tag: 'plain_text',\n content: input.title,\n },\n subtitle: {\n tag: 'plain_text',\n content: '',\n },\n template: 'blue',\n padding: '12px 8px 12px 8px',\n },\n };\n\n return JSON.stringify(card);\n}\n","import type { PermissionButtonDef } from '../types.js';\n\nexport interface PermissionCardInput {\n title: string;\n content: string;\n buttons: PermissionButtonDef[];\n}\n\nexport function buildPermissionCard(input: PermissionCardInput): string {\n const columns = input.buttons.map((btn) => {\n const buttonEl: Record<string, unknown> = {\n tag: 'button',\n text: { tag: 'plain_text', content: btn.text },\n type: btn.type,\n width: 'default',\n size: 'small',\n behaviors: [\n {\n type: 'callback',\n value: { action: btn.value },\n },\n ],\n };\n if (btn.confirm) {\n buttonEl.confirm = {\n title: { tag: 'plain_text', content: btn.confirm.title },\n text: { tag: 'plain_text', content: btn.confirm.text },\n };\n }\n return {\n tag: 'column',\n width: 'auto',\n elements: [buttonEl],\n padding: '0px 0px 0px 0px',\n direction: 'horizontal',\n horizontal_spacing: '4px',\n vertical_spacing: '4px',\n horizontal_align: 'center',\n vertical_align: 'center',\n margin: '0px 0px 0px 0px',\n };\n });\n\n const card = {\n schema: '2.0',\n config: { update_multi: true },\n body: {\n direction: 'vertical',\n elements: [\n {\n tag: 'markdown',\n content: input.content,\n text_align: 'left',\n text_size: 'normal',\n margin: '0px 0px 0px 0px',\n },\n { tag: 'hr', margin: '0px 0px 0px 0px' },\n {\n tag: 'column_set',\n horizontal_spacing: '4px',\n horizontal_align: 'left',\n columns,\n margin: '0px 0px 0px 0px',\n },\n ],\n },\n header: {\n title: { tag: 'plain_text', content: input.title },\n subtitle: { tag: 'plain_text', content: '' },\n template: 'blue',\n padding: '12px 8px 12px 8px',\n },\n };\n\n return JSON.stringify(card);\n}\n","import type { QuestionItem, QuestionMode } from '../types.js';\n\nexport interface QuestionCardInput {\n title: string;\n content: string;\n mode: QuestionMode;\n items: QuestionItem[];\n requestId?: string;\n}\n\nexport function buildQuestionCard(input: QuestionCardInput): string {\n const elements: unknown[] = [\n {\n tag: 'markdown',\n content: input.content,\n text_align: 'left',\n text_size: 'normal',\n margin: '0px 0px 0px 0px',\n },\n { tag: 'hr', margin: '0px 0px 0px 0px' },\n ];\n\n if (input.mode === 'single') {\n const columns = input.items.map((item) => ({\n tag: 'column',\n width: 'auto',\n elements: [\n {\n tag: 'button',\n text: { tag: 'plain_text', content: item.label },\n hover_tips: { tag: 'plain_text', content: item.label },\n type: 'primary',\n width: 'default',\n size: 'small',\n behaviors: [\n {\n type: 'callback',\n value: { action: 'select', optionId: item.id, requestId: input.requestId },\n },\n ],\n },\n ],\n padding: '0px 0px 0px 0px',\n direction: 'horizontal',\n horizontal_spacing: '4px',\n vertical_spacing: '4px',\n horizontal_align: 'center',\n vertical_align: 'center',\n margin: '0px 0px 0px 0px',\n }));\n\n elements.push({\n tag: 'column_set',\n horizontal_spacing: '4px',\n horizontal_align: 'left',\n columns,\n margin: '0px 0px 0px 0px',\n });\n } else {\n // Multi-select: checkers on the left, Submit on the right\n const checkerElements = input.items.map((item) => ({\n tag: 'checker',\n element_id: `checker_${item.id}`,\n name: `checker_${item.id}`,\n checked: false,\n text: { tag: 'plain_text', content: item.label },\n behaviors: [\n {\n type: 'callback',\n value: { action: 'check', optionId: item.id, requestId: input.requestId },\n },\n ],\n }));\n\n elements.push({\n tag: 'column_set',\n horizontal_spacing: '4px',\n horizontal_align: 'left',\n columns: [\n {\n tag: 'column',\n width: 'weighted',\n elements: checkerElements,\n padding: '0px 0px 0px 0px',\n direction: 'horizontal',\n horizontal_spacing: '4px',\n vertical_spacing: '4px',\n horizontal_align: 'left',\n vertical_align: 'center',\n margin: '0px 0px 0px 0px',\n weight: 1,\n },\n {\n tag: 'column',\n width: 'auto',\n elements: [\n {\n tag: 'button',\n text: { tag: 'plain_text', content: 'Submit' },\n type: 'primary_filled',\n width: 'default',\n size: 'small',\n margin: '0px 0px 0px 0px',\n behaviors: [\n {\n type: 'callback',\n value: { action: 'submit', requestId: input.requestId },\n },\n ],\n },\n ],\n padding: '0px 0px 0px 0px',\n direction: 'vertical',\n horizontal_spacing: '8px',\n vertical_spacing: '8px',\n horizontal_align: 'right',\n vertical_align: 'center',\n margin: '0px 0px 0px 0px',\n },\n ],\n margin: '0px 0px 0px 0px',\n });\n }\n\n const card = {\n schema: '2.0',\n config: { update_multi: true },\n body: {\n direction: 'vertical',\n elements,\n },\n header: {\n title: { tag: 'plain_text', content: input.title },\n subtitle: { tag: 'plain_text', content: '' },\n template: 'blue',\n padding: '12px 8px 12px 8px',\n },\n };\n\n return JSON.stringify(card);\n}\n","#!/usr/bin/env node\n\nimport { writePidFile, removePidFile } from '../shared/pidfile.js';\nimport { setupFileLogging, getLogger, LogLevel, createAgentLogger, createChannelLogger } from '../shared/logger.js';\nimport { SessionLogger } from '../shared/session-logger.js';\nimport { type EventFrame, Gateway } from './index.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport { ClaudeHookAgentAdapter, ClaudeRemoteAgentAdapter } from '../adapters/agent/claude/index.js';\nimport { CodexAppAgentAdapter } from '../adapters/agent/codex/index.js';\nimport { AgentAdapterRegistry } from '../core/adapter/AgentAdapterRegistry.js';\nimport { Persistence } from '../shared/persistence.js';\nimport { HttpServer, setupRoutes } from '../server/http.js';\nimport { WebSocketServer, setupWebSocketHandlers, broadcastEvent } from '../server/websocket.js';\nimport { getHookToken } from '../shared/credentials.js';\n// Note: Old adapters removed - using new core/channel architecture via ChannelManager\nimport { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadConfig } from '../config.js';\n// Note: Notification system removed - using EventBus architecture now\nimport { EventBus } from '../core/bus/index.js';\nimport { ChannelManager } from '../core/channel/manager.js';\nimport { InboundRouter } from '../core/routing/index.js';\nimport { setupAllHandlers } from './handlers/index.js';\nimport { NotificationHandler } from './notification-handler.js';\nimport { BindingService } from '../core/binding/index.js';\nimport '../adapters/channels/index.js'; // Auto-register Channels\nimport { AppChannelWebSocketServer } from '../adapters/channels/app/server.js';\nimport { AppChannel } from '../adapters/channels/app/index.js';\nimport { createAppChannelProtocolHandler } from '../adapters/channels/app/protocol.js';\nimport { SessionRecoveryService } from '../core/session/SessionRecoveryService.js';\nimport { createRequire } from 'module';\n\nconst pkg = createRequire(import.meta.url)('../../package.json');\nconst VERSION = pkg.version as string;\n\nasync function main() {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n\n // Load configuration first\n const config = loadConfig();\n\n // Read environment variables (override config)\n const port = parseInt(process.env.HANDSOFF_PORT || String(config.general.hook_server_port), 10);\n const pidFilePath = process.env.HANDSOFF_PID_FILE || '';\n\n // Setup gateway file logging FIRST (before any other component initializes logger)\n const logLevel = (config.general.log_level as LogLevel) || LogLevel.INFO;\n const logFile = `${homedir}/.handsoff/logs/gateway.log`;\n setupFileLogging(logFile, logLevel);\n\n const logger = getLogger(logLevel);\n logger.info('Starting Handsoff Gateway...');\n\n try {\n // Load hook token from credentials\n const hookToken = getHookToken();\n if (!hookToken) {\n logger.error('Hook token not found. Please run \"handsoff init\" first.');\n process.exit(1);\n }\n logger.info(`Loaded hook token: ${hookToken.substring(0, 8)}...`);\n\n // Write PID file EARLY (right after token validation, before heavy initialization)\n // This allows parent process to detect that daemon has started\n if (pidFilePath) {\n writePidFile(pidFilePath, {\n pid: process.pid,\n port,\n startedAt: new Date().toISOString(),\n version: VERSION,\n token: hookToken,\n });\n logger.info(`PID file written to: ${pidFilePath}`);\n }\n\n // Create server components\n const httpServer = new HttpServer(port);\n const wsServer = new WebSocketServer(httpServer, { path: '/ws' });\n\n // Create gateway components\n const persistence = new Persistence(`${homedir}/.handsoff/sessions`);\n\n // Create InteractionQueue with config\n const interactionQueue = new InteractionQueue({\n timeoutMs: config.channel.permission?.timeout_ms,\n defaultOnTimeout: config.channel.permission?.default_on_timeout,\n });\n logger.info(`InteractionQueue initialized (timeout: ${config.channel.permission?.timeout_ms}ms, default: ${config.channel.permission?.default_on_timeout})`);\n\n // Create EventBus\n const bus = new EventBus();\n logger.info('EventBus initialized');\n\n bus.onInbound((message) => {\n if (message.targetAgent || message.systemCommand) {\n return;\n }\n\n logger.info(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n textPreview: message.text.slice(0, 120),\n senderId: message.sender.id,\n },\n '[Inbound] Message received from channel'\n );\n });\n\n // Start SessionLogger\n const sessionLogger = new SessionLogger(bus);\n sessionLogger.start();\n logger.info('SessionLogger started');\n\n // Create ChannelManager\n const channelManager = new ChannelManager(bus, logger);\n\n // Initialize Channels from config\n const channelsConfig: Record<string, { enabled: boolean; [key: string]: unknown }> = {};\n if (config.channel.logger) {\n channelsConfig.logger = {\n enabled: config.channel.logger.enabled !== false,\n notify_types: config.channel.logger.notify_types ?? ['permission_request', 'error'],\n };\n }\n if (config.channel.telegram) {\n channelsConfig.telegram = {\n enabled: config.channel.telegram.enabled && !!config.channel.telegram.bot_token,\n bot_token: config.channel.telegram.bot_token,\n allowed_users: config.channel.telegram.allowed_users,\n notify_types: config.channel.telegram.notify_types ?? ['permission_request', 'question_request', 'finished'],\n };\n }\n if (config.channel.feishu) {\n channelsConfig.feishu = {\n enabled: config.channel.feishu.enabled && !!config.channel.feishu.app_id,\n app_id: config.channel.feishu.app_id,\n app_secret: config.channel.feishu.app_secret,\n allowed_users: config.channel.feishu.allowed_users,\n notify_types: config.channel.feishu.notify_types ?? ['permission_request', 'question_request', 'finished', 'session_start', 'error'],\n };\n }\n channelManager.initializeFromConfig(channelsConfig);\n logger.info(`ChannelManager initialized with ${channelManager.count} channels`);\n\n // Start Channels\n await channelManager.startAll();\n logger.info('All channels started');\n\n // Start InboundRouter (after channels, before adapters)\n const inboundRouter = new InboundRouter(bus, logger);\n inboundRouter.start();\n logger.info('InboundRouter started');\n\n // Create InteractionService\n const interactionService = new InteractionService(interactionQueue, bus);\n\n // Create EventPublisher\n const eventPublisher = new EventPublisher(\n bus,\n (frame: EventFrame) => {\n broadcastEvent(wsServer, frame);\n },\n persistence\n );\n\n // Create Gateway\n const gateway = new Gateway(\n bus,\n interactionService,\n eventPublisher,\n logger\n );\n\n // Create shared BindingService instance (single source of truth for runtime binding lookups)\n const bindingService = new BindingService(logger);\n\n // Create NotificationHandler with lazy sessionAgentType lookup function\n let notificationHandler = new NotificationHandler(\n bus,\n logger,\n (id) => gateway.getSessionAgentType(id),\n (id) => gateway.getSessionInfo(id),\n bindingService\n );\n notificationHandler.start();\n logger.info('NotificationHandler started');\n\n gateway.getAgentRegistry().registerAgent('claude', hookToken);\n logger.info('Registered claude agent with persistent token');\n\n // Instantiate and initialize Codex adapter (conditional on config)\n let codexAdapter: CodexAppAgentAdapter | undefined;\n if (config.agent.codex?.enabled) {\n const codexToken = gateway.getAgentRegistry().registerAgent('codex');\n codexAdapter = new CodexAppAgentAdapter({\n bus,\n logger: createAgentLogger('codex'),\n bridge: gateway,\n token: codexToken,\n command: config.agent.codex.command,\n defaultWorkDir: config.agent.codex.work_dir || undefined,\n defaultModel: config.agent.codex.model || undefined,\n defaultApprovalPolicy: (config.agent.codex.approval_policy as import('../adapters/agent/codex/codexAppServerTypes.js').ApprovalPolicy) || undefined,\n });\n try {\n await codexAdapter.initialize();\n logger.info('Codex adapter initialized');\n } catch (err) {\n logger.warn({ error: err instanceof Error ? err.message : String(err) }, 'Codex adapter initialization failed, skipping');\n codexAdapter = undefined;\n }\n }\n\n // Setup handlers after gateway is created\n setupAllHandlers(bus, gateway, interactionQueue, logger);\n logger.info('Command and permission handlers setup complete');\n\n const claudeConfig = config.agent?.claude;\n const adapter = claudeConfig?.adapter === 'remote'\n ? new ClaudeRemoteAgentAdapter({\n logger: createAgentLogger('claude'),\n bus,\n bridge: gateway,\n token: hookToken,\n command: claudeConfig.binary ? [claudeConfig.binary] : undefined,\n defaultWorkDir: claudeConfig.work_dir,\n defaultModel: claudeConfig.model,\n defaultPermissionMode: claudeConfig.permission_mode as 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | undefined,\n })\n : new ClaudeHookAgentAdapter({\n logger: createAgentLogger('claude'),\n bus,\n bridge: gateway,\n token: hookToken,\n });\n try {\n await adapter.initialize();\n } catch (err) {\n logger.warn({ error: err instanceof Error ? err.message : String(err) }, 'Claude adapter initialization failed, skipping');\n // Continue without Claude adapter; routes and WS handlers will operate without it\n }\n // Register adapters in AgentAdapterRegistry so SessionManager can discover them\n AgentAdapterRegistry.getInstance().register(adapter);\n if (codexAdapter) {\n AgentAdapterRegistry.getInstance().register(codexAdapter);\n }\n logger.info('Adapters registered in AgentAdapterRegistry');\n\n // Recover active Claude sessions from ~/.claude/sessions/\n const recoveryService = new SessionRecoveryService();\n await recoveryService.recover(gateway);\n\n setupRoutes(httpServer, gateway, () => wsServer.getClientCount());\n setupWebSocketHandlers(wsServer, gateway, { interactionQueue });\n\n let appWebSocketServer: AppChannelWebSocketServer | undefined;\n\n // Setup signal handlers for graceful shutdown\n const shutdown = async (signal: string) => {\n logger.info(`Received ${signal}, shutting down gracefully...`);\n inboundRouter.stop();\n notificationHandler.stop();\n sessionLogger.stop();\n if (codexAdapter) {\n await codexAdapter.shutdown();\n }\n if (appWebSocketServer) {\n await appWebSocketServer.stop();\n }\n await adapter.shutdown();\n await channelManager.stopAll();\n await wsServer.stop();\n await httpServer.stop();\n if (pidFilePath) {\n removePidFile(pidFilePath);\n }\n process.exit(0);\n };\n\n process.on('SIGTERM', () => shutdown('SIGTERM'));\n process.on('SIGINT', () => shutdown('SIGINT'));\n\n // Start servers\n await httpServer.start();\n await wsServer.start();\n\n // Start App Channel WebSocket server if enabled\n if (config.channel?.app?.enabled) {\n appWebSocketServer = new AppChannelWebSocketServer(httpServer, gateway, {\n protocolHandler: createAppChannelProtocolHandler({\n gateway: gateway as import('../adapters/channels/app/protocol.js').AppProtocolGateway,\n bus: {\n publishInteractionResponse: (response) => {\n bus.publishInteractionResponse(response);\n },\n },\n listPendingInteractions: (sessionId) =>\n interactionQueue\n .listPending()\n .filter((p) => p.sessionId === sessionId)\n .map((p) => ({\n id: p.requestId,\n kind: p.type,\n title: p.toolName,\n })),\n }),\n });\n await appWebSocketServer.start();\n\n const appChannel = new AppChannel(\n {\n enabled: true,\n channel_id: config.channel.app.channel_id,\n auth_token: config.channel.app.auth_token,\n heartbeat_interval_ms: config.channel.app.heartbeat_interval_ms,\n notify_types: config.channel.app.notify_types ?? ['*'],\n transport: {\n sendEvent: (channelId: string, event: import('../adapters/channels/app/mapper.js').AppMappedOutboundEvent) => {\n appWebSocketServer?.broadcastToChannel(channelId, event as import('../adapters/channels/app/types.js').AppProtocolEventFrame);\n },\n },\n },\n bus,\n createChannelLogger('app'),\n );\n await appChannel.start();\n channelManager.register(appChannel);\n logger.info('[AppChannel] App channel registered and started');\n }\n\n logger.info(`Handsoff Gateway running on port ${port}`);\n\n // Handle unhandled rejections to prevent silent crashes\n process.on('unhandledRejection', (reason, promise) => {\n // Ignore pino worker thread errors - they're benign\n const reasonStr = String(reason);\n if (reasonStr.includes('worker has exited') || reasonStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${reasonStr}`);\n return;\n }\n logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`);\n });\n\n // Handle uncaught exceptions\n process.on('uncaughtException', (error) => {\n // Ignore pino worker thread errors\n const errorStr = error.message || String(error);\n if (errorStr.includes('worker has exited') || errorStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${errorStr}`);\n return;\n }\n logger.error(`Uncaught Exception: ${error.message}`);\n if (error.stack) {\n logger.error(error.stack);\n }\n });\n\n // Keep process alive using setTimeout loop (not unref'd to keep event loop active)\n const keepProcessAlive = () => {\n setTimeout(keepProcessAlive, 60000);\n };\n keepProcessAlive();\n } catch (error) {\n logger.error({ error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }, 'Failed to start Gateway');\n process.exit(1);\n }\n}\n\nmain();\n","import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { mkdirSync } from 'fs';\n\nexport interface PidFileData {\n pid: number;\n port: number;\n startedAt: string;\n version?: string;\n agents?: string[];\n channels?: string[];\n token?: string;\n}\n\nexport function writePidFile(pidFilePath: string, data: PidFileData): void {\n // Validate pid is a positive integer\n if (!Number.isInteger(data.pid) || data.pid <= 0) {\n throw new TypeError(`Invalid pid: ${data.pid}. Must be a positive integer.`);\n }\n\n // Validate port is a positive integer between 1-65535\n if (!Number.isInteger(data.port) || data.port < 1 || data.port > 65535) {\n throw new TypeError(`Invalid port: ${data.port}. Must be an integer between 1 and 65535.`);\n }\n\n mkdirSync(dirname(pidFilePath), { recursive: true });\n writeFileSync(pidFilePath, JSON.stringify(data, null, 2));\n}\n\nexport function readPidFile(pidFilePath: string): PidFileData | null {\n if (!existsSync(pidFilePath)) {\n return null;\n }\n try {\n const content = readFileSync(pidFilePath, 'utf-8');\n return JSON.parse(content) as PidFileData;\n } catch {\n return null;\n }\n}\n\nexport function removePidFile(pidFilePath: string): void {\n if (existsSync(pidFilePath)) {\n unlinkSync(pidFilePath);\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import pino from 'pino';\nimport { mkdirSync, existsSync, appendFileSync } from 'fs';\nimport { dirname } from 'path';\nimport { hostname } from 'os';\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\nlet fileLogger: pino.Logger | null = null;\nlet consoleLogger: pino.Logger | null = null;\nlet currentLogLevel: LogLevel = LogLevel.INFO;\n\nfunction createSyncLogger(logFilePath: string, minLevel: LogLevel = LogLevel.INFO): pino.Logger {\n const hostnameValue = hostname();\n\n const writeLog = (level: string, msg: string, obj?: object) => {\n try {\n const logDir = dirname(logFilePath);\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n const logEntry: Record<string, unknown> = {\n level,\n time: Date.now(),\n msg,\n pid: process.pid,\n hostname: hostnameValue,\n ...obj,\n };\n const line = JSON.stringify(logEntry) + '\\n';\n appendFileSync(logFilePath, line);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`[Logger] Failed to write to ${logFilePath}:`, err);\n }\n };\n\n const log = (logLevel: string) => {\n const minLevelNum = LOG_LEVEL_MAP[minLevel] ?? LOG_LEVEL_MAP.info;\n const callLevelNum = LOG_LEVEL_MAP[logLevel] ?? LOG_LEVEL_MAP.info;\n return (obj: object | string, msg?: string) => {\n if (callLevelNum < minLevelNum) return;\n if (typeof obj === 'string') {\n writeLog(logLevel, obj);\n } else {\n writeLog(logLevel, msg || '', obj);\n }\n };\n };\n\n const createChild = (_bindings: object): pino.Logger => {\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n };\n\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n\nexport function setupFileLogging(logFilePath: string, level: LogLevel = LogLevel.INFO): pino.Logger {\n currentLogLevel = level;\n fileLogger = createSyncLogger(logFilePath, level);\n return fileLogger;\n}\n\nexport function getFileLogger(): pino.Logger | null {\n return fileLogger;\n}\n\nexport function createChannelLogger(channelName: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/channels/${channelName}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createAgentLogger(agentType: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/agents/${agentType}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createSessionLogger(sessionId: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const date = new Date().toISOString().split('T')[0];\n const logFile = `${homedir}/.handsoff/logs/sessions/${date}/${sessionId}.jsonl`;\n\n // Session logs are always written (NDJSON timeline), ignore currentLogLevel\n return createSyncLogger(logFile, LogLevel.DEBUG);\n}\n\nexport function getLogger(_level?: LogLevel): pino.Logger {\n if (!consoleLogger) {\n // Prefer fileLogger's level if set, otherwise use provided level or default to INFO\n const effectiveLevel = _level ?? (fileLogger ? (fileLogger as unknown as { level: string }).level as LogLevel : LogLevel.INFO);\n consoleLogger = pino({\n level: effectiveLevel,\n });\n }\n\n const delegate = (method: 'info' | 'warn' | 'error' | 'debug') => {\n return (obj: object | string, msg?: string) => {\n const target = fileLogger || consoleLogger;\n if (target) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (target as any)[method](obj, msg);\n }\n };\n };\n\n return {\n info: delegate('info'),\n warn: delegate('warn'),\n error: delegate('error'),\n debug: delegate('debug'),\n child: () => getLogger(_level),\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n","import type { EventBus } from '../core/bus/index.js';\nimport { createSessionLogger } from './logger.js';\n\nexport class SessionLogger {\n private bus: EventBus;\n private unsubscribeFns: Array<() => void> = [];\n private requestIdToSessionId = new Map<string, string>();\n private sessionLoggers = new Map<string, ReturnType<typeof createSessionLogger>>();\n\n constructor(bus: EventBus) {\n this.bus = bus;\n }\n\n start(): void {\n this.unsubscribeFns.push(\n this.bus.onInbound((e) => {\n if (!e.targetAgent) {\n return;\n }\n\n const sessionId = `${e.targetAgent}-${e.chatId}`;\n this.write(sessionId, 'inbound:message', 'inbound', {\n channel: e.channel,\n channelInstanceId: e.channelInstanceId,\n chatId: e.chatId,\n messageId: e.messageId,\n targetAgent: e.targetAgent,\n agentCommand: e.agentCommand,\n systemCommand: e.systemCommand,\n textPreview: e.text.slice(0, 240),\n });\n })\n );\n this.unsubscribeFns.push(\n this.bus.onSessionStart((e) => this.write(e.sessionId, 'session:start', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionEnd((e) => this.write(e.sessionId, 'session:end', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onTurnFinished((e) => this.write(e.sessionId, 'turn:finished', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolExecuted((e) => this.write(e.sessionId, 'tool:executed', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionRequest((e) => {\n this.requestIdToSessionId.set(e.requestId, e.sessionId);\n this.write(e.sessionId, 'interaction:request', 'inbound', e);\n })\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionResponse((e) => {\n const sessionId = this.requestIdToSessionId.get(e.requestId);\n if (sessionId) {\n this.write(sessionId, 'interaction:response', 'inbound', e);\n this.requestIdToSessionId.delete(e.requestId);\n }\n })\n );\n this.unsubscribeFns.push(\n this.bus.onTurnFinished((e) => this.write(e.sessionId, 'turn:finished', 'system', e))\n );\n this.unsubscribeFns.push(\n this.bus.onOutbound((e) => {\n const sessionId = (e.context as any)?.sessionId;\n if (sessionId) {\n this.write(sessionId, 'outbound:message', 'outbound', e);\n }\n })\n );\n }\n\n stop(): void {\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n }\n\n private write(\n sessionId: string,\n event: string,\n direction: 'inbound' | 'outbound' | 'agent' | 'system',\n payload: unknown\n ): void {\n let logger = this.sessionLoggers.get(sessionId);\n if (!logger) {\n logger = createSessionLogger(sessionId);\n this.sessionLoggers.set(sessionId, logger);\n }\n logger.info({ ts: new Date().toISOString(), event, direction, payload });\n }\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../core/bus/index.js';\nimport type { AgentEventEnvelope, AgentType, CreateSessionOptions } from '../core/adapter/types.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport type { InteractionRequest, InteractionResponse } from '../core/interaction/types.js';\nimport { AgentRegistry } from '../core/agent/AgentRegistry.js';\nimport { SessionManager } from '../core/session/SessionManager.js';\nimport type { SessionInfo } from '../core/session/types.js';\nimport type { Session } from '../core/session/Session.js';\nimport type { AgentBridgePort, SessionSnapshot } from '../core/agent/AgentBridgePort.js';\n\n/** Backward compatible SessionFilter interface */\nexport interface SessionFilter {\n agentType?: string;\n includeEnded?: boolean;\n}\n\n/**\n * Gateway is the core domain aggregate root.\n * It orchestrates sessions, events, and agent management.\n *\n * Implements AgentBridgePort to serve as the bridge between agent adapters\n * and the gateway infrastructure (EventPublisher, SessionManager, etc.)\n */\nexport class Gateway implements AgentBridgePort {\n private sessionManager: SessionManager;\n private agentRegistry: AgentRegistry;\n private eventPublisher: EventPublisher;\n private interactionService: InteractionService;\n\n constructor(\n _eventBus: EventBus,\n interactionService: InteractionService,\n eventPublisher: EventPublisher,\n private logger?: Logger,\n ) {\n this.sessionManager = new SessionManager();\n this.agentRegistry = new AgentRegistry();\n this.eventPublisher = eventPublisher;\n this.interactionService = interactionService;\n }\n\n /**\n * Register a new agent type and get its token\n */\n registerAgent(agentType: string, token?: string): string {\n return this.agentRegistry.registerAgent(agentType, token);\n }\n\n /**\n * List all registered agents\n */\n listRegisteredAgents(): Array<{ token: string; agentType: string }> {\n return this.agentRegistry.listRegisteredAgents();\n }\n\n /**\n * Create a new session\n * @param skipPublishSessionStart - If true, do not publish session:start event (used for compensating creation)\n */\n async createSession(\n token: string,\n sessionId: string,\n options?: CreateSessionOptions,\n skipPublishSessionStart?: boolean\n ): Promise<Session> {\n const agentType = this.agentRegistry.getAgentType(token);\n if (!agentType) {\n throw new Error('Invalid token: no agent registered');\n }\n\n const session = await this.sessionManager.createSession(\n agentType as AgentType,\n { ...options, sessionId, token }\n );\n\n // Only publish session:start when not a compensating creation\n if (!skipPublishSessionStart) {\n this.logger?.debug({ sessionId: session.id, agentType: session.agentType }, '[Gateway] Publishing session:start for created session');\n this.eventPublisher.publish(\n {\n type: 'session:start',\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n agentType: session.agentType,\n payload: { ...(options?.metadata ?? {}), cwd: session.cwd },\n metadata: {\n transportType: session.agent.transportType,\n },\n },\n session\n );\n }\n\n return session;\n }\n\n /**\n * Get a session by ID\n */\n getSession(sessionId: string): Session | undefined {\n return this.sessionManager.getSession(sessionId);\n }\n\n /**\n * Get agent type for a session (used by NotificationHandler for lazy sessionAgentMap population)\n */\n getSessionAgentType(sessionId: string): 'claude' | 'codex' | undefined {\n const session = this.sessionManager.getSession(sessionId);\n return session?.agentType;\n }\n\n /**\n * Get session info snapshot (including model/permissionMode/slashCommands)\n */\n getSessionInfo(sessionId: string): SessionInfo | undefined {\n return this.sessionManager.getSessionInfo(sessionId);\n }\n\n /**\n * List all sessions\n */\n listSessions(filter?: SessionFilter): SessionInfo[] {\n let sessions = this.sessionManager.listSessions();\n\n if (filter?.agentType) {\n sessions = sessions.filter((s) => s.agentType === filter.agentType);\n }\n\n if (!filter?.includeEnded) {\n sessions = sessions.filter((s) => s.status !== 'closed');\n }\n\n return sessions;\n }\n\n /**\n * End a session\n */\n async endSession(sessionId: string): Promise<void> {\n // Cancel any pending interactions for this session before closing\n this.interactionService.cancelBySession(sessionId, 'session ended');\n await this.sessionManager.closeSession(sessionId);\n }\n\n /**\n * Get the session manager for advanced operations\n */\n getSessionManager(): SessionManager {\n return this.sessionManager;\n }\n\n /**\n * Get the agent registry for advanced operations\n */\n getAgentRegistry(): AgentRegistry {\n return this.agentRegistry;\n }\n\n // === AgentBridgePort Implementation ===\n\n /** Emit an event envelope directly */\n emitEvent(envelope: AgentEventEnvelope): void {\n const session = this.sessionManager.getSession(envelope.sessionId);\n if (!session) {\n this.logger?.debug({ sessionId: envelope.sessionId }, '[Gateway] Session not found for emitEvent');\n return;\n }\n this.eventPublisher.publish(envelope, session);\n }\n\n async ensureSession(\n sessionId: string,\n options: CreateSessionOptions,\n agentType?: AgentType\n ): Promise<SessionSnapshot> {\n const existing = this.sessionManager.getSession(sessionId);\n if (existing) {\n return {\n id: existing.id,\n agentType: existing.agentType,\n getStatus: () => existing.getStatus(),\n sendCommand: async (cmd) => existing.sendCommand(cmd),\n };\n }\n\n // Try to get token from options, or look up from registry\n let token = options.token;\n if (!token && agentType) {\n // Find a registered agent of this type\n const agents = this.agentRegistry.listRegisteredAgents();\n const match = agents.find((a) => a.agentType === agentType);\n token = match?.token;\n }\n if (!token) {\n throw new Error(\n `Cannot create session ${sessionId}: no token provided and no registered agent found${agentType ? ` for type ${agentType}` : ''}`\n );\n }\n\n const session = await this.createSession(token, sessionId, options);\n return {\n id: session.id,\n agentType: session.agentType,\n getStatus: () => session.getStatus(),\n sendCommand: async (cmd) => session.sendCommand(cmd),\n };\n }\n\n async evaluateInteraction(request: InteractionRequest): Promise<InteractionResponse> {\n const sessionId = request.sessionId;\n if (!sessionId) {\n return { requestId: request.requestId, action: 'deny', message: 'No session ID' };\n }\n\n const session = this.sessionManager.getSession(sessionId);\n if (!session) {\n return { requestId: request.requestId, action: 'deny', message: 'Session not found' };\n }\n\n // Convert InteractionRequest to envelope for InteractionService\n const envelope: AgentEventEnvelope = {\n type: request.type === 'permission' ? 'permission:request' : 'question:request',\n sessionId,\n timestamp: new Date(request.timestamp).toISOString(),\n agentType: session.agentType,\n payload: {\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n },\n metadata: { transportType: session.agent.transportType },\n };\n\n return await this.interactionService.evaluate(envelope);\n }\n\n updateSessionInfo(sessionId: string, info: Partial<Omit<SessionInfo, 'id' | 'agentType' | 'transportType' | 'createdAt'>>): void {\n this.sessionManager.updateSessionInfo(sessionId, info);\n }\n\n renameSessionId(oldId: string, newId: string): boolean {\n return this.sessionManager.renameSessionId(oldId, newId);\n }\n}\n\n// Re-export gateway types\nexport * from './events.js';\nexport * from './interaction-service.js';\n","import { randomBytes } from 'crypto';\n\n/**\n * AgentRegistry - handles token-based agent registration and authorization\n * Maintains the token -> agentType mapping\n */\nexport class AgentRegistry {\n private registrations = new Map<string, string>();\n\n registerAgent(agentType: string, customToken?: string): string {\n const token = customToken ?? this.generateToken();\n this.registrations.set(token, agentType);\n return token;\n }\n\n unregisterAgent(token: string): boolean {\n return this.registrations.delete(token);\n }\n\n isTokenRegistered(token: string): boolean {\n return this.registrations.has(token);\n }\n\n getAgentType(token: string): string | undefined {\n return this.registrations.get(token);\n }\n\n listRegisteredAgents(): { token: string; agentType: string }[] {\n return Array.from(this.registrations.entries()).map(([token, agentType]) => ({\n token,\n agentType,\n }));\n }\n\n private generateToken(): string {\n return randomBytes(16).toString('hex');\n }\n}\n","// src/core/session/SessionManager.ts\n\nimport { randomUUID } from 'crypto';\nimport { getLogger } from '../../shared/logger.js';\nimport { AgentAdapterRegistry } from '../adapter/AgentAdapterRegistry.js';\nimport type { AgentType, CreateSessionOptions } from '../adapter/types.js';\nimport type { SessionInfo } from './types.js';\nimport { Session } from './Session.js';\n\nexport class SessionManager {\n private sessions = new Map<string, Session>();\n private logger = getLogger();\n\n async createSession(\n agentType: AgentType,\n options?: CreateSessionOptions & { token?: string }\n ): Promise<Session> {\n const adapter = AgentAdapterRegistry.getInstance().getAdapter(agentType);\n if (!adapter) {\n throw new Error(`No adapter found for agent type: ${agentType}`);\n }\n\n const sessionId = options?.sessionId ?? randomUUID();\n const transportState = await adapter.createTransportState({\n ...options,\n });\n\n const transportCwd = transportState.cwd as string | undefined;\n const cwd = options?.cwd || transportCwd || undefined;\n this.logger.debug({ sessionId, optionsCwd: options?.cwd, transportCwd, resolvedCwd: cwd }, '[SessionManager] Resolved cwd for session');\n\n const session = new Session({\n id: sessionId,\n adapter,\n transportState,\n token: options?.token,\n metadata: options?.metadata,\n cwd,\n createdAt: options?.createdAt,\n });\n\n this.sessions.set(sessionId, session);\n this.logger.info({ sessionId, agentType, cwd, token: options?.token?.slice(0, 8) }, '[Session] Created');\n\n return session;\n }\n\n async closeSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n await session.close();\n this.sessions.delete(sessionId);\n this.logger.info({ sessionId }, '[Session] Closed');\n }\n\n getSession(sessionId: string): Session | undefined {\n return this.sessions.get(sessionId);\n }\n\n getSessionInfo(sessionId: string): SessionInfo | undefined {\n return this.sessions.get(sessionId)?.toInfo();\n }\n\n listSessions(): SessionInfo[] {\n return Array.from(this.sessions.values()).map(s => s.toInfo());\n }\n\n listSessionsByAgent(agentType: AgentType): SessionInfo[] {\n return this.listSessions().filter(s => s.agentType === agentType);\n }\n\n getSessionCount(): number {\n return this.sessions.size;\n }\n\n updateSessionInfo(sessionId: string, info: Partial<Omit<SessionInfo, 'id' | 'agentType' | 'transportType' | 'createdAt'>>): boolean {\n const session = this.sessions.get(sessionId);\n if (!session) {\n this.logger.warn({ sessionId }, '[SessionManager] updateSessionInfo: session not found');\n return false;\n }\n session.updateInfo(info);\n this.logger.debug({ sessionId, ...info }, '[SessionManager] Session info updated');\n return true;\n }\n\n renameSessionId(oldId: string, newId: string): boolean {\n const session = this.sessions.get(oldId);\n if (!session) {\n this.logger.warn({ oldId, newId }, '[SessionManager] renameSessionId: session not found');\n return false;\n }\n if (this.sessions.has(newId)) {\n this.logger.warn({ oldId, newId }, '[SessionManager] renameSessionId: newId already exists');\n return false;\n }\n session.setId(newId);\n this.sessions.delete(oldId);\n this.sessions.set(newId, session);\n this.logger.info({ oldId, newId }, '[SessionManager] Session renamed');\n return true;\n }\n}\n","import type { AgentAdapter } from './AgentAdapter.js';\nimport type { AgentType, TransportType } from './types.js';\n\n/**\n * Adapter Registry\n * Manages registration and discovery of all AgentAdapter instances\n */\nexport class AgentAdapterRegistry {\n private static instance: AgentAdapterRegistry | null = null;\n private adapters: Map<string, AgentAdapter> = new Map();\n\n private constructor() {}\n\n static getInstance(): AgentAdapterRegistry {\n if (!AgentAdapterRegistry.instance) {\n AgentAdapterRegistry.instance = new AgentAdapterRegistry();\n }\n return AgentAdapterRegistry.instance;\n }\n\n /**\n * Register adapter (uses agentType:transportType as key)\n */\n register(adapter: AgentAdapter): void {\n const key = this.makeKey(adapter.agentType, adapter.transportType);\n if (this.adapters.has(key)) {\n console.warn(`Adapter ${key} already registered, overwriting...`);\n }\n this.adapters.set(key, adapter);\n }\n\n /**\n * Get adapter\n */\n get(agentType: AgentType, transportType: TransportType): AgentAdapter | undefined {\n return this.adapters.get(this.makeKey(agentType, transportType));\n }\n\n /**\n * Get adapter by agent type (returns first available transport)\n */\n getAdapter(agentType: 'claude' | 'codex'): AgentAdapter | undefined {\n const adapters = this.getAllForAgent(agentType);\n return adapters.length > 0 ? adapters[0] : undefined;\n }\n\n /**\n * Get all adapters for a specific agent type\n */\n getAllForAgent(agentType: AgentType): AgentAdapter[] {\n return Array.from(this.adapters.values()).filter(\n (a) => a.agentType === agentType\n );\n }\n\n /**\n * List all available (agentType, transportType) combinations\n */\n listAvailable(): Array<{ agentType: AgentType; transportType: TransportType }> {\n return Array.from(this.adapters.values()).map((a) => ({\n agentType: a.agentType,\n transportType: a.transportType,\n }));\n }\n\n /**\n * Check if adapter exists\n */\n has(agentType: AgentType, transportType: TransportType): boolean {\n return this.adapters.has(this.makeKey(agentType, transportType));\n }\n\n /**\n * Reset (for testing)\n */\n reset(): void {\n this.adapters.clear();\n }\n\n private makeKey(agentType: AgentType, transportType: TransportType): string {\n return `${agentType}:${transportType}`;\n }\n}\n\n/**\n * Adapter decorator factory\n * Used for automatic adapter registration\n *\n * @note The setTimeout cannot be cancelled. This decorator should only be used\n * for adapters that are registered once at application startup.\n */\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function registerAdapter(agentType: AgentType, transportType: TransportType): (target: Function) => Function {\n return function (target: Function): Function {\n const registry = AgentAdapterRegistry.getInstance();\n // Delay instantiation until all modules are loaded\n setTimeout(() => {\n const instance = new (target as new (...args: unknown[]) => AgentAdapter)();\n if (instance.agentType === agentType && instance.transportType === transportType) {\n registry.register(instance);\n }\n }, 0);\n return target;\n };\n}\n","// src/core/session/Session.ts\n\nimport type { AgentAdapter, TransportState } from '../adapter/AgentAdapter.js';\nimport type { AgentCommand, SessionInfo } from '../adapter/types.js';\n\nexport class Session {\n private _id: string;\n readonly agent: AgentAdapter;\n readonly token?: string;\n readonly metadata: Record<string, unknown>;\n readonly createdAt: number;\n\n private _status: 'active' | 'closed' | 'archived' = 'active';\n private _updatedAt: number;\n private _transportState: TransportState;\n\n cwd?: string;\n model?: string;\n permissionMode?: string;\n slashCommands?: string[];\n\n constructor(options: {\n id: string;\n adapter: AgentAdapter;\n transportState: TransportState;\n token?: string;\n metadata?: Record<string, unknown>;\n cwd?: string;\n createdAt?: number;\n }) {\n this._id = options.id;\n this.agent = options.adapter;\n this.token = options.token;\n this.metadata = options.metadata ?? {};\n this._transportState = options.transportState;\n this.createdAt = options.createdAt ?? Date.now();\n this._updatedAt = this.createdAt;\n this.cwd = options.cwd;\n }\n\n get id(): string {\n return this._id;\n }\n\n setId(newId: string): void {\n this._id = newId;\n }\n\n get agentType() {\n return this.agent.agentType;\n }\n\n get status(): 'active' | 'closed' | 'archived' {\n return this._status;\n }\n\n get updatedAt(): number {\n return this._updatedAt;\n }\n\n get transportState(): TransportState {\n return this._transportState;\n }\n\n updateInfo(partial: Partial<Omit<SessionInfo, 'id' | 'agentType' | 'transportType' | 'createdAt'>>): void {\n if (partial.status !== undefined) this._status = partial.status;\n if (partial.cwd !== undefined) this.cwd = partial.cwd;\n if (partial.model !== undefined) this.model = partial.model;\n if (partial.permissionMode !== undefined) this.permissionMode = partial.permissionMode;\n if (partial.slashCommands !== undefined) this.slashCommands = partial.slashCommands;\n this._updatedAt = Date.now();\n }\n\n async sendCommand(command: AgentCommand): Promise<void> {\n if (this._status !== 'active') {\n throw new Error(`Cannot send command to closed session: ${this.id}`);\n }\n return this.agent.sendCommand(this._transportState, command);\n }\n\n async close(): Promise<void> {\n if (this._status !== 'active') {\n return;\n }\n await this.agent.closeTransportState(this._transportState);\n this._status = 'closed';\n }\n\n /** @deprecated Use `status` getter instead */\n getStatus(): 'active' | 'closed' | 'archived' {\n return this._status;\n }\n\n /** @deprecated Use `toInfo()` instead */\n toJSON(): SessionInfo {\n return this.toInfo();\n }\n\n toInfo(): SessionInfo {\n return {\n id: this.id,\n agentType: this.agentType,\n transportType: this.agent.transportType,\n status: this._status,\n createdAt: this.createdAt,\n updatedAt: this._updatedAt,\n token: this.token,\n cwd: this.cwd,\n model: this.model,\n permissionMode: this.permissionMode,\n slashCommands: this.slashCommands,\n };\n }\n}\n","/**\n * Event frame structure for normalized events\n */\nexport interface EventFrame {\n type: 'event';\n event: string;\n payload: {\n agentType: string;\n sessionId: string;\n timestamp: string;\n data: unknown;\n };\n seq?: number;\n}\n\n/**\n * Response frame structure\n */\nexport interface ResponseFrame {\n type: 'res';\n id: string;\n result?: unknown;\n error?: { code: number; message: string };\n}\n\n/**\n * Default event type mappings for Claude Code\n * Centralized mapping to avoid duplication\n */\nexport const EVENT_TYPE_MAP: Record<string, string> = {\n SessionStart: 'session:start',\n SessionEnd: 'session:end',\n Stop: 'turn:finished',\n PostToolUse: 'tool:executed',\n PostToolUseFailure: 'tool:failure',\n PreToolUse: 'permission:request',\n Notification: 'notification',\n SubagentStart: 'message',\n SubagentStop: 'message',\n UserPromptSubmit: 'message',\n};\n\n/**\n * Normalize event type from agent-specific to standard format\n */\nexport function normalizeEventType(eventType: string): string {\n return EVENT_TYPE_MAP[eventType] ?? eventType.toLowerCase();\n}\n\n/**\n * Extract session ID from payload (supports both snake_case and camelCase)\n */\nexport function extractSessionId(payload: unknown): string | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const p = payload as Record<string, unknown>;\n const sessionId = p.session_id ?? p.sessionId;\n return typeof sessionId === 'string' ? sessionId : undefined;\n}\n","import { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadPermissionsConfig, checkPermission, checkDenyOnly } from '../shared/permissions.js';\nimport { EventBus } from '../core/bus/index.js';\nimport { getLogger } from '../shared/logger.js';\nimport type { AgentEventEnvelope } from '../core/adapter/types.js';\nimport type { InteractionResponse, InteractionRequest } from '../core/interaction/types.js';\nimport type { InteractionContent } from '../core/interaction/types.js';\n\ninterface EvaluationResult {\n immediate: boolean;\n response?: InteractionResponse;\n reason?: string;\n}\n\nfunction evaluatePermission(\n agentType: string,\n toolName: string,\n toolInput: Record<string, unknown>,\n permissionMode: string,\n cwd: string\n): EvaluationResult {\n if (permissionMode === 'bypassPermissions') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'permissionMode is bypassPermissions' },\n };\n }\n\n const projectConfig = cwd ? loadPermissionsConfig(cwd) : null;\n\n if (permissionMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit', 'codex_patch_apply'].includes(toolName)) {\n const denyResult = checkDenyOnly(toolName, toolInput, projectConfig);\n if (denyResult.decision === 'deny') {\n return {\n immediate: true,\n response: { requestId: '', action: 'deny', message: denyResult.reason },\n };\n }\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'acceptEdits mode for Edit/Write' },\n };\n }\n\n const result = checkPermission(toolName, toolInput, projectConfig);\n\n if (result.decision === 'deny') {\n return {\n immediate: true,\n response: { requestId: '', action: 'deny', message: result.reason },\n };\n }\n if (result.decision === 'allow') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: result.reason },\n };\n }\n\n return { immediate: false };\n}\n\nexport class InteractionService {\n constructor(\n private interactionQueue: InteractionQueue,\n private bus: EventBus\n ) {}\n\n async evaluate(envelope: AgentEventEnvelope): Promise<InteractionResponse> {\n const logger = getLogger();\n const payload = envelope.payload as {\n sessionId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n };\n const sessionId = String(payload.sessionId || envelope.sessionId);\n const toolName = String(payload.toolName);\n const toolInput = payload.toolInput || {};\n const permissionMode = (envelope.metadata.permissionMode as string) || 'auto';\n const cwd = (envelope.payload.cwd as string) || '';\n const agentType = String(envelope.agentType || 'claude');\n\n logger.info({ sessionId, toolName, type: envelope.type }, '[Interaction] Request received');\n\n // Determine interaction type\n let interactionType: 'permission' | 'question' = envelope.type === 'question:request' ? 'question' : 'permission';\n\n // Special case: AskUserQuestion is a question tool masquerading as a permission request\n if (toolName === 'AskUserQuestion' && Array.isArray(toolInput.questions)) {\n interactionType = 'question';\n }\n\n // For permissions, check if immediate decision possible\n if (interactionType === 'permission') {\n const evaluation = evaluatePermission(agentType, toolName, toolInput, permissionMode, cwd);\n if (evaluation.immediate && evaluation.response) {\n logger.info({ toolName, action: evaluation.response.action }, '[Interaction] Immediate response');\n return { ...evaluation.response, requestId: '' };\n }\n }\n\n // Queue for user interaction\n const request: InteractionRequest = {\n requestId: '',\n sessionId,\n type: interactionType,\n toolName,\n toolInput,\n timestamp: Date.now(),\n };\n\n const startTime = Date.now();\n const { requestId, responsePromise } = this.interactionQueue.request(request);\n logger.info({ requestId, sessionId, type: interactionType, toolName }, '[Interaction] Blocking');\n\n // Build content based on type\n const content = this.buildContent(interactionType, toolName, toolInput, cwd);\n\n // Publish event\n this.bus.publishInteractionRequest({\n requestId,\n sessionId,\n interactionType,\n content,\n chatId: sessionId,\n messageId: '',\n cwd,\n });\n\n const response = await responsePromise;\n const elapsedMs = Date.now() - startTime;\n logger.info({ requestId, action: response.action, elapsedMs }, '[Interaction] Response sent');\n return response;\n }\n\n cancelBySession(sessionId: string, reason = 'session closed'): number {\n return this.interactionQueue.cancelBySession(sessionId, reason);\n }\n\n private buildContent(\n type: 'permission' | 'question',\n toolName: string,\n toolInput: Record<string, unknown>,\n cwd: string\n ): InteractionContent {\n if (type === 'question') {\n const questions = (toolInput.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; description?: string; value?: unknown }>;\n multiSelect?: boolean;\n }>) || [];\n const question = questions[0] || { question: 'Question', options: [] };\n\n return {\n title: question.header || 'Question',\n description: question.question,\n question: {\n text: question.question,\n header: question.header,\n options: (question.options || []).map((opt, idx) => ({\n id: String(idx),\n label: opt.label,\n value: opt.value ?? opt.label,\n description: opt.description,\n })),\n allowCustomInput: false, // TODO: make configurable\n multiSelect: question.multiSelect ?? false,\n },\n };\n }\n\n // Permission content\n return {\n title: `Permission Required: ${toolName}`,\n description: `${toolName} ${JSON.stringify(toolInput)}`,\n permission: {\n riskLevel: 'medium',\n args: toolInput,\n },\n };\n }\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { getLogger } from './logger.js';\nimport { minimatch } from 'minimatch';\n\nexport interface PermissionRule {\n tool: string;\n pattern?: string;\n raw: string;\n}\n\nexport interface PermissionsConfig {\n allow: PermissionRule[];\n deny: PermissionRule[];\n ask: PermissionRule[];\n defaultMode: 'acceptEdits' | 'prompt' | 'auto' | 'default';\n}\n\nconst logger = getLogger();\n\n/**\n * Parse a permission rule like \"Bash(rm *)\" or \"Edit(./src/**)\"\n */\nfunction parseRule(rule: string): PermissionRule {\n const match = rule.match(/^([^(]+)(?:\\((.+)\\))?$/);\n if (!match) {\n return { tool: rule, raw: rule };\n }\n return {\n tool: match[1].trim(),\n pattern: match[2]?.trim(),\n raw: rule,\n };\n}\n\n/**\n * Load permissions config from project's .claude/settings.local.json\n */\nexport function loadPermissionsConfig(cwd: string): PermissionsConfig | null {\n const configPath = join(cwd, '.claude', 'settings.local.json');\n\n if (!existsSync(configPath)) {\n logger.debug(`[Permissions] No config found at ${configPath}`);\n return null;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content);\n\n const permissions = config.permissions || {};\n\n return {\n allow: (permissions.allow || []).map(parseRule),\n deny: (permissions.deny || []).map(parseRule),\n ask: (permissions.ask || []).map(parseRule),\n defaultMode: permissions.defaultMode || 'default',\n };\n } catch (error) {\n logger.warn(`[Permissions] Failed to load config from ${configPath}:`, error);\n return null;\n }\n}\n\n/**\n * Check if a tool input matches a pattern\n * Examples:\n * \"rm a.txt\" matches \"rm *\"\n * \"./src/config.ts\" matches \"./src/**\"\n */\nfunction matchesPattern(input: string, pattern: string): boolean {\n // Handle glob patterns\n if (pattern.includes('*') || pattern.includes('?')) {\n return minimatch(input, pattern, { matchBase: true });\n }\n // Exact match\n return input === pattern;\n}\n\n/**\n * Check if a tool matches a permission rule\n */\nfunction matchesRule(toolName: string, toolInput: Record<string, unknown>, rule: PermissionRule): boolean {\n // Tool name must match\n if (rule.tool !== toolName) {\n return false;\n }\n\n // If no pattern, match any usage of this tool\n const pattern = rule.pattern;\n if (!pattern) {\n return true;\n }\n\n // For Bash / codex_exec_command with string command\n if ((toolName === 'Bash' || toolName === 'codex_exec_command') && typeof toolInput.command === 'string') {\n const command = toolInput.command;\n // Extract the first word (the actual command)\n const firstWord = command.trim().split(/\\s+/)[0];\n return matchesPattern(command, pattern) || matchesPattern(firstWord, pattern);\n }\n\n // For codex_exec_command with string[] command\n if (toolName === 'codex_exec_command' && Array.isArray(toolInput.command)) {\n const command = (toolInput.command as string[]).join(' ');\n const firstWord = command.trim().split(/\\s+/)[0];\n return matchesPattern(command, pattern) || matchesPattern(firstWord, pattern);\n }\n\n // For file operations (Read, Edit, Write, etc.), match against file_path\n if (typeof toolInput.file_path === 'string') {\n return matchesPattern(toolInput.file_path, pattern);\n }\n\n // For codex_patch_apply with fileChanges object\n if (toolName === 'codex_patch_apply' && toolInput.fileChanges && typeof toolInput.fileChanges === 'object') {\n const paths = Object.keys(toolInput.fileChanges as Record<string, unknown>);\n return paths.some((path) => matchesPattern(path, pattern));\n }\n\n return false;\n}\n\nexport type PermissionDecision = 'allow' | 'deny' | 'ask';\n\n/**\n * Determine permission decision based on config and tool usage\n */\nexport function checkPermission(\n toolName: string,\n toolInput: Record<string, unknown>,\n config: PermissionsConfig | null\n): { decision: PermissionDecision; reason: string } {\n // No config - default to ask\n if (!config) {\n return { decision: 'ask', reason: 'No permissions config found' };\n }\n\n // Check deny list first (highest priority)\n for (const rule of config.deny) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'deny', reason: `Matches deny rule: ${rule.raw}` };\n }\n }\n\n // Check allow list\n for (const rule of config.allow) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'allow', reason: `Matches allow rule: ${rule.raw}` };\n }\n }\n\n // Check ask list\n for (const rule of config.ask) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'ask', reason: `Matches ask rule: ${rule.raw}` };\n }\n }\n\n // Default based on defaultMode\n if (config.defaultMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit', 'codex_patch_apply'].includes(toolName)) {\n return { decision: 'allow', reason: 'defaultMode is acceptEdits' };\n }\n\n return { decision: 'ask', reason: 'No matching rule, default to ask' };\n}\n\n/**\n * Check if we need to intercept based on permission_mode\n */\nexport function shouldIntercept(permissionMode: string): boolean {\n // Only intercept modes that would show permission dialogs\n return permissionMode === 'prompt' || permissionMode === 'default';\n}\n\n/**\n * Check only deny rules\n * @param toolName The name of the tool to check\n * @param toolInput The tool input/arguments\n * @param config The permissions configuration\n * @returns Decision object with 'deny' or 'allow' and reason\n */\nexport function checkDenyOnly(\n toolName: string,\n toolInput: Record<string, unknown>,\n config: PermissionsConfig | null\n): { decision: PermissionDecision; reason: string } {\n if (!config) {\n return { decision: 'allow', reason: 'No config, allow low-risk tool' };\n }\n\n for (const rule of config.deny) {\n if (matchesRule(toolName, toolInput, rule)) {\n return { decision: 'deny', reason: `Matches deny rule: ${rule.raw}` };\n }\n }\n\n return { decision: 'allow', reason: 'Low-risk tool, no deny match' };\n}\n","import { expand } from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport type { ExtglobType } from './ast.js'\nimport { AST } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\nexport type Platform =\n | 'aix'\n | 'android'\n | 'darwin'\n | 'freebsd'\n | 'haiku'\n | 'linux'\n | 'openbsd'\n | 'sunos'\n | 'win32'\n | 'cygwin'\n | 'netbsd'\n\nexport interface MinimatchOptions {\n /** do not expand `{x,y}` style braces */\n nobrace?: boolean\n /** do not treat patterns starting with `#` as a comment */\n nocomment?: boolean\n /** do not treat patterns starting with `!` as a negation */\n nonegate?: boolean\n /** print LOTS of debugging output */\n debug?: boolean\n /** treat `**` the same as `*` */\n noglobstar?: boolean\n /** do not expand extglobs like `+(a|b)` */\n noext?: boolean\n /** return the pattern if nothing matches */\n nonull?: boolean\n /** treat `\\\\` as a path separator, not an escape character */\n windowsPathsNoEscape?: boolean\n /**\n * inverse of {@link MinimatchOptions.windowsPathsNoEscape}\n * @deprecated\n */\n allowWindowsEscape?: boolean\n /**\n * Compare a partial path to a pattern. As long as the parts\n * of the path that are present are not contradicted by the\n * pattern, it will be treated as a match. This is useful in\n * applications where you're walking through a folder structure,\n * and don't yet have the full path, but want to ensure that you\n * do not walk down paths that can never be a match.\n */\n partial?: boolean\n /** allow matches that start with `.` even if the pattern does not */\n dot?: boolean\n /** ignore case */\n nocase?: boolean\n /** ignore case only in wildcard patterns */\n nocaseMagicOnly?: boolean\n /** consider braces to be \"magic\" for the purpose of `hasMagic` */\n magicalBraces?: boolean\n /**\n * If set, then patterns without slashes will be matched\n * against the basename of the path if it contains slashes.\n * For example, `a?b` would match the path `/xyz/123/acb`, but\n * not `/xyz/acb/123`.\n */\n matchBase?: boolean\n /** invert the results of negated matches */\n flipNegate?: boolean\n /** do not collapse multiple `/` into a single `/` */\n preserveMultipleSlashes?: boolean\n /**\n * A number indicating the level of optimization that should be done\n * to the pattern prior to parsing and using it for matches.\n */\n optimizationLevel?: number\n /** operating system platform */\n platform?: Platform\n /**\n * When a pattern starts with a UNC path or drive letter, and in\n * `nocase:true` mode, do not convert the root portions of the\n * pattern into a case-insensitive regular expression, and instead\n * leave them as strings.\n *\n * This is the default when the platform is `win32` and\n * `nocase:true` is set.\n */\n windowsNoMagicRoot?: boolean\n /**\n * max number of `{...}` patterns to expand. Default 100_000.\n */\n braceExpandMax?: number\n /**\n * Max number of non-adjacent `**` patterns to recursively walk down.\n *\n * The default of 200 is almost certainly high enough for most purposes,\n * and can handle absurdly excessive patterns.\n */\n maxGlobstarRecursion?: number\n\n /**\n * Max depth to traverse for nested extglobs like `*(a|b|c)`\n *\n * Default is 2, which is quite low, but any higher value\n * swiftly results in punishing performance impacts. Note\n * that this is *not* relevant when the globstar types can\n * be safely coalesced into a single set.\n *\n * For example, `*(a|@(b|c)|d)` would be flattened into\n * `*(a|b|c|d)`. Thus, many common extglobs will retain good\n * performance and never hit this limit, even if they are\n * excessively deep and complicated.\n *\n * If the limit is hit, then the extglob characters are simply\n * not parsed, and the pattern effectively switches into\n * `noextglob: true` mode for the contents of that nested\n * sub-pattern. This will typically _not_ result in a match,\n * but is considered a valid trade-off for security and\n * performance.\n */\n maxExtglobRecursion?: number\n}\n\nexport const minimatch = (\n p: string,\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n return new Minimatch(pattern, options).match(p)\n}\n\n// Optimized checking for the most common glob patterns.\nconst starDotExtRE = /^\\*+([^+@!?*[(]*)$/\nconst starDotExtTest = (ext: string) => (f: string) =>\n !f.startsWith('.') && f.endsWith(ext)\nconst starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)\nconst starDotExtTestNocase = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => !f.startsWith('.') && f.toLowerCase().endsWith(ext)\n}\nconst starDotExtTestNocaseDot = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => f.toLowerCase().endsWith(ext)\n}\nconst starDotStarRE = /^\\*+\\.\\*+$/\nconst starDotStarTest = (f: string) =>\n !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) =>\n f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) =>\n f.length !== 0 && f !== '.' && f !== '..'\nconst qmarksRE = /^\\?+([^+@!?*[(]*)?$/\nconst qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTestNoExt = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && !f.startsWith('.')\n}\nconst qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && f !== '.' && f !== '..'\n}\n\n/* c8 ignore start */\nconst defaultPlatform: Platform = (\n typeof process === 'object' && process ?\n (typeof process.env === 'object' &&\n process.env &&\n process.env.__MINIMATCH_TESTING_PLATFORM__) ||\n process.platform\n : 'posix') as Platform\n\nexport type Sep = '\\\\' | '/'\n\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep =\n defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep\nminimatch.sep = sep\n\nexport const GLOBSTAR = Symbol('globstar **')\nminimatch.GLOBSTAR = GLOBSTAR\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nconst twoStarDot = '(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nconst twoStarNoDot = '(?:(?!(?:\\\\/|^)\\\\.).)*?'\n\nexport const filter =\n (pattern: string, options: MinimatchOptions = {}) =>\n (p: string) =>\n minimatch(p, pattern, options)\nminimatch.filter = filter\n\nconst ext = (a: MinimatchOptions, b: MinimatchOptions = {}) =>\n Object.assign({}, a, b)\n\nexport const defaults = (def: MinimatchOptions): typeof minimatch => {\n if (!def || typeof def !== 'object' || !Object.keys(def).length) {\n return minimatch\n }\n\n const orig = minimatch\n\n const m = (p: string, pattern: string, options: MinimatchOptions = {}) =>\n orig(p, pattern, ext(def, options))\n\n return Object.assign(m, {\n Minimatch: class Minimatch extends orig.Minimatch {\n constructor(pattern: string, options: MinimatchOptions = {}) {\n super(pattern, ext(def, options))\n }\n static defaults(options: MinimatchOptions) {\n return orig.defaults(ext(def, options)).Minimatch\n }\n },\n\n AST: class AST extends orig.AST {\n /* c8 ignore start */\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n super(type, parent, ext(def, options))\n }\n /* c8 ignore stop */\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n return orig.AST.fromGlob(pattern, ext(def, options))\n }\n },\n\n unescape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.escape(s, ext(def, options)),\n\n filter: (pattern: string, options: MinimatchOptions = {}) =>\n orig.filter(pattern, ext(def, options)),\n\n defaults: (options: MinimatchOptions) =>\n orig.defaults(ext(def, options)),\n\n makeRe: (pattern: string, options: MinimatchOptions = {}) =>\n orig.makeRe(pattern, ext(def, options)),\n\n braceExpand: (pattern: string, options: MinimatchOptions = {}) =>\n orig.braceExpand(pattern, ext(def, options)),\n\n match: (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n ) => orig.match(list, pattern, ext(def, options)),\n\n sep: orig.sep,\n GLOBSTAR: GLOBSTAR as typeof GLOBSTAR,\n })\n}\nminimatch.defaults = defaults\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nexport const braceExpand = (\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // Thanks to Yeting Li <https://github.com/yetingli> for\n // improving this regexp to avoid a ReDOS vulnerability.\n if (options.nobrace || !/\\{(?:(?!\\{).)*\\}/.test(pattern)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern, { max: options.braceExpandMax })\n}\nminimatch.braceExpand = braceExpand\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\n\nexport const makeRe = (pattern: string, options: MinimatchOptions = {}) =>\n new Minimatch(pattern, options).makeRe()\nminimatch.makeRe = makeRe\n\nexport const match = (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n const mm = new Minimatch(pattern, options)\n list = list.filter(f => mm.match(f))\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\nminimatch.match = match\n\n// replace stuff like \\* with *\nconst globMagic = /[?*]|[+@!]\\(.*?\\)|\\[|\\]/\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\nexport type MMRegExp = RegExp & {\n _src?: string\n _glob?: string\n}\n\nexport type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR\nexport type ParseReturn = ParseReturnFiltered | false\n\nexport class Minimatch {\n options: MinimatchOptions\n set: ParseReturnFiltered[][]\n pattern: string\n\n windowsPathsNoEscape: boolean\n nonegate: boolean\n negate: boolean\n comment: boolean\n empty: boolean\n preserveMultipleSlashes: boolean\n partial: boolean\n globSet: string[]\n globParts: string[][]\n nocase: boolean\n\n isWindows: boolean\n platform: Platform\n windowsNoMagicRoot: boolean\n maxGlobstarRecursion: number\n\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n // avoid the annoying deprecation flag lol\n const awe = ('allowWindow' + 'sEscape') as keyof MinimatchOptions\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options[awe] === false\n if (this.windowsPathsNoEscape) {\n this.pattern = this.pattern.replace(/\\\\/g, '/')\n }\n this.preserveMultipleSlashes = !!options.preserveMultipleSlashes\n this.regexp = null\n this.negate = false\n this.nonegate = !!options.nonegate\n this.comment = false\n this.empty = false\n this.partial = !!options.partial\n this.nocase = !!this.options.nocase\n this.windowsNoMagicRoot =\n options.windowsNoMagicRoot !== undefined ?\n options.windowsNoMagicRoot\n : !!(this.isWindows && this.nocase)\n\n this.globSet = []\n this.globParts = []\n this.set = []\n\n // make the set of regexps etc.\n this.make()\n }\n\n hasMagic(): boolean {\n if (this.options.magicalBraces && this.set.length > 1) {\n return true\n }\n for (const pattern of this.set) {\n for (const part of pattern) {\n if (typeof part !== 'string') return true\n }\n }\n return false\n }\n\n debug(..._: unknown[]) {}\n\n make() {\n const pattern = this.pattern\n const options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n this.globSet = [...new Set(this.braceExpand())]\n\n if (options.debug) {\n //oxlint-disable-next-line no-console\n this.debug = (...args: unknown[]) => console.error(...args)\n }\n\n this.debug(this.pattern, this.globSet)\n\n // step 3: now we have a set, so turn each one into a series of\n // path-portion matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n //\n // First, we preprocess to make the glob pattern sets a bit simpler\n // and deduped. There are some perf-killing patterns that can cause\n // problems with a glob walk, but we can simplify them down a bit.\n const rawGlobParts = this.globSet.map(s => this.slashSplit(s))\n this.globParts = this.preprocess(rawGlobParts)\n this.debug(this.pattern, this.globParts)\n\n // glob --> regexps\n let set = this.globParts.map((s, _, __) => {\n if (this.isWindows && this.windowsNoMagicRoot) {\n // check if it's a drive or unc path.\n const isUNC =\n s[0] === '' &&\n s[1] === '' &&\n (s[2] === '?' || !globMagic.test(s[2])) &&\n !globMagic.test(s[3])\n const isDrive = /^[a-z]:/i.test(s[0])\n if (isUNC) {\n return [\n ...s.slice(0, 4),\n ...s.slice(4).map(ss => this.parse(ss)),\n ]\n } else if (isDrive) {\n return [s[0], ...s.slice(1).map(ss => this.parse(ss))]\n }\n }\n return s.map(ss => this.parse(ss))\n })\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n this.set = set.filter(\n s => s.indexOf(false) === -1,\n ) as ParseReturnFiltered[][]\n\n // do not treat the ? in UNC paths as magic\n if (this.isWindows) {\n for (let i = 0; i < this.set.length; i++) {\n const p = this.set[i]\n if (\n p[0] === '' &&\n p[1] === '' &&\n this.globParts[i][2] === '?' &&\n typeof p[3] === 'string' &&\n /^[a-z]:$/i.test(p[3])\n ) {\n p[2] = '?'\n }\n }\n }\n\n this.debug(this.pattern, this.set)\n }\n\n // various transforms to equivalent pattern sets that are\n // faster to process in a filesystem walk. The goal is to\n // eliminate what we can, and push all ** patterns as far\n // to the right as possible, even if it increases the number\n // of patterns that we have to process.\n preprocess(globParts: string[][]) {\n // if we're not in globstar mode, then turn ** into *\n if (this.options.noglobstar) {\n for (const partset of globParts) {\n for (let j = 0; j < partset.length; j++) {\n if (partset[j] === '**') {\n partset[j] = '*'\n }\n }\n }\n }\n\n const { optimizationLevel = 1 } = this.options\n\n if (optimizationLevel >= 2) {\n // aggressive optimization for the purpose of fs walking\n globParts = this.firstPhasePreProcess(globParts)\n globParts = this.secondPhasePreProcess(globParts)\n } else if (optimizationLevel >= 1) {\n // just basic optimizations to remove some .. parts\n globParts = this.levelOneOptimize(globParts)\n } else {\n // just collapse multiple ** portions into one\n globParts = this.adjascentGlobstarOptimize(globParts)\n }\n\n return globParts\n }\n\n // just get rid of adjascent ** portions\n adjascentGlobstarOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let i = gs\n while (parts[i + 1] === '**') {\n i++\n }\n if (i !== gs) {\n parts.splice(gs, i - gs)\n }\n }\n return parts\n })\n }\n\n // get rid of adjascent ** and resolve .. portions\n levelOneOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n parts = parts.reduce((set: string[], part) => {\n const prev = set[set.length - 1]\n if (part === '**' && prev === '**') {\n return set\n }\n if (part === '..') {\n if (prev && prev !== '..' && prev !== '.' && prev !== '**') {\n set.pop()\n return set\n }\n }\n set.push(part)\n return set\n }, [])\n return parts.length === 0 ? [''] : parts\n })\n }\n\n levelTwoFileOptimize(parts: string | string[]) {\n if (!Array.isArray(parts)) {\n parts = this.slashSplit(parts)\n }\n let didSomething: boolean = false\n\n do {\n didSomething = false\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (\n p &&\n p !== '.' &&\n p !== '..' &&\n p !== '**' &&\n !(this.isWindows && /^[a-z]:$/i.test(p))\n ) {\n didSomething = true\n parts.splice(dd - 1, 2)\n dd -= 2\n }\n }\n } while (didSomething)\n return parts.length === 0 ? [''] : parts\n }\n\n // First phase: single-pattern processing\n // <pre> is 1 or more portions\n // <rest> is 1 or more portions\n // <p> is any portion other than ., .., '', or **\n // <e> is . or ''\n //\n // **/.. is *brutal* for filesystem walking performance, because\n // it effectively resets the recursive walk each time it occurs,\n // and ** cannot be reduced out by a .. pattern part like a regexp\n // or most strings (other than .., ., and '') can be.\n //\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n // <pre>/<e>/<rest> -> <pre>/<rest>\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n // **/**/<rest> -> **/<rest>\n //\n // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow\n // this WOULD be allowed if ** did follow symlinks, or * didn't\n firstPhasePreProcess(globParts: string[][]) {\n let didSomething = false\n do {\n didSomething = false\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n for (let parts of globParts) {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let gss: number = gs\n while (parts[gss + 1] === '**') {\n // <pre>/**/**/<rest> -> <pre>/**/<rest>\n gss++\n }\n // eg, if gs is 2 and gss is 4, that means we have 3 **\n // parts, and can remove 2 of them.\n if (gss > gs) {\n parts.splice(gs + 1, gss - gs)\n }\n\n let next = parts[gs + 1]\n const p = parts[gs + 2]\n const p2 = parts[gs + 3]\n if (next !== '..') continue\n if (\n !p ||\n p === '.' ||\n p === '..' ||\n !p2 ||\n p2 === '.' ||\n p2 === '..'\n ) {\n continue\n }\n didSomething = true\n // edit parts in place, and push the new one\n parts.splice(gs, 1)\n const other = parts.slice(0)\n other[gs] = '**'\n globParts.push(other)\n gs--\n }\n\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n const needDot = dd === 1 && parts[dd + 1] === '**'\n const splin = needDot ? ['.'] : []\n parts.splice(dd - 1, 2, ...splin)\n if (parts.length === 0) parts.push('')\n dd -= 2\n }\n }\n }\n } while (didSomething)\n\n return globParts\n }\n\n // second phase: multi-pattern dedupes\n // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>\n // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>\n // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>\n //\n // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>\n // ^-- not valid because ** doens't follow symlinks\n secondPhasePreProcess(globParts: string[][]): string[][] {\n for (let i = 0; i < globParts.length - 1; i++) {\n for (let j = i + 1; j < globParts.length; j++) {\n const matched = this.partsMatch(\n globParts[i],\n globParts[j],\n !this.preserveMultipleSlashes,\n )\n if (matched) {\n globParts[i] = []\n globParts[j] = matched\n break\n }\n }\n }\n return globParts.filter(gs => gs.length)\n }\n\n partsMatch(\n a: string[],\n b: string[],\n emptyGSMatch: boolean = false,\n ): false | string[] {\n let ai = 0\n let bi = 0\n let result: string[] = []\n let which: string = ''\n while (ai < a.length && bi < b.length) {\n if (a[ai] === b[bi]) {\n result.push(which === 'b' ? b[bi] : a[ai])\n ai++\n bi++\n } else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {\n result.push(a[ai])\n ai++\n } else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {\n result.push(b[bi])\n bi++\n } else if (\n a[ai] === '*' &&\n b[bi] &&\n (this.options.dot || !b[bi].startsWith('.')) &&\n b[bi] !== '**'\n ) {\n if (which === 'b') return false\n which = 'a'\n result.push(a[ai])\n ai++\n bi++\n } else if (\n b[bi] === '*' &&\n a[ai] &&\n (this.options.dot || !a[ai].startsWith('.')) &&\n a[ai] !== '**'\n ) {\n if (which === 'a') return false\n which = 'b'\n result.push(b[bi])\n ai++\n bi++\n } else {\n return false\n }\n }\n // if we fall out of the loop, it means they two are identical\n // as long as their lengths match\n return a.length === b.length && result\n }\n\n parseNegate() {\n if (this.nonegate) return\n\n const pattern = this.pattern\n let negate = false\n let negateOffset = 0\n\n for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.slice(negateOffset)\n this.negate = negate\n }\n\n // set partial to true to test if, for example,\n // \"/a/b\" matches the start of \"/*/b/*/d\"\n // Partial means, if you run out of file before you run\n // out of pattern, then that's fine, as long as all\n // the parts match.\n matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean = false,\n ) {\n let fileStartIndex = 0\n let patternStartIndex = 0\n\n // UNC paths like //?/X:/... can match X:/... and vice versa\n // Drive letters in absolute drive or unc paths are always compared\n // case-insensitively.\n if (this.isWindows) {\n const fileDrive =\n typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0])\n const fileUNC =\n !fileDrive &&\n file[0] === '' &&\n file[1] === '' &&\n file[2] === '?' &&\n /^[a-z]:$/i.test(file[3])\n\n const patternDrive =\n typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0])\n const patternUNC =\n !patternDrive &&\n pattern[0] === '' &&\n pattern[1] === '' &&\n pattern[2] === '?' &&\n typeof pattern[3] === 'string' &&\n /^[a-z]:$/i.test(pattern[3])\n\n const fdi =\n fileUNC ? 3\n : fileDrive ? 0\n : undefined\n const pdi =\n patternUNC ? 3\n : patternDrive ? 0\n : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [\n file[fdi],\n pattern[pdi] as string,\n ]\n // start matching at the drive letter index of each\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n patternStartIndex = pdi\n fileStartIndex = fdi\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // don't need to do the second phase, because it's only one string[]\n const { optimizationLevel = 1 } = this.options\n if (optimizationLevel >= 2) {\n file = this.levelTwoFileOptimize(file)\n }\n\n if (pattern.includes(GLOBSTAR)) {\n return this.#matchGlobstar(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n return this.#matchOne(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n #matchGlobstar(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n // split the pattern into head, tail, and middle of ** delimited parts\n const firstgs = pattern.indexOf(GLOBSTAR, patternIndex)\n const lastgs = pattern.lastIndexOf(GLOBSTAR)\n\n // split the pattern up into globstar-delimited sections\n // the tail has to be at the end, and the others just have\n // to be found in order from the head.\n const [head, body, tail] =\n partial ?\n [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1),\n [],\n ]\n : [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1, lastgs),\n pattern.slice(lastgs + 1),\n ]\n\n // check the head, from the current file/pattern index.\n if (head.length) {\n const fileHead = file.slice(fileIndex, fileIndex + head.length)\n if (!this.#matchOne(fileHead, head, partial, 0, 0)) {\n return false\n }\n fileIndex += head.length\n patternIndex += head.length\n }\n // now we know the head matches!\n\n // if the last portion is not empty, it MUST match the end\n // check the tail\n let fileTailMatch: number = 0\n if (tail.length) {\n // if head + tail > file, then we cannot possibly match\n if (tail.length + fileIndex > file.length) return false\n\n // try to match the tail\n let tailStart = file.length - tail.length\n if (this.#matchOne(file, tail, partial, tailStart, 0)) {\n fileTailMatch = tail.length\n } else {\n // affordance for stuff like a/**/* matching a/b/\n // if the last file portion is '', and there's more to the pattern\n // then try without the '' bit.\n if (\n file[file.length - 1] !== '' ||\n fileIndex + tail.length === file.length\n ) {\n return false\n }\n tailStart--\n if (!this.#matchOne(file, tail, partial, tailStart, 0)) {\n return false\n }\n fileTailMatch = tail.length + 1\n }\n }\n\n // now we know the tail matches!\n\n // the middle is zero or more portions wrapped in **, possibly\n // containing more ** sections.\n // so a/**/b/**/c/**/d has become **/b/**/c/**\n // if it's empty, it means a/**/b, just verify we have no bad dots\n // if there's no tail, so it ends on /**, then we must have *something*\n // after the head, or it's not a matc\n if (!body.length) {\n let sawSome = !!fileTailMatch\n for (let i = fileIndex; i < file.length - fileTailMatch; i++) {\n const f = String(file[i])\n sawSome = true\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n // in partial mode, we just need to get past all file parts\n return partial || sawSome\n }\n\n // now we know that there's one or more body sections, which can\n // be matched anywhere from the 0 index (because the head was pruned)\n // through to the length-fileTailMatch index.\n // split the body up into sections, and note the minimum index it can\n // be found at (start with the length of all previous segments)\n // [section, before, after]\n const bodySegments: [ParseReturn[], number][] = [[[], 0]]\n let currentBody: [ParseReturn[], number] = bodySegments[0]\n let nonGsParts = 0\n const nonGsPartsSums: number[] = [0]\n for (const b of body) {\n if (b === GLOBSTAR) {\n nonGsPartsSums.push(nonGsParts)\n currentBody = [[], 0]\n bodySegments.push(currentBody)\n } else {\n currentBody[0].push(b)\n nonGsParts++\n }\n }\n let i = bodySegments.length - 1\n const fileLength = file.length - fileTailMatch\n for (const b of bodySegments) {\n b[1] = fileLength - ((nonGsPartsSums[i--] as number) + b[0].length)\n }\n\n return !!this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex,\n 0,\n partial,\n 0,\n !!fileTailMatch,\n )\n }\n\n // return false for \"nope, not matching\"\n // return null for \"not matching, cannot keep trying\"\n #matchGlobStarBodySections(\n file: string[],\n // pattern section, last possible position for it\n bodySegments: [ParseReturn[], number][],\n fileIndex: number,\n bodyIndex: number,\n partial: boolean,\n globStarDepth: number,\n sawTail: boolean,\n ): boolean | null {\n // take the first body segment, and walk from fileIndex to its \"after\"\n // value at the end\n // If it doesn't match at that position, we increment, until we hit\n // that final possible position, and give up.\n // If it does match, then advance and try to rest.\n // If any of them fail we keep walking forward.\n // this is still a bit recursively painful, but it's more constrained\n // than previous implementations, because we never test something that\n // can't possibly be a valid matching condition.\n const bs = bodySegments[bodyIndex]\n if (!bs) {\n // just make sure that there's no bad dots\n for (let i = fileIndex; i < file.length; i++) {\n sawTail = true\n const f = file[i]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n return sawTail\n }\n\n // have a non-globstar body section to test\n const [body, after] = bs\n while (fileIndex <= after) {\n const m = this.#matchOne(\n file.slice(0, fileIndex + body.length),\n body,\n partial,\n fileIndex,\n 0,\n )\n // if limit exceeded, no match. intentional false negative,\n // acceptable break in correctness for security.\n if (m && globStarDepth < this.maxGlobstarRecursion) {\n // match! see if the rest match. if so, we're done!\n const sub = this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex + body.length,\n bodyIndex + 1,\n partial,\n globStarDepth + 1,\n sawTail,\n )\n if (sub !== false) {\n return sub\n }\n }\n const f = file[fileIndex]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n\n fileIndex++\n }\n // walked off. no point continuing\n return partial || null\n }\n\n #matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n let fi: number\n let pi: number\n let pl: number\n let fl: number\n for (\n fi = fileIndex,\n pi = patternIndex,\n fl = file.length,\n pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n let p = pattern[pi]\n let f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n /* c8 ignore start */\n if (p === false || p === GLOBSTAR) {\n return false\n }\n /* c8 ignore stop */\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n let hit: boolean\n if (typeof p === 'string') {\n hit = f === p\n this.debug('string match', p, f, hit)\n } else {\n hit = p.test(f)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n return fi === fl - 1 && file[fi] === ''\n\n /* c8 ignore start */\n } else {\n // should be unreachable.\n throw new Error('wtf?')\n }\n /* c8 ignore stop */\n }\n\n braceExpand() {\n return braceExpand(this.pattern, this.options)\n }\n\n parse(pattern: string): ParseReturn {\n assertValidPattern(pattern)\n\n const options = this.options\n\n // shortcuts\n if (pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n // far and away, the most common glob pattern parts are\n // *, *.*, and *.<ext> Add a fast check method for those.\n let m: RegExpMatchArray | null\n let fastTest: null | ((f: string) => boolean) = null\n if ((m = pattern.match(starRE))) {\n fastTest = options.dot ? starTestDot : starTest\n } else if ((m = pattern.match(starDotExtRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n starDotExtTestNocaseDot\n : starDotExtTestNocase\n : options.dot ? starDotExtTestDot\n : starDotExtTest)(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot ? qmarksTestDot\n : qmarksTest)(m)\n } else if ((m = pattern.match(starDotStarRE))) {\n fastTest = options.dot ? starDotStarTestDot : starDotStarTest\n } else if ((m = pattern.match(dotStarRE))) {\n fastTest = dotStarTest\n }\n\n const re = AST.fromGlob(pattern, this.options).toMMPattern()\n if (fastTest && typeof re === 'object') {\n // Avoids overriding in frozen environments\n Reflect.defineProperty(re, 'test', { value: fastTest })\n }\n return re\n }\n\n makeRe() {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n const set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n const options = this.options\n\n const twoStar =\n options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n const flags = new Set(options.nocase ? ['i'] : [])\n\n // regexpify non-globstar patterns\n // if ** is only item, then we just do one twoStar\n // if ** is first, and there are more, prepend (\\/|twoStar\\/)? to next\n // if ** is last, append (\\/twoStar|) to previous\n // if ** is in the middle, append (\\/|\\/twoStar\\/) to previous\n // then filter out GLOBSTAR symbols\n let re = set\n .map(pattern => {\n const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => {\n if (p instanceof RegExp) {\n for (const f of p.flags.split('')) flags.add(f)\n }\n return (\n typeof p === 'string' ? regExpEscape(p)\n : p === GLOBSTAR ? GLOBSTAR\n : p._src\n )\n }) as (string | typeof GLOBSTAR)[]\n pp.forEach((p, i) => {\n const next = pp[i + 1]\n const prev = pp[i - 1]\n if (p !== GLOBSTAR || prev === GLOBSTAR) {\n return\n }\n if (prev === undefined) {\n if (next !== undefined && next !== GLOBSTAR) {\n pp[i + 1] = '(?:\\\\/|' + twoStar + '\\\\/)?' + next\n } else {\n pp[i] = twoStar\n }\n } else if (next === undefined) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + ')?'\n } else if (next !== GLOBSTAR) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + '\\\\/)' + next\n pp[i + 1] = GLOBSTAR\n }\n })\n const filtered = pp.filter(p => p !== GLOBSTAR)\n\n // For partial matches, we need to make the pattern match\n // any prefix of the full path. We do this by generating\n // alternative patterns that match progressively longer prefixes.\n if (this.partial && filtered.length >= 1) {\n const prefixes: string[] = []\n for (let i = 1; i <= filtered.length; i++) {\n prefixes.push(filtered.slice(0, i).join('/'))\n }\n return '(?:' + prefixes.join('|') + ')'\n }\n\n return filtered.join('/')\n })\n .join('|')\n\n // need to wrap in parens if we had more than one thing with |,\n // otherwise only the first will be anchored to ^ and the last to $\n const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^' + open + re + close + '$'\n\n // In partial mode, '/' should always match as it's a valid prefix for any pattern\n if (this.partial) {\n re = '^(?:\\\\/|' + open + re.slice(1, -1) + close + ')$'\n }\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').+$'\n\n try {\n this.regexp = new RegExp(re, [...flags].join(''))\n /* c8 ignore start */\n } catch {\n // should be impossible\n this.regexp = false\n }\n /* c8 ignore stop */\n return this.regexp\n }\n\n slashSplit(p: string) {\n // if p starts with // on windows, we preserve that\n // so that UNC paths aren't broken. Otherwise, any number of\n // / characters are coalesced into one, unless\n // preserveMultipleSlashes is set to true.\n if (this.preserveMultipleSlashes) {\n return p.split('/')\n } else if (this.isWindows && /^\\/\\/[^/]+/.test(p)) {\n // add an extra '' for the one we lose\n return ['', ...p.split(/\\/+/)]\n } else {\n return p.split(/\\/+/)\n }\n }\n\n match(f: string, partial = this.partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) {\n return false\n }\n if (this.empty) {\n return f === ''\n }\n\n if (f === '/' && partial) {\n return true\n }\n\n const options = this.options\n\n // windows: need to use /, not \\\n if (this.isWindows) {\n f = f.split('\\\\').join('/')\n }\n\n // treat the test path as a set of pathparts.\n const ff = this.slashSplit(f)\n this.debug(this.pattern, 'split', ff)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n const set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n let filename: string = ff[ff.length - 1]\n if (!filename) {\n for (let i = ff.length - 2; !filename && i >= 0; i--) {\n filename = ff[i]\n }\n }\n\n for (const pattern of set) {\n let file = ff\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n const hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) {\n return true\n }\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) {\n return false\n }\n return this.negate\n }\n\n static defaults(def: MinimatchOptions) {\n return minimatch.defaults(def).Minimatch\n }\n}\n/* c8 ignore start */\nexport { AST } from './ast.js'\nexport { escape } from './escape.js'\nexport { unescape } from './unescape.js'\n/* c8 ignore stop */\nminimatch.AST = AST\nminimatch.Minimatch = Minimatch\nminimatch.escape = escape\nminimatch.unescape = unescape\n","import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\nfunction expand_(str: string, max: number, isTop: boolean): string[] {\n /** @type {string[]} */\n const expansions: string[] = []\n\n const m = balanced('{', '}', str)\n if (!m) return [str]\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n const post: string[] = m.post.length ? expand_(m.post, max, false) : ['']\n\n if (/\\$$/.test(m.pre)) {\n for (let k = 0; k < post.length && k < max; k++) {\n const expansion = pre + '{' + m.body + '}' + post[k]\n expansions.push(expansion)\n }\n } else {\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n return expand_(str, max, true)\n }\n return [str]\n }\n\n let n: string[]\n if (isSequence) {\n n = m.body.split(/\\.\\./)\n } else {\n n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n return post.map(p => m.pre + n[0] + p)\n }\n /* c8 ignore stop */\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n let N: string[]\n\n if (isSequence && n[0] !== undefined && n[1] !== undefined) {\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ?\n Math.max(Math.abs(numeric(n[2])), 1)\n : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n N = []\n\n for (let i = x; test(i, y); i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n N.push(c)\n }\n } else {\n N = []\n\n for (let j = 0; j < n.length; j++) {\n N.push.apply(N, expand_(n[j] as string, max, false))\n }\n }\n\n for (let j = 0; j < N.length; j++) {\n for (let k = 0; k < post.length && expansions.length < max; k++) {\n const expansion = pre + N[j] + post[k]\n if (!isTop || isSequence || expansion) {\n expansions.push(expansion)\n }\n }\n }\n }\n\n return expansions\n}\n","export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: unknown) => void = (\n pattern: unknown,\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport type { MinimatchOptions, MMRegExp } from './index.js'\nimport { unescape } from './unescape.js'\n\n// classes [] are handled by the parseClass method\n// for positive extglobs, we sub-parse the contents, and combine,\n// with the appropriate regexp close.\n// for negative extglobs, we sub-parse the contents, but then\n// have to include the rest of the pattern, then the parent, etc.,\n// as the thing that cannot be because RegExp negative lookaheads\n// are different from globs.\n//\n// So for example:\n// a@(i|w!(x|y)z|j)b => ^a(i|w((!?(x|y)zb).*)z|j)b$\n// 1 2 3 4 5 6 1 2 3 46 5 6\n//\n// Assembling the extglob requires not just the negated patterns themselves,\n// but also anything following the negative patterns up to the boundary\n// of the current pattern, plus anything following in the parent pattern.\n//\n//\n// So, first, we parse the string into an AST of extglobs, without turning\n// anything into regexps yet.\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y']}, 'z'], ['j']]}, 'b']\n//\n// Then, for all the negative extglobs, we append whatever comes after in\n// each parent as their tail\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y'], 'z', 'b'}, 'z'], ['j']]}, 'b']\n//\n// Lastly, we turn each of these pieces into a regexp, and join\n//\n// v----- .* because there's more following,\n// v v otherwise, .+ because it must be\n// v v *something* there.\n// ['^a', {@ ['i', 'w(?:(!?(?:x|y).*zb$).*)z', 'j' ]}, 'b$']\n// copy what follows into here--^^^^^\n// ['^a', '(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)', 'b$']\n// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']\n\nexport type ExtglobType = '!' | '?' | '+' | '*' | '@'\nconst types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])\nconst isExtglobType = (c: string | null): c is ExtglobType =>\n types.has(c as ExtglobType)\nconst isExtglobAST = (c: AST): c is AST & { type: ExtglobType } =>\n isExtglobType(c.type)\n\n// Map of which extglob types can adopt the children of a nested extglob\n//\n// anything but ! can adopt a matching type:\n// +(a|+(b|c)|d) => +(a|b|c|d)\n// *(a|*(b|c)|d) => *(a|b|c|d)\n// @(a|@(b|c)|d) => @(a|b|c|d)\n// ?(a|?(b|c)|d) => ?(a|b|c|d)\n//\n// * can adopt anything, because 0 or repetition is allowed\n// *(a|?(b|c)|d) => *(a|b|c|d)\n// *(a|+(b|c)|d) => *(a|b|c|d)\n// *(a|@(b|c)|d) => *(a|b|c|d)\n//\n// + can adopt @, because 1 or repetition is allowed\n// +(a|@(b|c)|d) => +(a|b|c|d)\n//\n// + and @ CANNOT adopt *, because 0 would be allowed\n// +(a|*(b|c)|d) => would match \"\", on *(b|c)\n// @(a|*(b|c)|d) => would match \"\", on *(b|c)\n//\n// + and @ CANNOT adopt ?, because 0 would be allowed\n// +(a|?(b|c)|d) => would match \"\", on ?(b|c)\n// @(a|?(b|c)|d) => would match \"\", on ?(b|c)\n//\n// ? can adopt @, because 0 or 1 is allowed\n// ?(a|@(b|c)|d) => ?(a|b|c|d)\n//\n// ? and @ CANNOT adopt * or +, because >1 would be allowed\n// ?(a|*(b|c)|d) => would match bbb on *(b|c)\n// @(a|*(b|c)|d) => would match bbb on *(b|c)\n// ?(a|+(b|c)|d) => would match bbb on +(b|c)\n// @(a|+(b|c)|d) => would match bbb on +(b|c)\n//\n// ! CANNOT adopt ! (nothing else can either)\n// !(a|!(b|c)|d) => !(a|b|c|d) would fail to match on b (not not b|c)\n//\n// ! can adopt @\n// !(a|@(b|c)|d) => !(a|b|c|d)\n//\n// ! CANNOT adopt *\n// !(a|*(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt +\n// !(a|+(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt ?\n// x!(a|?(b|c)|d) => x!(a|b|c|d) would fail to match \"x\"\nconst adoptionMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['@']],\n ['?', ['?', '@']],\n ['@', ['@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@']],\n])\n\n// nested extglobs that can be adopted in, but with the addition of\n// a blank '' element.\nconst adoptionWithSpaceMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?']],\n ['@', ['?']],\n ['+', ['?', '*']],\n])\n\n// union of the previous two maps\nconst adoptionAnyMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?', '@']],\n ['?', ['?', '@']],\n ['@', ['?', '@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@', '?', '*']],\n])\n\n// Extglobs that can take over their parent if they are the only child\n// the key is parent, value maps child to resulting extglob parent type\n// '@' is omitted because it's a special case. An `@` extglob with a single\n// member can always be usurped by that subpattern.\nconst usurpMap = new Map<\n ExtglobType,\n Map<ExtglobType | null, ExtglobType | null>\n>([\n ['!', new Map([['!', '@']])],\n [\n '?',\n new Map([\n ['*', '*'],\n ['+', '*'],\n ]),\n ],\n [\n '@',\n new Map([\n ['!', '!'],\n ['?', '?'],\n ['@', '@'],\n ['*', '*'],\n ['+', '+'],\n ]),\n ],\n [\n '+',\n new Map([\n ['?', '*'],\n ['*', '*'],\n ]),\n ],\n])\n\n// Patterns that get prepended to bind to the start of either the\n// entire string, or just a single path portion, to prevent dots\n// and/or traversal patterns, when needed.\n// Exts don't need the ^ or / bit, because the root binds that already.\nconst startNoTraversal = '(?!(?:^|/)\\\\.\\\\.?(?:$|/))'\nconst startNoDot = '(?!\\\\.)'\n\n// characters that indicate a start of pattern needs the \"no dots\" bit,\n// because a dot *might* be matched. ( is not in the list, because in\n// the case of a child extglob, it will handle the prevention itself.\nconst addPatternStart = new Set(['[', '.'])\n// cases where traversal is A-OK, no dot prevention needed\nconst justDots = new Set(['..', '.'])\nconst reSpecials = new Set('().*{}+?[]^$\\\\!')\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// any single thing other than /\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n// use + when we need to ensure that *something* matches, because the * is\n// the only thing in the path portion.\nconst starNoEmpty = qmark + '+?'\n\n// remove the \\ chars that we added if we end up doing a nonmagic compare\n// const deslash = (s: string) => s.replace(/\\\\(.)/g, '$1')\n\nlet ID = 0\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n #parent?: AST\n #parentIndex: number\n #negs: AST[]\n #filledNegs: boolean = false\n #options: MinimatchOptions\n #toString?: string\n // set to true if it's an extglob with no children\n // (which really means one child of '')\n #emptyExt: boolean = false\n id = ++ID\n\n get depth(): number {\n return (this.#parent?.depth ?? -1) + 1\n }\n\n [Symbol.for('nodejs.util.inspect.custom')]() {\n return {\n '@@type': 'AST',\n id: this.id,\n type: this.type,\n root: this.#root.id,\n parent: this.#parent?.id,\n depth: this.depth,\n partsLength: this.#parts.length,\n parts: this.#parts,\n }\n }\n\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n this.type = type\n // extglobs are inherently magical\n if (type) this.#hasMagic = true\n this.#parent = parent\n this.#root = this.#parent ? this.#parent.#root : this\n this.#options = this.#root === this ? options : this.#root.#options\n this.#negs = this.#root === this ? [] : this.#root.#negs\n if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)\n this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0\n }\n\n get hasMagic(): boolean | undefined {\n /* c8 ignore start */\n if (this.#hasMagic !== undefined) return this.#hasMagic\n /* c8 ignore stop */\n for (const p of this.#parts) {\n if (typeof p === 'string') continue\n if (p.type || p.hasMagic) return (this.#hasMagic = true)\n }\n // note: will be undefined until we generate the regexp src and find out\n return this.#hasMagic\n }\n\n // reconstructs the pattern\n toString(): string {\n return (\n this.#toString !== undefined ? this.#toString\n : !this.type ?\n (this.#toString = this.#parts.map(p => String(p)).join(''))\n : (this.#toString =\n this.type +\n '(' +\n this.#parts.map(p => String(p)).join('|') +\n ')')\n )\n }\n\n #fillNegs() {\n /* c8 ignore start */\n if (this !== this.#root) throw new Error('should only call on root')\n if (this.#filledNegs) return this\n /* c8 ignore stop */\n\n // call toString() once to fill this out\n this.toString()\n this.#filledNegs = true\n let n: AST | undefined\n while ((n = this.#negs.pop())) {\n if (n.type !== '!') continue\n // walk up the tree, appending everthing that comes AFTER parentIndex\n let p: AST | undefined = n\n let pp = p.#parent\n while (pp) {\n for (\n let i = p.#parentIndex + 1;\n !pp.type && i < pp.#parts.length;\n i++\n ) {\n for (const part of n.#parts) {\n /* c8 ignore start */\n if (typeof part === 'string') {\n throw new Error('string part in extglob AST??')\n }\n /* c8 ignore stop */\n part.copyIn(pp.#parts[i])\n }\n }\n p = pp\n pp = p.#parent\n }\n }\n return this\n }\n\n push(...parts: (string | AST)[]) {\n for (const p of parts) {\n if (p === '') continue\n /* c8 ignore start */\n if (\n typeof p !== 'string' &&\n !(p instanceof AST && p.#parent === this)\n ) {\n throw new Error('invalid part: ' + p)\n }\n /* c8 ignore stop */\n this.#parts.push(p)\n }\n }\n\n toJSON() {\n const ret: unknown[] =\n this.type === null ?\n this.#parts\n .slice()\n .map(p => (typeof p === 'string' ? p : p.toJSON()))\n : [this.type, ...this.#parts.map(p => (p as AST).toJSON())]\n if (this.isStart() && !this.type) ret.unshift([])\n if (\n this.isEnd() &&\n (this === this.#root ||\n (this.#root.#filledNegs && this.#parent?.type === '!'))\n ) {\n ret.push({})\n }\n return ret\n }\n\n isStart(): boolean {\n if (this.#root === this) return true\n // if (this.type) return !!this.#parent?.isStart()\n if (!this.#parent?.isStart()) return false\n if (this.#parentIndex === 0) return true\n // if everything AHEAD of this is a negation, then it's still the \"start\"\n const p = this.#parent\n for (let i = 0; i < this.#parentIndex; i++) {\n const pp = p.#parts[i]\n if (!(pp instanceof AST && pp.type === '!')) {\n return false\n }\n }\n return true\n }\n\n isEnd(): boolean {\n if (this.#root === this) return true\n if (this.#parent?.type === '!') return true\n if (!this.#parent?.isEnd()) return false\n if (!this.type) return this.#parent?.isEnd()\n // if not root, it'll always have a parent\n /* c8 ignore start */\n const pl = this.#parent ? this.#parent.#parts.length : 0\n /* c8 ignore stop */\n return this.#parentIndex === pl - 1\n }\n\n copyIn(part: AST | string) {\n if (typeof part === 'string') this.push(part)\n else this.push(part.clone(this))\n }\n\n clone(parent: AST) {\n const c = new AST(this.type, parent)\n for (const p of this.#parts) {\n c.copyIn(p)\n }\n return c\n }\n\n static #parseAST(\n str: string,\n ast: AST,\n pos: number,\n opt: MinimatchOptions,\n extDepth: number,\n ): number {\n const maxDepth = opt.maxExtglobRecursion ?? 2\n let escaping = false\n let inBrace = false\n let braceStart = -1\n let braceNeg = false\n if (ast.type === null) {\n // outside of a extglob, append until we find a start\n let i = pos\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n // we don't have to check for adoption here, because that's\n // done at the other recursion point.\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n extDepth <= maxDepth\n if (doRecurse) {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt, extDepth + 1)\n ast.push(ext)\n continue\n }\n acc += c\n }\n ast.push(acc)\n return i\n }\n\n // some kind of extglob, pos is at the (\n // find the next | or )\n let i = pos + 1\n let part = new AST(null, ast)\n const parts: AST[] = []\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n /* c8 ignore start - the maxDepth is sufficient here */\n (extDepth <= maxDepth || (ast && ast.#canAdoptType(c)))\n /* c8 ignore stop */\n if (doRecurse) {\n const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1\n part.push(acc)\n acc = ''\n const ext = new AST(c, part)\n part.push(ext)\n i = AST.#parseAST(str, ext, i, opt, extDepth + depthAdd)\n continue\n }\n if (c === '|') {\n part.push(acc)\n acc = ''\n parts.push(part)\n part = new AST(null, ast)\n continue\n }\n if (c === ')') {\n if (acc === '' && ast.#parts.length === 0) {\n ast.#emptyExt = true\n }\n part.push(acc)\n acc = ''\n ast.push(...parts, part)\n return i\n }\n acc += c\n }\n\n // unfinished extglob\n // if we got here, it was a malformed extglob! not an extglob, but\n // maybe something else in there.\n ast.type = null\n ast.#hasMagic = undefined\n ast.#parts = [str.substring(pos - 1)]\n return i\n }\n\n #canAdoptWithSpace(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n return this.#canAdopt(child, adoptionWithSpaceMap)\n }\n\n #canAdopt(\n child?: AST | string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionMap,\n ): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canAdoptType(\n gc.type,\n map,\n )\n }\n #canAdoptType(\n c: string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionAnyMap,\n ): c is ExtglobType {\n return !!map.get(this.type as ExtglobType)?.includes(c as ExtglobType)\n }\n\n #adoptWithSpace(\n this: AST & { type: ExtglobType },\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const blank = new AST(null, gc, this.options)\n blank.#parts.push('')\n gc.push(blank)\n this.#adopt(child, index)\n }\n\n #adopt(\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n this.#parts.splice(index, 1, ...gc.#parts)\n for (const p of gc.#parts) {\n if (typeof p === 'object') p.#parent = this\n }\n this.#toString = undefined\n }\n\n #canUsurpType(c: string): boolean {\n const m = usurpMap.get(this.type as ExtglobType)\n return !!m?.has(c as ExtglobType)\n }\n\n #canUsurp(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null ||\n this.#parts.length !== 1\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canUsurpType(gc.type)\n }\n\n #usurp(this: AST & { type: ExtglobType }, child: AST & { type: null }) {\n const m = usurpMap.get(this.type as ExtglobType)\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const nt = m?.get(gc.type)\n /* c8 ignore start - impossible */\n if (!nt) return false\n /* c8 ignore stop */\n this.#parts = gc.#parts\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#parent = this\n }\n }\n this.type = nt\n this.#toString = undefined\n this.#emptyExt = false\n }\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options, 0)\n return ast\n }\n\n // returns the regular expression if there's magic, or the unescaped\n // string if not.\n toMMPattern(): MMRegExp | string {\n // should only be called on root\n /* c8 ignore start */\n if (this !== this.#root) return this.#root.toMMPattern()\n /* c8 ignore stop */\n const glob = this.toString()\n const [re, body, hasMagic, uflag] = this.toRegExpSource()\n // if we're in nocase mode, and not nocaseMagicOnly, then we do\n // still need a regular expression if we have to case-insensitively\n // match capital/lowercase characters.\n const anyMagic =\n hasMagic ||\n this.#hasMagic ||\n (this.#options.nocase &&\n !this.#options.nocaseMagicOnly &&\n glob.toUpperCase() !== glob.toLowerCase())\n if (!anyMagic) {\n return body\n }\n\n const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')\n return Object.assign(new RegExp(`^${re}$`, flags), {\n _src: re,\n _glob: glob,\n })\n }\n\n get options() {\n return this.#options\n }\n\n // returns the string match, the regexp source, whether there's magic\n // in the regexp (so a regular expression is required) and whether or\n // not the uflag is needed for the regular expression (for posix classes)\n // TODO: instead of injecting the start/end at this point, just return\n // the BODY of the regexp, along with the start/end portions suitable\n // for binding the start/end in either a joined full-path makeRe context\n // (where we bind to (^|/), or a standalone matchPart context (where\n // we bind to ^, and not /). Otherwise slashes get duped!\n //\n // In part-matching mode, the start is:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: ^(?!\\.\\.?$)\n // - if dots allowed or not possible: ^\n // - if dots possible and not allowed: ^(?!\\.)\n // end is:\n // - if not isEnd(): nothing\n // - else: $\n //\n // In full-path matching mode, we put the slash at the START of the\n // pattern, so start is:\n // - if first pattern: same as part-matching mode\n // - if not isStart(): nothing\n // - if traversal possible, but not allowed: /(?!\\.\\.?(?:$|/))\n // - if dots allowed or not possible: /\n // - if dots possible and not allowed: /(?!\\.)\n // end is:\n // - if last pattern, same as part-matching mode\n // - else nothing\n //\n // Always put the (?:$|/) on negated tails, though, because that has to be\n // there to bind the end of the negated pattern portion, and it's easier to\n // just stick it in now rather than try to inject it later in the middle of\n // the pattern.\n //\n // We can just always return the same end, and leave it up to the caller\n // to know whether it's going to be used joined or in parts.\n // And, if the start is adjusted slightly, can do the same there:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: (?:/|^)(?!\\.\\.?$)\n // - if dots allowed or not possible: (?:/|^)\n // - if dots possible and not allowed: (?:/|^)(?!\\.)\n //\n // But it's better to have a simpler binding without a conditional, for\n // performance, so probably better to return both start options.\n //\n // Then the caller just ignores the end if it's not the first pattern,\n // and the start always gets applied.\n //\n // But that's always going to be $ if it's the ending pattern, or nothing,\n // so the caller can just attach $ at the end of the pattern when building.\n //\n // So the todo is:\n // - better detect what kind of start is needed\n // - return both flavors of starting pattern\n // - attach $ at the end of the pattern when creating the actual RegExp\n //\n // Ah, but wait, no, that all only applies to the root when the first pattern\n // is not an extglob. If the first pattern IS an extglob, then we need all\n // that dot prevention biz to live in the extglob portions, because eg\n // +(*|.x*) can match .xy but not .yx.\n //\n // So, return the two flavors if it's #root and the first child is not an\n // AST, otherwise leave it to the child AST to handle it, and there,\n // use the (?:^|/) style of start binding.\n //\n // Even simplified further:\n // - Since the start for a join is eg /(?!\\.) and the start for a part\n // is ^(?!\\.), we can just prepend (?!\\.) to the pattern (either root\n // or start or whatever) and prepend ^ or / at the Regexp construction.\n toRegExpSource(\n allowDot?: boolean,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n const dot = allowDot ?? !!this.#options.dot\n if (this.#root === this) {\n this.#flatten()\n this.#fillNegs()\n }\n if (!isExtglobAST(this)) {\n const noEmpty =\n this.isStart() &&\n this.isEnd() &&\n !this.#parts.some(s => typeof s !== 'string')\n const src = this.#parts\n .map(p => {\n const [re, _, hasMagic, uflag] =\n typeof p === 'string' ?\n AST.#parseGlob(p, this.#hasMagic, noEmpty)\n : p.toRegExpSource(allowDot)\n this.#hasMagic = this.#hasMagic || hasMagic\n this.#uflag = this.#uflag || uflag\n return re\n })\n .join('')\n\n let start = ''\n if (this.isStart()) {\n if (typeof this.#parts[0] === 'string') {\n // this is the string that will match the start of the pattern,\n // so we need to protect against dots and such.\n\n // '.' and '..' cannot match unless the pattern is that exactly,\n // even if it starts with . or dot:true is set.\n const dotTravAllowed =\n this.#parts.length === 1 && justDots.has(this.#parts[0])\n if (!dotTravAllowed) {\n const aps = addPatternStart\n // check if we have a possibility of matching . or ..,\n // and prevent that.\n const needNoTrav =\n // dots are allowed, and the pattern starts with [ or .\n (dot && aps.has(src.charAt(0))) ||\n // the pattern starts with \\., and then [ or .\n (src.startsWith('\\\\.') && aps.has(src.charAt(2))) ||\n // the pattern starts with \\.\\., and then [ or .\n (src.startsWith('\\\\.\\\\.') && aps.has(src.charAt(4)))\n // no need to prevent dots if it can't match a dot, or if a\n // sub-pattern will be preventing it anyway.\n const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))\n\n start =\n needNoTrav ? startNoTraversal\n : needNoDot ? startNoDot\n : ''\n }\n }\n }\n\n // append the \"end of path portion\" pattern to negation tails\n let end = ''\n if (\n this.isEnd() &&\n this.#root.#filledNegs &&\n this.#parent?.type === '!'\n ) {\n end = '(?:$|\\\\/)'\n }\n const final = start + src + end\n return [\n final,\n unescape(src),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n // We need to calculate the body *twice* if it's a repeat pattern\n // at the start, once in nodot mode, then again in dot mode, so a\n // pattern like *(?) can match 'x.y'\n\n const repeated = this.type === '*' || this.type === '+'\n // some kind of extglob\n const start = this.type === '!' ? '(?:(?!(?:' : '(?:'\n let body = (this as AST & { type: ExtglobType }).#partsToRegExp(dot)\n\n if (this.isStart() && this.isEnd() && !body && this.type !== '!') {\n // invalid extglob, has to at least be *something* present, if it's\n // the entire path portion.\n const s = this.toString()\n const me = this as AST\n me.#parts = [s]\n me.type = null\n me.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n let bodyDotAllowed =\n !repeated || allowDot || dot || !startNoDot ?\n ''\n : this.#partsToRegExp(true)\n if (bodyDotAllowed === body) {\n bodyDotAllowed = ''\n }\n if (bodyDotAllowed) {\n body = `(?:${body})(?:${bodyDotAllowed})*?`\n }\n\n // an empty !() is exactly equivalent to a starNoEmpty\n let final = ''\n if (this.type === '!' && this.#emptyExt) {\n final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty\n } else {\n const close =\n this.type === '!' ?\n // !() must match something,but !(x) can match ''\n '))' +\n (this.isStart() && !dot && !allowDot ? startNoDot : '') +\n star +\n ')'\n : this.type === '@' ? ')'\n : this.type === '?' ? ')?'\n : this.type === '+' && bodyDotAllowed ? ')'\n : this.type === '*' && bodyDotAllowed ? `)?`\n : `)${this.type}`\n final = start + body + close\n }\n return [\n final,\n unescape(body),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n #flatten() {\n if (!isExtglobAST(this)) {\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#flatten()\n }\n }\n } else {\n // do up to 10 passes to flatten as much as possible\n let iterations = 0\n let done = false\n do {\n done = true\n for (let i = 0; i < this.#parts.length; i++) {\n const c = this.#parts[i]\n if (typeof c === 'object') {\n c.#flatten()\n if (this.#canAdopt(c)) {\n done = false\n this.#adopt(c, i)\n } else if (this.#canAdoptWithSpace(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#adoptWithSpace(c, i)\n } else if (this.#canUsurp(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#usurp(c)\n }\n }\n }\n } while (!done && ++iterations < 10)\n }\n this.#toString = undefined\n }\n\n #partsToRegExp(this: AST & { type: ExtglobType }, dot: boolean) {\n return this.#parts\n .map(p => {\n // extglob ASTs should only contain parent ASTs\n /* c8 ignore start */\n if (typeof p === 'string') {\n throw new Error('string type in extglob ast??')\n }\n /* c8 ignore stop */\n // can ignore hasMagic, because extglobs are already always magic\n const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot)\n this.#uflag = this.#uflag || uflag\n return re\n })\n .filter(p => !(this.isStart() && this.isEnd()) || !!p)\n .join('|')\n }\n\n static #parseGlob(\n glob: string,\n hasMagic: boolean | undefined,\n noEmpty: boolean = false,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n let escaping = false\n let re = ''\n let uflag = false\n // multiple stars that aren't globstars coalesce into one *\n let inStar = false\n for (let i = 0; i < glob.length; i++) {\n const c = glob.charAt(i)\n if (escaping) {\n escaping = false\n re += (reSpecials.has(c) ? '\\\\' : '') + c\n continue\n }\n if (c === '*') {\n if (inStar) continue\n inStar = true\n re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star\n hasMagic = true\n continue\n } else {\n inStar = false\n }\n if (c === '\\\\') {\n if (i === glob.length - 1) {\n re += '\\\\\\\\'\n } else {\n escaping = true\n }\n continue\n }\n if (c === '[') {\n const [src, needUflag, consumed, magic] = parseClass(glob, i)\n if (consumed) {\n re += src\n uflag = uflag || needUflag\n i += consumed - 1\n hasMagic = hasMagic || magic\n continue\n }\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } =\n {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n }\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean,\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number,\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'\n : ranges.length ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then\n * square-bracket escapes are removed, but not backslash escapes.\n *\n * For example, it will turn the string `'[*]'` into `*`, but it will not\n * turn `'\\\\*'` into `'*'`, because `\\` is a path separator in\n * `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both square-bracket escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n *\n * When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be\n * unescaped.\n */\n\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = true,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\])\\]/g, '$1$2')\n .replace(/\\\\([^/])/g, '$1')\n }\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\{}])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\{}])\\]/g, '$1$2')\n .replace(/\\\\([^/{}])/g, '$1')\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import type { EventBus as CoreEventBus } from '../core/bus/index.js';\nimport type { AgentEventEnvelope } from '../core/adapter/types.js';\nimport type { EventFrame } from './events.js';\nimport type { Session } from '../core/session/Session.js';\nimport type { Persistence } from '../shared/persistence.js';\n\nexport interface BroadcastFn {\n (frame: EventFrame): void;\n}\n\nexport class EventPublisher {\n constructor(\n private bus: CoreEventBus,\n private broadcastFn?: BroadcastFn,\n private persistence?: Persistence\n ) {}\n\n publish(envelope: AgentEventEnvelope, session: Session): void {\n switch (envelope.type) {\n case 'session:start': {\n const resolvedCwd = (envelope.payload.cwd as string) || session.cwd || undefined;\n this.bus.publishSessionStart({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n agentType: session.agentType,\n cwd: resolvedCwd,\n });\n break;\n }\n case 'session:end':\n this.bus.publishSessionEnd({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n chatId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n });\n break;\n case 'turn:finished': {\n // payload.lastAssistantMessage 由上游统一提供 (hook/remote 各自转换)\n const lastAssistantMsg = (envelope.payload.lastAssistantMessage as string | undefined) ?? '';\n const thinkingMsg = (envelope.payload.thinking as string | undefined) ?? '';\n const durationVal = (envelope.payload.durationMs as number | undefined);\n const turnCwd = (envelope.payload.cwd as string) || session.cwd || undefined;\n this.bus.publishTurnFinished({\n sessionId: session.id,\n userId: session.token ?? 'unknown',\n chatId: session.token ?? 'unknown',\n agentType: session.agentType,\n lastAssistantMessage: lastAssistantMsg,\n thinking: thinkingMsg,\n durationMs: durationVal,\n // 透传其他 payload 字段\n ...envelope.payload,\n cwd: turnCwd,\n });\n break;\n }\n case 'permission:request':\n // PermissionRequest bus publishing is handled by InteractionService when queued.\n // We only broadcast the frame here for WebSocket clients.\n break;\n case 'tool:executed':\n this.bus.publishToolExecuted({\n sessionId: session.id,\n toolCallId: envelope.payload.toolCallId as string,\n toolName: envelope.payload.toolName as string,\n summary: envelope.payload.summary as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n output: envelope.payload.output as string | undefined,\n isTimeout: envelope.payload.isTimeout as boolean ?? false,\n });\n break;\n case 'tool:started':\n this.bus.publishToolPost({\n sessionId: session.id,\n toolCallId: envelope.payload.toolCallId as string,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n });\n break;\n case 'tool:failure':\n this.bus.publishToolFailure({\n sessionId: session.id,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n error: envelope.payload.error as string | undefined,\n });\n break;\n case 'turn:thinking':\n this.bus.publishTurnThinking(session.id, envelope.payload.thinking as string);\n break;\n }\n\n if (this.broadcastFn) {\n const frame: EventFrame = {\n type: 'event',\n event: envelope.type,\n payload: {\n agentType: session.agentType,\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n data: envelope.payload,\n },\n };\n this.broadcastFn(frame);\n }\n\n // Persist event to disk\n if (this.persistence) {\n this.persistence.write(session.id, session.agentType, {\n event: envelope.type,\n timestamp: new Date().toISOString(),\n data: envelope.payload,\n }).catch(() => {\n // Ignore persistence errors to avoid blocking event flow\n });\n }\n }\n}\n","// src/adapters/agent/claude/index.ts\n// Claude Agent Adapters\n\nexport { ClaudeHookAgentAdapter } from './ClaudeHookAgentAdapter.js';\nexport { ClaudeHookAgentAdapter as ClaudeHookAdapter } from './ClaudeHookAgentAdapter.js';\nexport { ClaudeRemoteAgentAdapter } from './ClaudeRemoteAgentAdapter.js';\nexport {\n isClaudeHookEventType,\n type ClaudeHookEventType,\n} from './hook-types.js';\nexport { ClaudeSessionScanner } from './scanner.js';\nexport { readClaudeJSONL, resolveTranscriptPath } from './jsonl-reader.js';\n","// src/adapters/agent/claude/ClaudeHookAgentAdapter.ts\n// Claude Hook Agent Adapter - processes hook events and permission requests\n//\n// =============================================================================\n// INTERACTION RULES (Permission & Question) — Hook Mode\n// =============================================================================\n//\n// Hook mode is listen-only: Claude Code CLI drives the session via HTTP hooks.\n// The gateway receives events from Claude and forwards them to channels (Feishu,\n// Telegram, etc.). User responses flow back through the same HTTP hook channel.\n//\n// --- Permission Request Flow (tool call approval) ---\n// 1. Claude CLI wants to run a tool (e.g. Bash, Read)\n// 2. Claude sends PreToolUse hook to gateway /hook/{token}/event\n// 3. Gateway calls processPermissionRequest(eventType='PreToolUse', payload, requestId)\n// 4. Builds InteractionRequest { type: 'permission', toolName, toolInput, requestId }\n// 5. Calls evaluateInteraction(bridge, request) → blocks until user responds\n// 6. User receives permission card (Feishu/Telegram) and clicks Allow/Deny\n// 7. Channel publishes interaction:response → bridge.resolveInteraction()\n// 8. evaluateInteraction resolves with { action: 'allow' | 'deny' }\n// 9. processPermissionRequest returns { action, requestId } to Claude hook\n// 10. Claude hook response MUST be JSON: { \"accepted\": true/false }\n// (This is the Claude hook protocol contract, not our internal format)\n//\n// --- Question Flow (AskUserQuestion tool) ---\n// 1. Claude CLI runs AskUserQuestion tool (single-select or multi-select)\n// 2. Claude sends PreToolUse hook with tool_name='AskUserQuestion'\n// 3. processPermissionRequest detects toolName==='AskUserQuestion'\n// 4. Builds InteractionRequest { type: 'question', toolName, toolInput, requestId }\n// 5. Calls evaluateInteraction(bridge, request) → blocks until user responds\n// 6. User receives question card:\n// - Single-select: button grid, one click submits\n// - Multi-select: checker list + Submit button, multiple clicks then submit\n// 7. Channel publishes interaction:response with action='select' and selectedValues\n// 8. evaluateInteraction resolves with { action: 'select', selectedValues }\n// 9. processPermissionRequest returns { action: 'allow', requestId } to hook\n// 10. Claude hook response format:\n// - For AskUserQuestion: { \"hookSpecificOutput\": { \"hookEventName\": \"PermissionRequest\", \"decision\": { \"behavior\": \"allow\", \"updatedInput\": { \"questions\": [...], \"answers\": { \"Q\": \"A\" } } } } }\n// - NOTE: The hook protocol wraps our internal decision in hookSpecificOutput\n//\n// --- Key Differences from Remote Mode ---\n// - Hook: Claude sends PreToolUse/PermissionRequest events, gateway responds via\n// HTTP hook response body (synchronous round-trip)\n// - Remote: SDK calls canCallTool/canAnswerQuestion callbacks, gateway resolves\n// via Promise (asynchronous, within the Claude stdio stream)\n// - Hook: supportsInboundPrompt = false (Claude drives, no user:message)\n// - Remote: supportsInboundPrompt = true (gateway can inject user messages)\n//\n// =============================================================================\n\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { AgentCommand, AgentEventEnvelope, AgentEventType } from '../../../core/adapter/types.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\nimport type { TranscriptEnricher } from '../../../core/adapter/TranscriptEnricher.js';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport { evaluateInteraction } from '../../../core/agent/interaction-utils.js';\nimport type { ClaudeHookEventType } from './hook-types.js';\nimport { readClaudeJSONL, resolveTranscriptPath } from './jsonl-reader.js';\n\nexport interface ClaudeHookAgentAdapterConfig {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n token?: string;\n}\n\n/**\n * Claude Hook Agent Adapter\n *\n * Extends BaseAgentAdapter to process Claude hook events and permission requests.\n * - Emits events via EventNormalizer.fromHookEvent() + emitEvent()\n * - Handles permission requests via evaluateInteraction()\n */\nexport class ClaudeHookAgentAdapter extends BaseAgentAdapter implements TranscriptEnricher {\n readonly agentType = 'claude' as const;\n readonly transportType = 'hook' as const;\n readonly version = '1.0.0';\n\n /** Hook mode is listen-only; Claude drives via HTTP hooks. */\n protected override get supportsInboundPrompt(): boolean { return false; }\n\n private token: string;\n\n constructor(config: ClaudeHookAgentAdapterConfig) {\n super(config);\n this.token = config.token ?? '';\n this.enricher = this; // self-register\n }\n\n // === Transport Lifecycle ===\n\n async createTransportState(opts: { sessionId?: string; cwd?: string }): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `hook-${Date.now()}`;\n const state: TransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n cwd: opts.cwd ?? process.cwd(),\n };\n\n this.transports.set(sessionId, state);\n return state;\n }\n\n async closeTransportState(state: TransportState): Promise<void> {\n this.transports.delete(state.sessionId);\n }\n\n async processHookEvent(eventType: ClaudeHookEventType, payload: Record<string, unknown>): Promise<void> {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n if (!sessionId) {\n this.logger.debug({ eventType }, 'processHookEvent: no session_id in payload, skipping');\n return;\n }\n\n // SessionStart must create the session first so subsequent events have a session to bind to.\n if (eventType === 'SessionStart') {\n try {\n await this.bridge.ensureSession(sessionId, {\n cwd: payload.cwd as string | undefined,\n chatId: payload.chat_id as string | undefined,\n channel: payload.channel as string | undefined,\n metadata: {\n rawEventType: eventType,\n },\n }, this.agentType);\n\n const model = typeof payload.model === 'string' ? payload.model : undefined;\n if (model) {\n this.bridge.updateSessionInfo(sessionId, { model });\n }\n } catch (err) {\n this.logger.warn({ sessionId, error: err instanceof Error ? err.message : String(err) }, 'ensureSession failed during SessionStart');\n }\n // createSession already publishes session:start; skip duplicate emission\n return;\n }\n\n const envelope = EventNormalizer.fromHookEvent(\n eventType, payload, this.agentType, this.transportType\n );\n if (!envelope) return;\n\n const enriched = await this.enrichIfNeeded(envelope);\n this.emitEvent(enriched);\n }\n\n // === TranscriptEnricher implementation ===\n\n canEnrich(eventType: AgentEventType): boolean {\n return eventType === 'turn:finished';\n }\n\n async enrich(envelope: AgentEventEnvelope): Promise<AgentEventEnvelope> {\n const { sessionId, payload } = envelope;\n\n // Resolve transcript path: prefer payload.transcriptPath, fallback to cwd + sessionId\n const transcriptPath =\n typeof payload.transcriptPath === 'string' ? payload.transcriptPath\n : typeof payload.cwd === 'string' ? resolveTranscriptPath(payload.cwd, sessionId)\n : undefined;\n\n if (!transcriptPath) {\n return envelope;\n }\n\n const summary = await readClaudeJSONL(transcriptPath);\n if (!summary) {\n return envelope;\n }\n\n // Only fill missing fields — event-provided values always win\n const enrichedPayload: Record<string, unknown> = { ...payload };\n\n if (payload.durationMs === undefined && summary.durationMs !== undefined) {\n enrichedPayload.durationMs = summary.durationMs;\n }\n\n if (payload.usage === undefined && summary.inputTokens !== undefined && summary.outputTokens !== undefined) {\n enrichedPayload.usage = {\n inputTokens: summary.inputTokens,\n outputTokens: summary.outputTokens,\n };\n }\n\n return {\n ...envelope,\n payload: enrichedPayload,\n };\n }\n\n /**\n * Handle permission/question requests from Claude hook events.\n *\n * Called for both PreToolUse (regular tools) and PermissionRequest events.\n * When toolName === 'AskUserQuestion', the request type is 'question' instead\n * of 'permission', which causes channels to render question cards (single/multi\n * select) instead of permission cards (Allow/Deny).\n *\n * evaluateInteraction blocks until the user responds via a channel. The response\n * is returned to Claude as part of the HTTP hook response body.\n *\n * See file header for full flow diagrams.\n */\n async processPermissionRequest(\n eventType: 'PreToolUse' | 'PermissionRequest',\n payload: Record<string, unknown>,\n requestId: string\n ): Promise<InteractionResponse> {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : 'unknown';\n\n if (!sessionId) {\n this.logger.warn({ eventType, requestId }, 'processPermissionRequest: no session_id in payload');\n return { requestId, action: 'deny', message: 'Missing session_id' };\n }\n\n // AskUserQuestion is handled as a 'question' type; everything else is 'permission'\n const interactionRequest: InteractionRequest = {\n type: toolName === 'AskUserQuestion' ? 'question' : 'permission',\n requestId,\n sessionId,\n toolName,\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n timestamp: Date.now(),\n };\n\n try {\n return await evaluateInteraction(this.bridge, interactionRequest);\n } catch (err) {\n this.logger.error({ err, requestId }, 'Permission evaluation failed');\n return { requestId, action: 'deny', message: 'Evaluation error' };\n }\n }\n\n async sendCommand(_state: TransportState, command: AgentCommand): Promise<void> {\n switch (command.type) {\n case 'stop': {\n this.logger.info({ sessionId: _state.sessionId }, 'Stop command received for hook transport');\n await this.closeTransportState(_state);\n break;\n }\n case 'user:message':\n // Hook mode: Claude drives via HTTP hooks; user:message is a no-op\n this.logger.debug({ sessionId: _state.sessionId }, 'user:message command ignored in hook mode');\n break;\n case 'interrupt':\n this.logger.debug({ sessionId: _state.sessionId }, 'interrupt command ignored in hook mode');\n break;\n default:\n this.logger.debug({ sessionId: _state.sessionId, commandType: command.type }, 'Unhandled command in hook mode');\n }\n }\n\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { InboundMessage } from '../bus/events.js';\nimport type { AgentBridgePort } from './AgentBridgePort.js';\nimport type { AgentAdapter, TransportState, TransportInfo } from '../adapter/AgentAdapter.js';\nimport type { AgentEventEnvelope, AgentCommand, CreateSessionOptions } from '../adapter/types.js';\nimport type { TranscriptEnricher } from '../adapter/TranscriptEnricher.js';\nimport { parseInboundCommand } from './inbound-utils.js';\n\nexport interface BaseAgentAdapterConfig {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n}\n\nexport interface AgentCommandHandler {\n description: string;\n usage?: string;\n handler: (args: string[], message: InboundMessage) => Promise<string | void>;\n}\n\nexport abstract class BaseAgentAdapter implements AgentAdapter {\n protected readonly bus: EventBus;\n protected readonly bridge: AgentBridgePort;\n protected readonly logger: Logger;\n protected readonly transports = new Map<string, TransportState>();\n private readonly agentCommands = new Map<string, AgentCommandHandler>();\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private unsubscribeFns: Array<() => void> = [];\n protected enricher?: TranscriptEnricher;\n\n abstract readonly agentType: 'claude' | 'codex';\n abstract readonly transportType: 'hook' | 'sdk' | 'stdio' | 'remote';\n abstract readonly version: string;\n\n constructor(config: BaseAgentAdapterConfig) {\n this.bus = config.bus;\n this.bridge = config.bridge;\n this.logger = config.logger;\n }\n\n async initialize(): Promise<void> {\n this.subscribeInbound();\n this.logger.info(`${this.agentType} adapter initializing`);\n }\n\n async shutdown(): Promise<void> {\n for (const [sessionId, state] of this.transports) {\n try {\n await this.closeTransportState(state);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Error closing transport during shutdown');\n }\n }\n this.transports.clear();\n this.unsubscribeFns.forEach(fn => fn());\n this.unsubscribeFns = [];\n this.logger.info(`${this.agentType} adapter shutdown complete`);\n }\n\n /**\n * Whether this adapter supports receiving plain text as user prompts.\n * Override to `false` for passive/listen-only adapters (e.g. hook).\n */\n protected get supportsInboundPrompt(): boolean { return true; }\n\n /**\n * Register an agent-specific command.\n * Subclasses call this in their constructor to add custom commands\n * (e.g. `/claude model gpt-4`).\n */\n protected registerCommand(keyword: string, handler: AgentCommandHandler): void {\n this.agentCommands.set(keyword.toLowerCase(), handler);\n }\n\n abstract createTransportState(opts: CreateSessionOptions): Promise<TransportState>;\n abstract closeTransportState(state: TransportState): Promise<void>;\n abstract sendCommand(state: TransportState, command: AgentCommand): Promise<void>;\n\n async listTransportStates(): Promise<TransportInfo[]> {\n return Array.from(this.transports.values()).map(s => ({\n sessionId: s.sessionId,\n agentType: s.agentType,\n transportType: s.transportType,\n createdAt: new Date(),\n }));\n }\n\n async getTransportState(sessionId: string): Promise<TransportInfo | undefined> {\n const state = this.transports.get(sessionId);\n if (!state) return undefined;\n return {\n sessionId: state.sessionId,\n agentType: state.agentType,\n transportType: state.transportType,\n createdAt: new Date(),\n };\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return { healthy: true, message: `${this.transports.size} active transports` };\n }\n\n protected emitEvent(envelope: AgentEventEnvelope): void {\n if (this.eventHandler) {\n this.eventHandler(envelope);\n }\n this.bridge.emitEvent(envelope);\n }\n\n /**\n * Enrich the event envelope if a {@link TranscriptEnricher} is configured and\n * capable of handling this event type.\n *\n * Subclasses should call this in their async methods **before**\n * {@link emitEvent}. {@link emitEvent} remains synchronous by design because\n * downstream consumers (e.g. {@link TurnAggregator} callbacks) expect sync\n * execution. The async nature of enrichment means there may be an interleaving\n * gap between the call to this method and the subsequent emit.\n */\n protected async enrichIfNeeded(envelope: AgentEventEnvelope): Promise<AgentEventEnvelope> {\n if (!this.enricher?.canEnrich(envelope.type)) {\n return envelope;\n }\n try {\n return await this.enricher.enrich(envelope);\n } catch (err) {\n this.logger.warn(\n { sessionId: envelope.sessionId, eventType: envelope.type, error: err instanceof Error ? err.message : String(err) },\n 'Transcript enrichment failed, emitting original envelope'\n );\n return envelope;\n }\n }\n\n protected getHelpText(): string {\n const lines = [\n `${this.agentType} commands:`,\n `${this.prefix} help - show this help message`,\n `${this.prefix} status - show the current chat session state`,\n `${this.prefix} stop - stop the active session for this chat`,\n ];\n for (const [keyword, handler] of this.agentCommands) {\n lines.push(`${this.prefix} ${keyword}${handler.usage ? ` ${handler.usage}` : ''} - ${handler.description}`);\n }\n if (this.supportsInboundPrompt) {\n lines.push('Send any text to interact with the agent.');\n } else {\n lines.push('Send text to interact with the agent from its native interface.');\n }\n return lines.join('\\n');\n }\n\n private get prefix(): string {\n return `/${this.agentType}`;\n }\n\n protected subscribeInbound(): void {\n if (this.unsubscribeFns.length) return;\n this.unsubscribeFns.push(\n this.bus.onInbound((msg: InboundMessage) => this.handleInboundMessage(msg))\n );\n }\n\n /**\n * Resolve session ID from inbound message. Subclasses may override to\n * return a stable session ID based on transport-level identity (e.g.\n * Claude SDK session_id).\n */\n protected resolveSessionId(_message: InboundMessage): string | undefined {\n return undefined;\n }\n\n protected async handleInboundMessage(message: InboundMessage): Promise<void> {\n const text = message.text.trim();\n this.logger.debug({ channel: message.channel, chatId: message.chatId, targetAgent: message.targetAgent }, 'Inbound message received');\n\n if (message.systemCommand) return;\n if (message.targetAgent !== this.agentType) return;\n\n const parsed = parseInboundCommand(text, this.prefix);\n const sessionId = this.resolveSessionId(message) ?? `${this.agentType}-${message.sender.id}`;\n\n if (!parsed) {\n // Non-command text (e.g. \"hi\"): treat as prompt for agent-driven transports.\n if (!this.supportsInboundPrompt) {\n this.logger.debug({ sessionId, textPreview: text.slice(0, 60) }, 'Inbound prompt ignored: adapter does not support user input');\n return;\n }\n await this.handlePrompt(sessionId, message, text);\n return;\n }\n\n const keyword = parsed.keyword.toLowerCase();\n\n // Empty keyword (e.g. \"/claude\" with no args) → show help\n if (!keyword) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n }\n\n // 1. Agent-specific custom commands take priority\n const agentHandler = this.agentCommands.get(keyword);\n if (agentHandler) {\n try {\n const result = await agentHandler.handler(parsed.args, message);\n if (result) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: result });\n }\n } catch (err) {\n this.logger.error({ sessionId, keyword, error: err instanceof Error ? err.message : String(err) }, 'Agent command failed');\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `Command /${this.agentType} ${keyword} failed: ${err instanceof Error ? err.message : String(err)}` });\n }\n return;\n }\n\n // 2. Base generic commands as fallback\n switch (keyword) {\n case 'help':\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n case 'status': {\n const session = this.bridge.getSession(sessionId);\n const reply = session && session.getStatus() === 'active'\n ? `${this.agentType} session is active.\\nSession ID: ${sessionId}`\n : `No active ${this.agentType} session for this chat.`;\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: reply });\n return;\n }\n case 'stop': {\n const session = this.bridge.getSession(sessionId);\n if (!session) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `No active ${this.agentType} session to stop.` });\n return;\n }\n await session.sendCommand({ type: 'stop' });\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `${this.agentType} session stopped.` });\n return;\n }\n }\n\n // 3. Unknown keyword — treat as prompt if supported\n if (!this.supportsInboundPrompt) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: `Unknown command /${this.agentType} ${keyword}. Run /${this.agentType} help for available commands.` });\n return;\n }\n await this.handlePrompt(sessionId, message, parsed.content);\n }\n\n protected async handlePrompt(sessionId: string, message: InboundMessage, content: string): Promise<void> {\n const session = await this.bridge.ensureSession(sessionId, {\n chatId: message.chatId,\n channel: message.channel,\n metadata: {\n messageId: message.messageId,\n senderId: message.sender?.id,\n },\n }, this.agentType);\n await session.sendCommand({ type: 'user:message', content });\n }\n}\n","export interface ParsedCommand {\n /** First keyword after the agent prefix (e.g. 'help', 'model', 'status') */\n keyword: string;\n /** Remaining arguments */\n args: string[];\n /** Full remaining text after the keyword (for prompt) */\n content: string;\n}\n\n/**\n * Parse an inbound command string.\n * Supports:\n * /agent help → { keyword: 'help', args: [], content: '' }\n * /agent model gpt-4 → { keyword: 'model', args: ['gpt-4'], content: 'gpt-4' }\n * /agent hello world → { keyword: 'hello', args: ['world'], content: 'hello world' }\n *\n * Returns null if the text does not start with the given prefix.\n */\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function parseInboundCommand(text: string, prefix: string): ParsedCommand | null {\n const explicit = text.match(new RegExp(`^${escapeRegExp(prefix)}(?:@[^\\\\s]+)?(?:\\\\s+(.*))?$`, 's'));\n if (!explicit) return null;\n\n const rest = explicit[1]?.trim() ?? '';\n if (!rest) return { keyword: '', args: [], content: '' };\n\n const [keyword, ...args] = rest.split(/\\s+/);\n return {\n keyword,\n args,\n content: rest,\n };\n}\n\nexport function buildHelpText(agentName: string, prefix: string): string {\n return [\n `${agentName} commands:`,\n `${prefix} help - show this help message`,\n `${prefix} status - show the current chat session state`,\n `${prefix} stop - stop the active session for this chat`,\n `${prefix} <prompt> - run a task in the current chat`,\n 'Any other text is sent to the agent as a prompt.',\n ].join('\\n');\n}\n","import type { AgentEventEnvelope, AgentEventType, AgentType, TransportType } from '../adapter/types.js';\nimport type { InteractionRequest } from '../interaction/types.js';\nimport type { MergedTool, TurnResult } from './TurnAggregator.js';\n\nexport interface TurnFinishedExtra {\n durationMs?: number;\n usage?: {\n inputTokens: number;\n outputTokens: number;\n cacheReadInputTokens?: number;\n cacheCreationInputTokens?: number;\n };\n transcriptPath?: string;\n}\n\nexport class EventNormalizer {\n static sessionStart(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n payload?: Record<string, unknown>,\n extraMetadata?: Record<string, unknown>\n ): AgentEventEnvelope {\n return this.build('session:start', sessionId, agentType, transportType, {\n sessionId,\n ...payload,\n }, extraMetadata);\n }\n\n static sessionEnd(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n reason?: string\n ): AgentEventEnvelope {\n return this.build('session:end', sessionId, agentType, transportType, { sessionId, reason });\n }\n\n static turnStarted(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType\n ): AgentEventEnvelope {\n return this.build('turn:started', sessionId, agentType, transportType, { sessionId });\n }\n\n static turnThinking(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n thinking: string\n ): AgentEventEnvelope {\n return this.build('turn:thinking', sessionId, agentType, transportType, { sessionId, thinking });\n }\n\n static turnFinished(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n result: TurnResult,\n extra?: TurnFinishedExtra\n ): AgentEventEnvelope {\n return this.build('turn:finished', sessionId, agentType, transportType, {\n sessionId,\n lastAssistantMessage: result.lastAssistantMessage,\n thinking: result.thinking,\n tools: (result.tools ?? []).map(t => ({\n toolCallId: t.toolCallId,\n toolName: t.toolName,\n summary: t.summary,\n toolInput: t.toolInput,\n output: t.output,\n isTimeout: t.isTimeout,\n })),\n durationMs: extra?.durationMs,\n usage: extra?.usage,\n transcriptPath: extra?.transcriptPath,\n });\n }\n\n static toolExecuted(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n tool: MergedTool\n ): AgentEventEnvelope {\n return this.build('tool:executed', sessionId, agentType, transportType, {\n sessionId,\n toolCallId: tool.toolCallId,\n toolName: tool.toolName,\n summary: tool.summary,\n toolInput: tool.toolInput,\n output: tool.output,\n isTimeout: tool.isTimeout,\n });\n }\n\n static toolFailure(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n tool: MergedTool,\n error?: string\n ): AgentEventEnvelope {\n return this.build('tool:failure', sessionId, agentType, transportType, {\n sessionId,\n toolCallId: tool.toolCallId,\n toolName: tool.toolName,\n summary: tool.summary,\n toolInput: tool.toolInput,\n error,\n });\n }\n\n static permissionRequest(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n request: InteractionRequest\n ): AgentEventEnvelope {\n return this.build('permission:request', sessionId, agentType, transportType, {\n sessionId,\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n }, { permissionRequestId: request.requestId });\n }\n\n static questionRequest(\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n request: InteractionRequest\n ): AgentEventEnvelope {\n return this.build('question:request', sessionId, agentType, transportType, {\n sessionId,\n toolName: request.toolName,\n toolInput: request.toolInput,\n requestId: request.requestId,\n }, { questionRequestId: request.requestId });\n }\n\n static fromHookEvent(\n eventType: string,\n payload: Record<string, unknown>,\n agentType: AgentType = 'claude',\n transportType: TransportType = 'hook'\n ): AgentEventEnvelope | null {\n const mapping: Record<string, AgentEventType> = {\n SessionStart: 'session:start',\n SessionEnd: 'session:end',\n PreToolUse: 'permission:request',\n PermissionRequest: 'permission:request',\n PostToolUse: 'tool:executed',\n PostToolUseFailure: 'tool:failure',\n Stop: 'turn:finished',\n };\n\n const type = mapping[eventType];\n if (!type) return null;\n\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : '';\n if (!sessionId) return null;\n\n const common = {\n sessionId,\n cwd: typeof payload.cwd === 'string' ? payload.cwd : undefined,\n permissionMode: typeof payload.permission_mode === 'string' ? payload.permission_mode : undefined,\n };\n\n switch (type) {\n case 'session:start':\n return this.build(type, sessionId, agentType, transportType, { ...common, permissionMode: common.permissionMode }, {\n rawEventType: eventType, permissionMode: common.permissionMode,\n });\n case 'session:end':\n return this.build(type, sessionId, agentType, transportType, { ...common, reason: payload.reason as string | undefined }, {\n rawEventType: eventType, permissionMode: common.permissionMode,\n });\n case 'permission:request': {\n /**\n * PreToolUse event contract:\n * - tool_name === 'AskUserQuestion' → maps to 'question:request'\n * - any other tool_name → maps to 'permission:request'\n * This mirrors the logic in ClaudeHookAgentAdapter.processPermissionRequest\n */\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : '';\n const isQuestion = toolName === 'AskUserQuestion';\n const requestId = typeof payload.request_id === 'string' ? payload.request_id : sessionId;\n return this.build(\n isQuestion ? 'question:request' : 'permission:request',\n sessionId,\n agentType,\n transportType,\n { ...common, toolName, toolInput: (payload.tool_input as Record<string, unknown>) || {}, requestId },\n { rawEventType: eventType, [isQuestion ? 'questionRequestId' : 'permissionRequestId']: requestId }\n );\n }\n case 'tool:executed':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n toolCallId: payload.id as string | undefined,\n toolName: payload.tool_name as string | undefined,\n toolInput: payload.tool_input as Record<string, unknown> | undefined,\n output: payload.output as string | undefined,\n }, { rawEventType: eventType });\n case 'tool:failure':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n toolName: payload.tool_name as string | undefined,\n toolInput: payload.tool_input as Record<string, unknown> | undefined,\n error: payload.error as string | undefined,\n }, { rawEventType: eventType });\n case 'turn:finished':\n return this.build(type, sessionId, agentType, transportType, {\n ...common,\n reason: payload.reason as string | undefined,\n lastAssistantMessage: payload.last_assistant_message as string | undefined,\n durationMs: typeof payload.duration === 'number' ? payload.duration : undefined,\n transcriptPath: typeof payload.transcript_path === 'string' ? payload.transcript_path : undefined,\n }, { rawEventType: eventType });\n default:\n return null;\n }\n }\n\n private static build(\n type: AgentEventType,\n sessionId: string,\n agentType: AgentType,\n transportType: TransportType,\n payload: Record<string, unknown>,\n extraMetadata?: Record<string, unknown>\n ): AgentEventEnvelope {\n return {\n type,\n sessionId,\n timestamp: new Date().toISOString(),\n agentType,\n payload,\n metadata: {\n transportType,\n ...extraMetadata,\n },\n };\n }\n}\n","import type { AgentBridgePort } from './AgentBridgePort.js';\nimport type { InteractionRequest, InteractionResponse } from '../interaction/types.js';\n\n/**\n * Evaluate an interaction request and normalize the response for Claude.\n *\n * Contract rules for AskUserQuestion:\n * - When action === 'select' or 'input', wraps response with updatedInput:\n * { answers: { [questionText]: answerValue } }\n * - Hook mode: this updatedInput becomes hookSpecificOutput.decision.updatedInput\n * - Remote mode: this updatedInput becomes PermissionResult.updatedInput\n * (ClaudeRemoteAgentAdapter extracts the answer string from selectedValues[0])\n */\nexport async function evaluateInteraction(\n bridge: AgentBridgePort,\n request: InteractionRequest\n): Promise<InteractionResponse> {\n const originalResponse = await bridge.evaluateInteraction(request);\n\n if (\n request.toolName === 'AskUserQuestion' &&\n (originalResponse.action === 'select' || originalResponse.action === 'input')\n ) {\n const questions = request.toolInput?.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; value?: unknown }>;\n multiSelect?: boolean;\n }> | undefined;\n const question = questions?.[0];\n const questionText = question?.question ?? '';\n const answerValue = originalResponse.selectedValues?.[0] ?? originalResponse.customInput ?? '';\n\n return {\n ...originalResponse,\n updatedInput: {\n ...request.toolInput,\n answers: { [questionText]: answerValue },\n },\n };\n }\n\n return originalResponse;\n}\n","import { readFile } from 'fs/promises';\nimport { resolve } from 'path';\nimport { getLogger } from '../../../shared/logger.js';\n\nexport interface SessionSummary {\n inputTokens?: number;\n outputTokens?: number;\n durationMs?: number;\n thinking?: string;\n lastAssistantMessage?: string;\n}\n\ninterface TranscriptEntry {\n type?: string;\n uuid?: string;\n parentUuid?: string;\n timestamp?: string | number;\n message?: {\n content?: Array<{ type: string; text?: string; thinking?: string }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n}\n\n/**\n * Read a Claude JSONL transcript and extract session summary.\n * Includes retry logic because the transcript may not be fully written\n * when the Stop hook fires.\n */\nexport async function readClaudeJSONL(transcriptPath: string): Promise<SessionSummary | undefined> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= 5; attempt++) {\n try {\n const content = await readFile(transcriptPath, 'utf-8');\n const summary = parseTranscript(content);\n // Retry if summary has no data at all (handles timing issue where transcript isn't fully written)\n // Note: summary with only durationMs is valid (e.g., thinking-only assistant message)\n if (summary && (summary.lastAssistantMessage !== undefined || summary.durationMs !== undefined)) {\n return summary;\n }\n if (summary) {\n getLogger().debug({ attempt, summary }, 'Transcript read but incomplete, retrying...');\n }\n } catch (error) {\n lastError = error;\n }\n if (attempt < 5) {\n await new Promise((resolve) => setTimeout(resolve, 200));\n }\n }\n getLogger().warn({ error: lastError instanceof Error ? lastError.message : String(lastError), transcriptPath }, 'Failed to read transcript or transcript incomplete');\n return undefined;\n}\n\n/**\n * Resolve the JSONL file path from cwd and sessionId.\n *\n * Claude stores transcripts at:\n * ~/.claude/projects/{projectDirName}/{sessionId}.jsonl\n *\n * Where {projectDirName} is cwd with path separators replaced by '-'.\n * Example: /Users/hymane/workspace/project/handsoff -> -Users-hymane-workspace-project-handsoff\n *\n * @param cwd - The current working directory of the project (used to derive the directory name).\n * @param sessionId - The unique session identifier (becomes the JSONL filename).\n * @returns The absolute path to the expected transcript file.\n */\nexport function resolveTranscriptPath(cwd: string, sessionId: string): string {\n const projectDirName = cwd.replace(/[\\\\/]/g, '-');\n return resolve(process.env.HOME || '', '.claude', 'projects', projectDirName, `${sessionId}.jsonl`);\n}\n\nfunction parseTranscript(content: string): SessionSummary | undefined {\n const lines = content.split('\\n').filter((line) => line.trim().length > 0);\n\n let lastAssistantMessage: string | undefined;\n let thinking: string | undefined;\n let inputTokens: number | undefined;\n let outputTokens: number | undefined;\n\n let lastTextAssistant: { ts: number; uuid?: string; parentUuid?: string } | undefined;\n let lastAnyAssistant: { ts: number; uuid?: string; parentUuid?: string } | undefined;\n const userTimestamps = new Map<string, number>();\n const parentMap = new Map<string, string>();\n\n for (const line of lines) {\n let entry: TranscriptEntry;\n try {\n entry = JSON.parse(line) as TranscriptEntry;\n } catch (parseError) {\n getLogger().warn(\n { error: parseError instanceof Error ? parseError.message : String(parseError), line: line.slice(0, 200) },\n 'Skipping malformed transcript line'\n );\n continue;\n }\n\n const ts =\n typeof entry.timestamp === 'string'\n ? new Date(entry.timestamp).getTime()\n : typeof entry.timestamp === 'number'\n ? entry.timestamp\n : undefined;\n\n if (entry.uuid && typeof entry.parentUuid === 'string') {\n parentMap.set(entry.uuid, entry.parentUuid);\n }\n\n if (entry.type === 'user' && ts !== undefined && entry.uuid) {\n userTimestamps.set(entry.uuid, ts);\n }\n\n if (entry.type === 'assistant' && ts !== undefined) {\n const arr = Array.isArray(entry.message?.content) ? entry.message.content : [];\n const textBlock = arr.find((c) => c.type === 'text');\n const thinkingBlock = arr.find((c) => c.type === 'thinking');\n const assistantRef = { ts, uuid: entry.uuid, parentUuid: entry.parentUuid };\n lastAnyAssistant = assistantRef;\n\n if (textBlock && typeof textBlock.text === 'string') {\n lastAssistantMessage = textBlock.text;\n lastTextAssistant = assistantRef;\n }\n\n if (thinkingBlock && typeof thinkingBlock.thinking === 'string') {\n thinking = thinkingBlock.thinking;\n }\n\n if (textBlock) {\n const usage = entry.message?.usage;\n if (usage) {\n if (typeof usage.input_tokens === 'number') inputTokens = usage.input_tokens;\n if (typeof usage.output_tokens === 'number') outputTokens = usage.output_tokens;\n }\n }\n }\n }\n\n const durationMs = resolveDuration(lastTextAssistant, userTimestamps, parentMap)\n ?? resolveDuration(lastAnyAssistant, userTimestamps, parentMap);\n\n const summary: SessionSummary = {};\n if (lastAssistantMessage !== undefined) summary.lastAssistantMessage = lastAssistantMessage;\n if (thinking !== undefined) summary.thinking = thinking;\n if (inputTokens !== undefined) summary.inputTokens = inputTokens;\n if (outputTokens !== undefined) summary.outputTokens = outputTokens;\n if (durationMs !== undefined) summary.durationMs = durationMs;\n\n return Object.keys(summary).length > 0 ? summary : undefined;\n}\n\nfunction resolveDuration(\n assistantRef: { ts: number; uuid?: string; parentUuid?: string } | undefined,\n userTimestamps: Map<string, number>,\n parentMap: Map<string, string>,\n): number | undefined {\n if (!assistantRef) return undefined;\n if (assistantRef.parentUuid) {\n const directParentTs = userTimestamps.get(assistantRef.parentUuid);\n if (directParentTs !== undefined) {\n return assistantRef.ts - directParentTs;\n }\n }\n let currentUuid = assistantRef.uuid;\n const visited = new Set<string>();\n while (currentUuid && !visited.has(currentUuid)) {\n visited.add(currentUuid);\n const parentUuid = parentMap.get(currentUuid);\n if (!parentUuid) break;\n const parentTs = userTimestamps.get(parentUuid);\n if (parentTs !== undefined) {\n return assistantRef.ts - parentTs;\n }\n currentUuid = parentUuid;\n }\n return undefined;\n}\n","// =============================================================================\n// INTERACTION RULES (Permission & Question) — Remote Mode\n// =============================================================================\n//\n// Remote mode spawns the Claude CLI binary via SDK/stdio. The gateway drives\n// the session by pushing user messages into the Claude input stream. Claude's\n// lifecycle events (tool calls, questions, results) arrive as SDK messages.\n//\n// --- Permission Request Flow (tool call approval) ---\n// 1. Claude CLI wants to run a tool (e.g. Bash, Read)\n// 2. SDK calls canCallTool(toolName, toolInput, { signal }) callback\n// 3. Gateway handleCanCallTool(sessionId, toolName, toolInput, signal)\n// 4. Builds InteractionRequest { type: 'permission', toolName, toolInput, requestId }\n// 5. Calls evaluateInteraction(bridge, request) → blocks until user responds\n// 6. User receives permission card (Feishu/Telegram) and clicks Allow/Deny\n// 7. Channel publishes interaction:response → bridge.resolveInteraction()\n// 8. evaluateInteraction resolves with { action: 'allow' | 'deny' }\n// 9. handleCanCallTool resolves Promise<PermissionResult> with:\n// { behavior: 'allow' | 'deny', updatedInput?, message? }\n// 10. SDK receives result; if allowed, Claude proceeds with tool execution\n//\n// --- Question Flow (AskUserQuestion tool) ---\n// 1. Claude CLI runs AskUserQuestion tool (single-select or multi-select)\n// 2. SDK calls canAnswerQuestion(question, { signal }) callback\n// 3. Gateway handleCanAnswerQuestion(sessionId, question, signal)\n// 4. Builds InteractionRequest { type: 'question', toolName:'AskUserQuestion',\n// toolInput: { questions: [{ question }] }, requestId }\n// 5. Calls evaluateInteraction(bridge, request) → blocks until user responds\n// 6. User receives question card:\n// - Single-select: button grid, one click submits\n// - Multi-select: checker list + Submit button, multiple clicks then submit\n// 7. Channel publishes interaction:response with action='select' and selectedValues\n// 8. evaluateInteraction (interaction-utils.ts) wraps response with updatedInput:\n// { answers: { [questionText]: answerValue } }\n// 9. handleCanAnswerQuestion resolves Promise<QuestionResult> with:\n// { action: 'answer', answer: String(selectedValues[0] || customInput) }\n// 10. SDK receives answer string; Claude proceeds with tool result\n//\n// --- Key Differences from Hook Mode ---\n// - Remote: SDK callbacks (canCallTool, canAnswerQuestion) use Promise-based\n// async resolution within the stdio stream\n// - Hook: Claude sends HTTP hook events; gateway responds via hook response body\n// - Remote: supportsInboundPrompt = true (gateway can push user:message)\n// - Hook: supportsInboundPrompt = false (Claude drives, no injection)\n// - Remote: PermissionResult uses { behavior: 'allow'|'deny' }\n// - Hook: Returns { action: 'allow'|'deny' } which becomes { accepted: true|false }\n//\n// =============================================================================\n\nimport { randomUUID } from 'crypto';\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport { evaluateInteraction } from '../../../core/agent/interaction-utils.js';\nimport { TurnAggregator } from '../../../core/agent/TurnAggregator.js';\nimport type { MergedTool } from '../../../core/agent/TurnAggregator.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { AgentCommand, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { ClaudeSessionScanner } from './scanner.js';\nimport { query } from './sdk/query.js';\nimport type { SDKMessage, SDKUserMessage, PermissionResult, QuestionResult } from './sdk/types.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\n\ninterface RemoteTransportState extends TransportState {\n query: ReturnType<typeof query>;\n input: PushableAsyncIterable<SDKUserMessage>;\n aggregator: TurnAggregator;\n turnInProgress: boolean;\n chatId: string;\n channel: string;\n cwd: string;\n permissionMode?: string;\n senderId?: string;\n}\n\nclass PushableAsyncIterable<T> implements AsyncIterable<T> {\n private queue: T[] = [];\n private resolvers: Array<(value: IteratorResult<T>) => void> = [];\n private ended = false;\n\n push(value: T): void {\n if (this.ended) return;\n if (this.resolvers.length > 0) {\n const resolve = this.resolvers.shift()!;\n resolve({ done: false, value });\n } else {\n this.queue.push(value);\n }\n }\n\n end(): void {\n this.ended = true;\n while (this.resolvers.length > 0) {\n const resolve = this.resolvers.shift()!;\n resolve({ done: true, value: undefined });\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: () => {\n if (this.queue.length > 0) {\n return Promise.resolve({ done: false, value: this.queue.shift()! });\n }\n if (this.ended) {\n return Promise.resolve({ done: true, value: undefined });\n }\n return new Promise((resolve) => {\n this.resolvers.push(resolve);\n });\n },\n return: () => {\n this.end();\n return Promise.resolve({ done: true, value: undefined });\n },\n };\n }\n}\n\nexport class ClaudeRemoteAgentAdapter extends BaseAgentAdapter {\n readonly agentType = 'claude' as const;\n readonly transportType = 'remote' as const;\n readonly version = '1.0.0';\n private static scanner: ClaudeSessionScanner | null = null;\n private static readonly CONTROL_REQUEST_TIMEOUT_MS = 300000;\n\n private token: string;\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n private defaultWorkDir?: string;\n private defaultModel?: string;\n private defaultPermissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n\n private static readonly VALID_PERMISSION_MODES = ['default', 'acceptEdits', 'bypassPermissions', 'plan'] as const;\n\n /** Maps sender.id → real Claude session_id for stable multi-turn sessions */\n private senderSessionMap = new Map<string, string>();\n\n constructor(options: {\n bus: EventBus;\n bridge: AgentBridgePort;\n logger: Logger;\n token: string;\n command?: string[];\n cwd?: string;\n env?: Record<string, string>;\n defaultWorkDir?: string;\n defaultModel?: string;\n defaultPermissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n }) {\n super({ bus: options.bus, bridge: options.bridge, logger: options.logger });\n this.token = options.token;\n this.command = options.command?.length ? options.command : ['claude'];\n this.spawnCwd = options.cwd;\n this.envExtra = options.env ?? {};\n this.defaultWorkDir = options.defaultWorkDir;\n this.defaultModel = options.defaultModel;\n this.defaultPermissionMode = options.defaultPermissionMode;\n\n this.registerCommand('model', {\n description: 'Set default model for new sessions',\n usage: '<model-name>',\n handler: async (args) => {\n const model = args[0];\n if (!model) return 'Usage: /claude model <model-name> (e.g. sonnet, opus)';\n this.defaultModel = model;\n return `Default model set to ${model}. Will apply on next session.`;\n },\n });\n\n this.registerCommand('permission', {\n description: 'Set default permission mode',\n usage: '<default|acceptEdits|bypassPermissions|plan>',\n handler: async (args) => {\n const mode = args[0] as typeof this.defaultPermissionMode;\n const valid = ClaudeRemoteAgentAdapter.VALID_PERMISSION_MODES;\n if (!valid.includes(mode as (typeof valid)[number])) {\n return `Invalid mode \"${mode}\". Available: ${valid.join(', ')}`;\n }\n this.defaultPermissionMode = mode;\n return `Default permission mode set to ${mode}.`;\n },\n });\n }\n\n async initialize(): Promise<void> {\n await super.initialize();\n this.logger.info('ClaudeRemoteAgentAdapter initializing');\n try {\n const { execSync } = await import('child_process');\n execSync(`${this.command[0]} --version`, { encoding: 'utf8', windowsHide: true });\n this.logger.info('Claude CLI detected');\n } catch (err) {\n this.logger.warn('Claude CLI not found');\n throw err;\n }\n\n if (!ClaudeRemoteAgentAdapter.scanner) {\n ClaudeRemoteAgentAdapter.scanner = new ClaudeSessionScanner();\n SessionScannerRegistry.getInstance().register(ClaudeRemoteAgentAdapter.scanner);\n this.logger.info('Claude session scanner registered');\n }\n }\n\n /**\n * Return the real Claude session_id if this sender already has an active session.\n * This makes multi-turn conversations stable across turns.\n */\n protected resolveSessionId(message: InboundMessage): string | undefined {\n return this.senderSessionMap.get(message.sender.id);\n }\n\n async createTransportState(opts: CreateSessionOptions): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `claude-${randomUUID().slice(0, 8)}`;\n const chatId = opts.chatId ?? sessionId;\n const channel = opts.channel ?? 'broadcast';\n const cwd = opts.cwd || this.defaultWorkDir || process.cwd();\n this.logger.info({ sessionId, chatId, cwd, optsCwd: opts.cwd, defaultWorkDir: this.defaultWorkDir }, 'Creating Claude remote transport state');\n\n const input = new PushableAsyncIterable<SDKUserMessage>();\n const q = query({\n prompt: input,\n options: {\n cwd: this.spawnCwd,\n model: opts.model ?? this.defaultModel,\n permissionMode: this.defaultPermissionMode,\n env: this.envExtra,\n pathToClaudeCodeExecutable: this.command[0],\n bare: true,\n canCallTool: (toolName, toolInput, { signal }) => this.handleCanCallTool(sessionId, toolName, toolInput, signal),\n canAnswerQuestion: (question, { signal }) => this.handleCanAnswerQuestion(sessionId, question, signal),\n },\n });\n\n const aggregator = new TurnAggregator(this.logger, sessionId);\n aggregator.onThinkingChunk = (_chunk: string) => {\n // Noop: streaming not implemented yet.\n };\n\n const state: RemoteTransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n query: q,\n input,\n aggregator,\n turnInProgress: false,\n chatId,\n channel,\n cwd,\n permissionMode: this.defaultPermissionMode,\n senderId: opts.metadata?.senderId as string | undefined,\n };\n\n this.transports.set(sessionId, state);\n\n this.emitEvent(EventNormalizer.sessionStart(sessionId, this.agentType, this.transportType, {\n chatId,\n channel,\n cwd,\n ...opts.metadata,\n }));\n\n this.consumeQueryMessages(q, state).catch((err) => {\n this.logger.error({ sessionId, error: err }, 'Query consumer error');\n });\n\n this.logger.info({ sessionId }, 'Claude remote transport state created');\n return state;\n }\n\n async closeTransportState(state: TransportState): Promise<void> {\n const remoteState = state as RemoteTransportState;\n const sessionId = remoteState.sessionId;\n this.logger.info({ sessionId }, 'Closing Claude remote transport state');\n\n remoteState.input.end();\n remoteState.query.kill('SIGTERM');\n remoteState.aggregator.reset();\n this.transports.delete(sessionId);\n\n // Clean up sender → session mapping so the next message spawns a fresh session\n if (remoteState.senderId) {\n this.senderSessionMap.delete(remoteState.senderId);\n }\n\n this.emitEvent(EventNormalizer.sessionEnd(sessionId, this.agentType, this.transportType, 'close'));\n }\n\n async sendCommand(state: TransportState, command: AgentCommand): Promise<void> {\n const remoteState = state as RemoteTransportState;\n const sessionId = remoteState.sessionId;\n\n switch (command.type) {\n case 'user:message': {\n if (remoteState.turnInProgress) {\n this.logger.warn({ sessionId }, 'Concurrent turn rejected');\n this.bus.publishOutbound({\n channel: remoteState.channel,\n chatId: remoteState.chatId,\n text: 'Claude is still processing the previous message. Please wait.',\n });\n return;\n }\n remoteState.aggregator.startTurn();\n remoteState.turnInProgress = true;\n this.emitEvent(EventNormalizer.turnStarted(sessionId, this.agentType, this.transportType));\n remoteState.input.push({\n type: 'user',\n message: { role: 'user', content: command.content },\n });\n break;\n }\n case 'interrupt': {\n this.logger.info({ sessionId }, 'Interrupting turn');\n await remoteState.query.interrupt();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n await this.closeTransportState(remoteState);\n break;\n }\n default: {\n this.logger.warn({ sessionId, commandType: command.type }, 'Unsupported command');\n }\n }\n }\n\n // === Internal ===\n\n private async consumeQueryMessages(q: ReturnType<typeof query>, state: RemoteTransportState): Promise<void> {\n try {\n for await (const msg of q) {\n await this.handleSdkMessage(msg, state);\n }\n } catch (err) {\n this.logger.error({ sessionId: state.sessionId, error: err }, 'Claude remote stream ended with error');\n this.bus.publishOutbound({\n channel: state.channel,\n chatId: state.chatId,\n text: 'Claude session ended unexpectedly.',\n });\n } finally {\n state.aggregator.reset();\n state.turnInProgress = false;\n this.transports.delete(state.sessionId);\n this.emitEvent(EventNormalizer.sessionEnd(state.sessionId, this.agentType, this.transportType, 'stream_ended'));\n }\n }\n\n private async handleSdkMessage(msg: SDKMessage, state: RemoteTransportState): Promise<void> {\n const sessionId = state.sessionId;\n switch (msg.type) {\n case 'system': {\n const system = msg as { session_id?: string; subtype?: string; model?: string; slash_commands?: string[] };\n if (system.subtype === 'init' && system.session_id) {\n const claudeSessionId = system.session_id;\n this.logger.info({ sessionId, claudeSessionId }, 'Claude session initialized');\n\n // Rename Handsoff session key to the real Claude session_id\n if (claudeSessionId !== sessionId) {\n const renamed = this.bridge.renameSessionId(sessionId, claudeSessionId);\n if (renamed) {\n this.transports.delete(sessionId);\n state.sessionId = claudeSessionId;\n this.transports.set(claudeSessionId, state);\n this.logger.info({ oldId: sessionId, newId: claudeSessionId }, 'Session renamed to Claude session_id');\n }\n }\n\n this.bridge.updateSessionInfo(claudeSessionId, {\n model: system.model,\n slashCommands: system.slash_commands,\n permissionMode: state.permissionMode,\n });\n\n // Store mapping so next inbound message from the same sender reuses this session\n if (state.senderId) {\n this.senderSessionMap.set(state.senderId, claudeSessionId);\n }\n }\n break;\n }\n\n case 'assistant': {\n const assistant = msg as { message?: { content?: Array<{ type: string; text?: string; thinking?: string; name?: string; input?: unknown; id?: string }> } };\n const blocks = Array.isArray(assistant.message?.content) ? assistant.message.content : [];\n for (const block of blocks) {\n if (block.type === 'text' && typeof block.text === 'string') {\n state.aggregator.addAssistantText(block.text);\n }\n if (block.type === 'thinking' && typeof block.thinking === 'string') {\n state.aggregator.addThinking(block.thinking);\n }\n if (block.type === 'tool_use') {\n const toolName = typeof block.name === 'string' ? block.name : 'unknown';\n const toolCallId = typeof block.id === 'string' ? block.id : Math.random().toString(36).substring(2);\n state.aggregator.addPendingTool(toolCallId, toolName, block.input ?? {}, () => {});\n }\n }\n break;\n }\n\n case 'user': {\n const user = msg as { message?: { content?: string | Array<{ type: string; text?: string; tool_use_id?: string }> } };\n const content = user.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {\n state.aggregator.resolveTool(block.tool_use_id, block.text ?? '', (merged: MergedTool) => {\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, merged));\n });\n }\n }\n }\n break;\n }\n\n case 'result': {\n const result = msg as { subtype?: string; result?: string; duration_ms?: number; usage?: { input_tokens: number; output_tokens: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number } };\n this.logger.info({ sessionId, subtype: result.subtype }, 'Claude turn result');\n\n const thinking = state.aggregator.getThinking();\n const flushResult = state.aggregator.flushTurn((merged: MergedTool) => {\n const envelope = merged.isTimeout\n ? EventNormalizer.toolFailure(sessionId, this.agentType, this.transportType, merged)\n : EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, merged);\n this.emitEvent(envelope);\n });\n\n if (thinking) {\n this.emitEvent(EventNormalizer.turnThinking(sessionId, this.agentType, this.transportType, thinking));\n }\n\n this.emitEvent(\n EventNormalizer.turnFinished(sessionId, this.agentType, this.transportType, flushResult, {\n durationMs: result.duration_ms,\n usage: result.usage\n ? {\n inputTokens: result.usage.input_tokens,\n outputTokens: result.usage.output_tokens,\n cacheReadInputTokens: result.usage.cache_read_input_tokens,\n cacheCreationInputTokens: result.usage.cache_creation_input_tokens,\n }\n : undefined,\n })\n );\n state.turnInProgress = false;\n break;\n }\n\n case 'log': {\n const log = msg as { log?: { level?: string; message?: string } };\n const level = log.log?.level ?? 'debug';\n const message = log.log?.message ?? '';\n if (level === 'error') this.logger.error({ sessionId }, message);\n else if (level === 'warn') this.logger.warn({ sessionId }, message);\n else if (level === 'info') this.logger.info({ sessionId }, message);\n else this.logger.debug({ sessionId }, message);\n break;\n }\n }\n }\n\n /**\n * Handle tool permission requests from the Claude SDK.\n *\n * The SDK calls this callback when Claude wants to run a tool. We block\n * the Promise until the user responds via a channel (Feishu/Telegram).\n *\n * Resolution values:\n * - allow → { behavior: 'allow', updatedInput? }\n * - deny → { behavior: 'deny', message }\n *\n * See file header for full flow diagram.\n */\n private async handleCanCallTool(sessionId: string, toolName: string, toolInput: unknown, signal: AbortSignal): Promise<PermissionResult> {\n const state = this.transports.get(sessionId) as RemoteTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId, toolName }, 'Permission request but session not found, auto-denying');\n return { behavior: 'deny', message: 'Session not found' };\n }\n\n const requestId = `${sessionId}-${Math.random().toString(36).substring(2, 10)}`;\n this.logger.info({ sessionId, requestId, toolName }, 'Claude remote permission request');\n\n const interactionRequest: InteractionRequest = {\n requestId,\n sessionId,\n type: 'permission',\n toolName,\n toolInput: (toolInput ?? {}) as Record<string, unknown>,\n timestamp: Date.now(),\n };\n\n return new Promise<PermissionResult>((resolve) => {\n const timeout = setTimeout(() => {\n this.logger.warn({ sessionId, requestId }, 'Permission request timeout');\n resolve({ behavior: 'deny', message: 'Timeout' });\n }, ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve({ behavior: 'deny', message: 'Aborted' });\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n evaluateInteraction(this.bridge, interactionRequest).then((response) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n\n const decision: 'allow' | 'deny' = response.action === 'allow' ? 'allow' : 'deny';\n\n this.logger.info({ sessionId, requestId, toolName, decision }, 'Claude remote permission resolved');\n resolve({\n behavior: decision,\n updatedInput: response.updatedInput,\n ...(decision === 'deny' ? { message: 'User denied this tool call' } : {}),\n } as PermissionResult);\n }).catch((err) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n this.logger.error({ error: err, sessionId, requestId }, 'Claude remote permission handler error');\n resolve({ behavior: 'deny', message: 'Error' });\n });\n });\n }\n\n /**\n * Handle question requests from the Claude SDK (AskUserQuestion tool).\n *\n * The SDK calls this callback when Claude runs AskUserQuestion. We block\n * the Promise until the user selects an answer via a channel.\n *\n * For multi-select questions, the interaction-utils wraps the response\n * with updatedInput containing { answers: { [questionText]: answerValue } }.\n *\n * Resolution values:\n * - answer → { action: 'answer', answer: string }\n * - deny → { action: 'deny', message }\n *\n * See file header for full flow diagram.\n */\n private async handleCanAnswerQuestion(sessionId: string, question: string, signal: AbortSignal): Promise<QuestionResult> {\n const state = this.transports.get(sessionId) as RemoteTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId }, 'Question request but session not found, auto-deny');\n return { action: 'deny', message: 'Session not found' };\n }\n\n const requestId = `${sessionId}-${Math.random().toString(36).substring(2, 10)}`;\n this.logger.info({ sessionId, requestId, question }, 'Claude remote question request');\n\n const interactionRequest: InteractionRequest = {\n requestId,\n sessionId,\n type: 'question',\n toolName: 'AskUserQuestion',\n toolInput: { questions: [{ question }] },\n timestamp: Date.now(),\n };\n\n return new Promise<QuestionResult>((resolve) => {\n const timeout = setTimeout(() => {\n this.logger.warn({ sessionId, requestId }, 'Question request timeout');\n resolve({ action: 'deny', message: 'Timeout' });\n }, ClaudeRemoteAgentAdapter.CONTROL_REQUEST_TIMEOUT_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve({ action: 'deny', message: 'Aborted' });\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n evaluateInteraction(this.bridge, interactionRequest).then((response) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n if (!response) {\n resolve({ action: 'deny', message: 'No response' });\n return;\n }\n if (response.action === 'allow' || response.action === 'select') {\n const answer = response.selectedValues?.[0] ?? response.customInput ?? '';\n resolve({ action: 'answer', answer: String(answer) });\n } else {\n resolve({ action: 'deny', message: response.message ?? 'User denied' });\n }\n }).catch((err) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n this.logger.error({ error: err, sessionId, requestId }, 'Claude remote question handler error');\n resolve({ action: 'deny', message: 'Error' });\n });\n });\n }\n}\n","import type { Logger } from 'pino';\n\ninterface ToolPending {\n toolCallId: string;\n toolName: string;\n toolInput: unknown;\n hasBeenResolved?: boolean;\n}\n\nexport interface MergedTool {\n toolCallId: string;\n toolName: string;\n summary: string;\n toolInput: unknown;\n output?: string;\n isTimeout: boolean;\n}\n\nexport interface TurnResult {\n lastAssistantMessage: string;\n thinking: string;\n tools: MergedTool[];\n}\n\nexport class TurnAggregator {\n private assistantParts: string[] = [];\n private thinkingParts: string[] = [];\n private pendingTools = new Map<string, ToolPending>();\n /** Track tool_call_ids whose result has already been emitted (out-of-order or orphaned tool_result) */\n private resolvedToolCallIds = new Set<string>();\n private turnInProgress = false;\n\n constructor(\n private logger: Logger,\n private sessionId: string,\n ) {}\n\n startTurn(): void {\n this.reset();\n this.turnInProgress = true;\n }\n\n addAssistantText(content: string): void {\n this.assistantParts.push(content);\n }\n\n addThinking(content: string): void {\n this.thinkingParts.push(content);\n // [Extension Point] Streaming thinking: onThinkingChunk fires here per chunk.\n // Currently noop; streaming upgrade activates it in ClaudeRemoteAdapter.startSession().\n this.onThinkingChunk?.(content);\n }\n\n /**\n * [Extension Point — Streaming Thinking]\n * Callback for streaming thinking events. Set by the owner to emit thinking chunks\n * as they arrive (real-time streaming to Feishu/Telegram).\n *\n * Current behavior: set to noop in ClaudeRemoteAdapter.startSession(). The complete\n * thinking is emitted as a single turn:thinking event in handleResult.\n *\n * Future streaming upgrade: replace the noop with a debounced emit that sends\n * accumulated thinking every N ms or per chunk, without waiting for turn end.\n * No changes needed in TurnAggregator, NotificationHandler, or Feishu formatter —\n * only this callback implementation changes.\n */\n onThinkingChunk?: (chunk: string) => void;\n\n addPendingTool(\n toolCallId: string,\n toolName: string,\n toolInput: unknown,\n _onMerged: (tool: MergedTool) => void,\n ): void {\n // If this tool_call_id was already resolved out-of-order, skip creating a pending\n if (this.resolvedToolCallIds.has(toolCallId)) {\n this.logger.debug({ sessionId: this.sessionId, toolCallId }, 'tool_use arrived after out-of-order tool_result, skipping duplicate pending');\n this.resolvedToolCallIds.delete(toolCallId);\n return;\n }\n\n this.pendingTools.set(toolCallId, { toolCallId, toolName, toolInput, hasBeenResolved: false });\n }\n\n resolveTool(\n toolCallId: string,\n output: string,\n onMerged: (tool: MergedTool) => void,\n ): void {\n const pending = this.pendingTools.get(toolCallId);\n if (!pending) {\n // Out-of-order: tool_result arrived before tool_use (or already timed out).\n // Record it so addPendingTool doesn't create a duplicate pending.\n if (this.resolvedToolCallIds.has(toolCallId)) {\n this.logger.debug({ sessionId: this.sessionId, toolCallId }, 'tool_result already processed, skipping duplicate');\n return;\n }\n this.resolvedToolCallIds.add(toolCallId);\n this.logger.warn({ sessionId: this.sessionId, toolCallId }, 'tool_result without matching tool_use');\n onMerged({\n toolCallId,\n toolName: 'unknown',\n summary: output.slice(0, 100),\n toolInput: {},\n output,\n isTimeout: false,\n });\n return;\n }\n\n pending.hasBeenResolved = true;\n this.pendingTools.delete(toolCallId);\n const merged = this.buildMergedTool(pending, output, false);\n onMerged(merged);\n }\n\n flushTurn(onTool: (tool: MergedTool) => void): TurnResult {\n this.turnInProgress = false;\n\n const flushedTools: MergedTool[] = [];\n for (const [toolCallId, pending] of this.pendingTools) {\n pending.hasBeenResolved = true;\n this.resolvedToolCallIds.add(toolCallId);\n const merged = this.buildMergedTool(pending, undefined, true);\n flushedTools.push(merged);\n onTool(merged);\n }\n this.pendingTools.clear();\n\n const lastAssistantMessage = this.assistantParts.join('\\n');\n const thinking = this.thinkingParts.join('\\n');\n this.assistantParts = [];\n this.thinkingParts = [];\n\n return { lastAssistantMessage, thinking, tools: flushedTools };\n }\n\n reset(): void {\n this.turnInProgress = false;\n this.pendingTools.clear();\n this.resolvedToolCallIds.clear();\n this.assistantParts = [];\n this.thinkingParts = [];\n }\n\n isTurnInProgress(): boolean {\n return this.turnInProgress;\n }\n\n /**\n * Get accumulated thinking content without flushing.\n *\n * [Extension Point] Used by ClaudeRemoteAdapter to read accumulated thinking before\n * calling flushTurn(), which resets thinkingParts. This allows the owner to emit a\n * complete turn:thinking event before the aggregator state is cleared.\n *\n * For streaming upgrades, this is not needed — onThinkingChunk already emits per-chunk.\n */\n getThinking(): string {\n return this.thinkingParts.join('\\n');\n }\n\n private buildMergedTool(pending: ToolPending, output: string | undefined, isTimeout: boolean): MergedTool {\n const summary = this.buildToolSummary(pending.toolName, pending.toolInput, output);\n return {\n toolCallId: pending.toolCallId,\n toolName: pending.toolName,\n summary,\n toolInput: pending.toolInput,\n output,\n isTimeout,\n };\n }\n\n private buildToolSummary(toolName: string, input: unknown, output: string | undefined): string {\n const inputStr = this.truncate(JSON.stringify(input ?? {}), 200);\n const outputStr = output ? ` -> ${this.truncate(output, 200)}` : '';\n return `${toolName}: ${inputStr}${outputStr}`;\n }\n\n private truncate(str: string, max: number): string {\n return str.length > max ? `${str.slice(0, max)}...` : str;\n }\n}\n","// src/core/session-scanner/index.ts\n\nexport * from './types.js';\nexport { SessionScannerRegistry } from './registry.js';\n","// src/core/session-scanner/types.ts\n\nimport type { AgentType } from '../adapter/types.js';\nimport type { SessionInfo } from '../adapter/types.js';\n\n/**\n * Session Scanner 接口\n * 各 CLI adapter 实现此接口来提供 session 发现能力\n */\nexport interface SessionScanner {\n /** 对应的 agent 类型 */\n readonly agentType: AgentType;\n\n /** Session 文件目录 */\n getSessionDir(): string;\n\n /**\n * 扫描所有 session\n * @returns SessionInfo 列表\n */\n scanSessions(): Promise<SessionInfo[]>;\n}\n","// src/core/session-scanner/registry.ts\n\nimport type { AgentType } from '../adapter/types.js';\nimport type { SessionInfo } from '../adapter/types.js';\nimport type { SessionScanner } from './types.js';\n\n/**\n * Session Scanner 注册表\n * 管理所有 CLI 的 Scanner 实现\n */\nexport class SessionScannerRegistry {\n private scanners: Map<AgentType, SessionScanner> = new Map();\n\n /**\n * 注册 Scanner\n */\n register(scanner: SessionScanner): void {\n if (this.scanners.has(scanner.agentType)) {\n console.warn(`Scanner for ${scanner.agentType} already registered, overwriting`);\n }\n this.scanners.set(scanner.agentType, scanner);\n }\n\n /**\n * 注销 Scanner\n */\n unregister(agentType: AgentType): void {\n this.scanners.delete(agentType);\n }\n\n /**\n * 获取指定类型的 Scanner\n */\n getScanner(agentType: AgentType): SessionScanner | undefined {\n return this.scanners.get(agentType);\n }\n\n /**\n * 扫描所有 agent 的 session\n */\n async scanAll(): Promise<SessionInfo[]> {\n const results = await Promise.all(\n Array.from(this.scanners.values()).map((scanner) => scanner.scanSessions())\n );\n return results.flat();\n }\n\n /**\n * 按 agent 类型扫描\n */\n async scanByAgent(agentType: AgentType): Promise<SessionInfo[]> {\n const scanner = this.scanners.get(agentType);\n if (!scanner) {\n return [];\n }\n return scanner.scanSessions();\n }\n\n /**\n * 获取所有已注册的 agent 类型\n */\n listAgents(): AgentType[] {\n return Array.from(this.scanners.keys());\n }\n\n /**\n * 获取单例实例\n */\n static getInstance(): SessionScannerRegistry {\n if (!SessionScannerRegistry.instance) {\n SessionScannerRegistry.instance = new SessionScannerRegistry();\n }\n return SessionScannerRegistry.instance;\n }\n\n private static instance: SessionScannerRegistry | null = null;\n}","// src/adapters/agent/claude/scanner.ts\n\nimport { readdir, readFile } from 'fs/promises';\nimport { join, resolve } from 'path';\nimport type { SessionInfo } from '../../../core/adapter/types.js';\nimport type { SessionScanner } from '../../../core/session-scanner/types.js';\n\n/**\n * Claude Code Session Scanner\n * 扫描 ~/.claude/sessions/ 目录\n */\nexport class ClaudeSessionScanner implements SessionScanner {\n readonly agentType = 'claude' as const;\n private readonly sessionDir: string;\n\n constructor() {\n this.sessionDir = resolve(process.env.HOME || '', '.claude/sessions');\n }\n\n getSessionDir(): string {\n return this.sessionDir;\n }\n\n async scanSessions(): Promise<SessionInfo[]> {\n const sessions: SessionInfo[] = [];\n\n try {\n const files = await readdir(this.sessionDir);\n const jsonFiles = files.filter((f) => f.endsWith('.json'));\n\n for (const file of jsonFiles) {\n try {\n const filePath = join(this.sessionDir, file);\n const content = await readFile(filePath, 'utf-8');\n const meta = JSON.parse(content) as {\n pid?: number;\n sessionId?: string;\n cwd?: string;\n startedAt?: number;\n };\n\n if (!meta.sessionId) {\n continue;\n }\n\n const isActive = meta.pid ? await this.checkProcessAlive(meta.pid) : false;\n\n sessions.push({\n id: meta.sessionId,\n agentType: this.agentType,\n transportType: 'hook',\n status: isActive ? 'active' : 'archived',\n createdAt: meta.startedAt ?? Date.now(),\n updatedAt: meta.startedAt ?? Date.now(),\n cwd: meta.cwd,\n });\n } catch {\n // 忽略解析错误的文件\n }\n }\n } catch {\n // 目录不存在或无权限\n }\n\n return sessions;\n }\n\n private async checkProcessAlive(pid: number): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n process.kill(pid, 0);\n resolve(true);\n } catch {\n resolve(false);\n }\n });\n }\n}","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';\nimport { createInterface } from 'node:readline';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { Stream } from './stream.js';\nimport type {\n QueryOptions,\n QueryPrompt,\n SDKMessage,\n SDKControlResponse,\n CanUseToolControlRequest,\n CanUseToolControlResponse,\n ControlCancelRequest,\n PermissionResult,\n QuestionResult,\n} from './types.js';\nimport { AbortError } from './types.js';\nimport type { Writable } from 'node:stream';\n\nfunction getCleanEnv(): NodeJS.ProcessEnv {\n const env = { ...process.env };\n const cwd = process.cwd();\n const pathSep = process.platform === 'win32' ? ';' : ':';\n const pathKey = process.platform === 'win32' ? 'Path' : 'PATH';\n const actualPathKey = Object.keys(env).find((k) => k.toLowerCase() === 'path') || pathKey;\n if (env[actualPathKey]) {\n env[actualPathKey] = env[actualPathKey]!\n .split(pathSep)\n .filter((p) => {\n const normalizedP = p.replace(/\\\\/g, '/').toLowerCase();\n const normalizedCwd = cwd.replace(/\\\\/g, '/').toLowerCase();\n return !normalizedP.startsWith(normalizedCwd);\n })\n .join(pathSep);\n }\n return env;\n}\n\nexport function buildClaudeArgs(options: QueryOptions): string[] {\n const args = ['--output-format', 'stream-json', '--verbose'];\n if (options.customSystemPrompt) args.push('--system-prompt', options.customSystemPrompt);\n if (options.appendSystemPrompt) args.push('--append-system-prompt', options.appendSystemPrompt);\n if (options.maxTurns !== undefined) args.push('--max-turns', String(options.maxTurns));\n if (options.model) args.push('--model', options.model);\n if (options.canCallTool) {\n args.push('--permission-prompt-tool', 'stdio');\n }\n if (options.continue) args.push('--continue');\n if (options.resume) args.push('--resume', options.resume);\n if (options.allowedTools && options.allowedTools.length > 0) {\n args.push('--allowedTools', options.allowedTools.join(','));\n }\n if (options.disallowedTools && options.disallowedTools.length > 0) {\n args.push('--disallowedTools', options.disallowedTools.join(','));\n }\n if (options.mcpServers && Object.keys(options.mcpServers).length > 0) {\n args.push('--mcp-config', JSON.stringify({ mcpServers: options.mcpServers }));\n }\n if (options.strictMcpConfig) args.push('--strict-mcp-config');\n if (options.permissionMode) args.push('--permission-mode', options.permissionMode);\n if (options.settingsPath) args.push('--settings', options.settingsPath);\n if (options.bare) args.push('--bare');\n if (options.fallbackModel) {\n if (options.model && options.fallbackModel === options.model) {\n throw new Error('Fallback model cannot be the same as the main model. Please specify a different model for fallbackModel option.');\n }\n args.push('--fallback-model', options.fallbackModel);\n }\n return args;\n}\n\nclass Query implements AsyncIterableIterator<SDKMessage> {\n private pendingControlResponses = new Map<string, (response: SDKControlResponse['response']) => void>();\n private cancelControllers = new Map<string, AbortController>();\n private inputStream = new Stream<SDKMessage>();\n private sdkMessages: AsyncIterableIterator<SDKMessage>;\n private child?: ChildProcessWithoutNullStreams;\n\n constructor(\n private childStdin: Writable | null,\n private childStdout: NodeJS.ReadableStream,\n private processExitPromise: Promise<void>,\n private canCallTool?: (toolName: string, input: unknown, options: { signal: AbortSignal }) => Promise<PermissionResult>,\n private canAnswerQuestion?: (question: string, options: { signal: AbortSignal }) => Promise<QuestionResult>\n ) {\n this.readMessages();\n this.sdkMessages = this.readSdkMessages();\n }\n\n setChild(child: ChildProcessWithoutNullStreams): void {\n this.child = child;\n }\n\n kill(signal: NodeJS.Signals = 'SIGTERM'): void {\n if (this.child && !this.child.killed) {\n this.child.kill(signal);\n }\n }\n\n setError(error: Error): void {\n this.inputStream.error(error);\n }\n\n next(...args: [] | [undefined]): Promise<IteratorResult<SDKMessage>> {\n return this.sdkMessages.next(...args);\n }\n\n return(value?: any): Promise<IteratorResult<SDKMessage>> {\n if (this.sdkMessages.return) {\n return this.sdkMessages.return(value);\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n\n throw(e: any): Promise<IteratorResult<SDKMessage>> {\n if (this.sdkMessages.throw) {\n return this.sdkMessages.throw(e);\n }\n return Promise.reject(e);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<SDKMessage> {\n return this.sdkMessages;\n }\n\n private async readMessages(): Promise<void> {\n const rl = createInterface({ input: this.childStdout });\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const message = JSON.parse(line) as SDKMessage | SDKControlResponse;\n if (message.type === 'control_response') {\n const cr = message as SDKControlResponse;\n const handler = this.pendingControlResponses.get(cr.response.request_id);\n if (handler) handler(cr.response);\n continue;\n }\n if (message.type === 'control_request') {\n await this.handleControlRequest(message as unknown as CanUseToolControlRequest);\n continue;\n }\n if (message.type === 'control_cancel_request') {\n this.handleControlCancelRequest(message as unknown as ControlCancelRequest);\n continue;\n }\n this.inputStream.enqueue(message);\n } catch {\n // ignore non-JSON\n }\n }\n await this.processExitPromise;\n } catch (error) {\n this.inputStream.error(error as Error);\n } finally {\n this.inputStream.done();\n this.cleanupControllers();\n rl.close();\n }\n }\n\n private async *readSdkMessages(): AsyncIterableIterator<SDKMessage> {\n for await (const message of this.inputStream) {\n yield message;\n }\n }\n\n async interrupt(): Promise<void> {\n if (!this.childStdin) throw new Error('Interrupt requires --input-format stream-json');\n await this.request({ subtype: 'interrupt' }, this.childStdin);\n }\n\n private request(request: { subtype: string }, childStdin: Writable): Promise<SDKControlResponse['response']> {\n const requestId = Math.random().toString(36).substring(2, 15);\n const sdkRequest = {\n request_id: requestId,\n type: 'control_request',\n request,\n };\n return new Promise((resolve, reject) => {\n this.pendingControlResponses.set(requestId, (response) => {\n if (response.subtype === 'success') {\n resolve(response);\n } else {\n reject(new Error(response.error));\n }\n });\n childStdin.write(JSON.stringify(sdkRequest) + '\\n');\n });\n }\n\n private async handleControlRequest(request: CanUseToolControlRequest): Promise<void> {\n if (!this.childStdin) return;\n const controller = new AbortController();\n this.cancelControllers.set(request.request_id, controller);\n try {\n const response = await this.processControlRequest(request, controller.signal);\n const controlResponse: CanUseToolControlResponse = {\n type: 'control_response',\n response: {\n subtype: 'success',\n request_id: request.request_id,\n response,\n },\n };\n this.childStdin.write(JSON.stringify(controlResponse) + '\\n');\n } catch (error) {\n const controlErrorResponse: CanUseToolControlResponse = {\n type: 'control_response',\n response: {\n subtype: 'error',\n request_id: request.request_id,\n error: error instanceof Error ? error.message : String(error),\n },\n };\n this.childStdin.write(JSON.stringify(controlErrorResponse) + '\\n');\n } finally {\n this.cancelControllers.delete(request.request_id);\n }\n }\n\n private handleControlCancelRequest(request: ControlCancelRequest): void {\n const controller = this.cancelControllers.get(request.request_id);\n if (controller) {\n controller.abort();\n this.cancelControllers.delete(request.request_id);\n }\n }\n\n private async processControlRequest(request: CanUseToolControlRequest, signal: AbortSignal): Promise<PermissionResult | QuestionResult> {\n if (request.request.subtype === 'can_use_tool') {\n if (!this.canCallTool) {\n throw new Error('canCallTool callback is not provided.');\n }\n return this.canCallTool(request.request.tool_name, request.request.input, { signal });\n }\n if (request.request.subtype === 'can_answer_question') {\n if (!this.canAnswerQuestion) {\n throw new Error('canAnswerQuestion callback is not provided.');\n }\n const qReq = request as unknown as { request: { question: string } };\n return this.canAnswerQuestion(qReq.request.question, { signal });\n }\n throw new Error('Unsupported control request subtype: ' + request.request.subtype);\n }\n\n private cleanupControllers(): void {\n for (const [requestId, controller] of this.cancelControllers.entries()) {\n controller.abort();\n this.cancelControllers.delete(requestId);\n }\n }\n}\n\nexport function query(config: { prompt: QueryPrompt; options?: QueryOptions }): Query {\n const {\n prompt,\n options: {\n allowedTools = [],\n appendSystemPrompt,\n customSystemPrompt,\n cwd,\n disallowedTools = [],\n executable = 'node',\n executableArgs = [],\n maxTurns,\n mcpServers,\n pathToClaudeCodeExecutable = 'claude',\n permissionMode = 'default',\n continue: continueConversation,\n resume,\n model,\n fallbackModel,\n strictMcpConfig,\n canCallTool,\n canAnswerQuestion,\n settingsPath,\n env,\n abort,\n } = {},\n } = config;\n\n if (abort?.aborted) {\n throw new AbortError('Claude Code process aborted by user');\n }\n\n if (canCallTool && typeof prompt === 'string') {\n throw new Error('canCallTool callback requires --input-format stream-json. Please set prompt as an AsyncIterable.');\n }\n\n if (!process.env.CLAUDE_CODE_ENTRYPOINT) {\n process.env.CLAUDE_CODE_ENTRYPOINT = 'sdk-ts';\n }\n\n const args = buildClaudeArgs({\n allowedTools,\n appendSystemPrompt,\n customSystemPrompt,\n maxTurns,\n model,\n canCallTool,\n continue: continueConversation,\n resume,\n disallowedTools,\n mcpServers,\n strictMcpConfig,\n permissionMode,\n settingsPath,\n fallbackModel,\n });\n\n if (typeof prompt === 'string') {\n args.push('--print', prompt.trim());\n } else {\n args.push('--input-format', 'stream-json');\n }\n\n const isJsFile = pathToClaudeCodeExecutable.endsWith('.js') || pathToClaudeCodeExecutable.endsWith('.cjs');\n const isCommandOnly = pathToClaudeCodeExecutable === 'claude';\n if (!isCommandOnly && !existsSync(pathToClaudeCodeExecutable)) {\n throw new ReferenceError(`Claude Code executable not found at ${pathToClaudeCodeExecutable}`);\n }\n\n const spawnCommand = isJsFile ? executable : pathToClaudeCodeExecutable;\n const spawnArgs = isJsFile ? [...executableArgs, pathToClaudeCodeExecutable, ...args] : args;\n\n const spawnEnv = isCommandOnly ? { ...getCleanEnv(), ...env } : { ...process.env, ...env };\n\n const child = spawn(spawnCommand, spawnArgs, {\n cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n signal: abort,\n env: spawnEnv,\n shell: !isJsFile && process.platform === 'win32',\n windowsHide: true,\n }) as ChildProcessWithoutNullStreams;\n\n // Drain stderr to prevent buffer deadlock\n child.stderr.resume();\n\n let childStdin: Writable | null = null;\n if (typeof prompt === 'string') {\n child.stdin.end();\n } else {\n (async () => {\n try {\n for await (const msg of prompt) {\n if (abort?.aborted) break;\n const data = JSON.stringify(msg) + '\\n';\n if (!child.stdin.write(data)) {\n await new Promise<void>((resolve) => child.stdin.once('drain', resolve));\n }\n }\n } finally {\n child.stdin.end();\n }\n })();\n childStdin = child.stdin;\n }\n\n const cleanup = () => {\n if (!child.killed) child.kill('SIGTERM');\n };\n\n abort?.addEventListener('abort', cleanup);\n\n const processExitPromise = new Promise<void>((resolve) => {\n child.on('close', (code) => {\n if (abort?.aborted) {\n q.setError(new AbortError('Claude Code process aborted by user'));\n } else if (code !== 0 && code !== null) {\n q.setError(new Error(`Claude Code process exited with code ${code}`));\n } else {\n resolve();\n }\n });\n });\n\n const q = new Query(childStdin, child.stdout, processExitPromise, canCallTool, canAnswerQuestion);\n q.setChild(child);\n\n child.on('error', (error) => {\n if (abort?.aborted) {\n q.setError(new AbortError('Claude Code process aborted by user'));\n } else {\n q.setError(new Error(`Failed to spawn Claude Code process: ${error.message}`));\n }\n });\n\n processExitPromise.finally(() => {\n cleanup();\n abort?.removeEventListener('abort', cleanup);\n });\n\n return q;\n}\n","export class Stream<T> implements AsyncIterableIterator<T> {\n private queue: T[] = [];\n private readResolve?: (value: IteratorResult<T>) => void;\n private readReject?: (error: Error) => void;\n private isDone = false;\n private hasError?: Error;\n private started = false;\n\n constructor(private returned?: () => void) {}\n\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n if (this.started) {\n throw new Error('Stream can only be iterated once');\n }\n this.started = true;\n return this;\n }\n\n async next(): Promise<IteratorResult<T>> {\n if (this.queue.length > 0) {\n return Promise.resolve({ done: false, value: this.queue.shift()! });\n }\n if (this.isDone) {\n return Promise.resolve({ done: true, value: undefined });\n }\n if (this.hasError) {\n return Promise.reject(this.hasError);\n }\n return new Promise((resolve, reject) => {\n this.readResolve = resolve;\n this.readReject = reject;\n });\n }\n\n enqueue(value: T): void {\n if (this.isDone || this.hasError) return;\n if (this.readResolve) {\n const resolve = this.readResolve;\n this.readResolve = undefined;\n this.readReject = undefined;\n resolve({ done: false, value });\n } else {\n this.queue.push(value);\n }\n }\n\n done(): void {\n if (this.isDone || this.hasError) return;\n this.isDone = true;\n if (this.readResolve) {\n const resolve = this.readResolve;\n this.readResolve = undefined;\n this.readReject = undefined;\n resolve({ done: true, value: undefined });\n }\n }\n\n error(error: Error): void {\n if (this.isDone || this.hasError) return;\n this.hasError = error;\n if (this.readReject) {\n const reject = this.readReject;\n this.readResolve = undefined;\n this.readReject = undefined;\n reject(error);\n }\n }\n\n async return(): Promise<IteratorResult<T>> {\n this.isDone = true;\n if (this.returned) {\n this.returned();\n }\n return Promise.resolve({ done: true, value: undefined });\n }\n}\n","export interface SDKMessage {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface SDKUserMessage extends SDKMessage {\n type: 'user';\n parent_tool_use_id?: string;\n message: {\n role: 'user';\n content: string | Array<{\n type: string;\n text?: string;\n tool_use_id?: string;\n content?: unknown;\n [key: string]: unknown;\n }>;\n };\n}\n\nexport interface SDKAssistantMessage extends SDKMessage {\n type: 'assistant';\n parent_tool_use_id?: string;\n message: {\n role: 'assistant';\n content: Array<{\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n thinking?: string;\n [key: string]: unknown;\n }>;\n };\n}\n\nexport interface SDKSystemMessage extends SDKMessage {\n type: 'system';\n subtype: string;\n session_id?: string;\n model?: string;\n cwd?: string;\n tools?: string[];\n slash_commands?: string[];\n}\n\nexport interface SDKResultMessage extends SDKMessage {\n type: 'result';\n subtype: 'success' | 'error_max_turns' | 'error_during_execution';\n result?: string;\n num_turns: number;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n total_cost_usd: number;\n duration_ms: number;\n duration_api_ms: number;\n is_error: boolean;\n session_id: string;\n}\n\nexport interface SDKControlResponse extends SDKMessage {\n type: 'control_response';\n response: {\n request_id: string;\n subtype: 'success' | 'error';\n error?: string;\n };\n}\n\nexport interface SDKLog extends SDKMessage {\n type: 'log';\n log: {\n level: 'debug' | 'info' | 'warn' | 'error';\n message: string;\n };\n}\n\nexport interface ControlRequest {\n subtype: string;\n}\n\nexport interface CanUseToolRequest extends ControlRequest {\n subtype: 'can_use_tool';\n tool_name: string;\n input: unknown;\n}\n\nexport interface CanUseToolControlRequest {\n type: 'control_request';\n request_id: string;\n request: CanUseToolRequest;\n}\n\nexport interface CanAnswerQuestionRequest extends ControlRequest {\n subtype: 'can_answer_question';\n question: string;\n}\n\nexport interface CanAnswerQuestionControlRequest {\n type: 'control_request';\n request_id: string;\n request: CanAnswerQuestionRequest;\n}\n\nexport interface CanUseToolControlResponse {\n type: 'control_response';\n response: {\n subtype: 'success' | 'error';\n request_id: string;\n response?: PermissionResult | QuestionResult;\n error?: string;\n };\n}\n\nexport interface ControlCancelRequest {\n type: 'control_cancel_request';\n request_id: string;\n}\n\nexport interface SDKControlRequest {\n request_id: string;\n type: 'control_request';\n request: ControlRequest;\n}\n\n/**\n * Permission result returned to Claude SDK (Remote mode).\n * - behavior: 'allow' → Claude proceeds with tool execution\n * - behavior: 'deny' → Claude skips tool, optionally shows message\n */\nexport type PermissionResult =\n | { behavior: 'allow'; updatedInput: Record<string, unknown> }\n | { behavior: 'deny'; message: string };\n\n/**\n * Question result returned to Claude SDK (Remote mode).\n * - action: 'answer' → Claude receives the answer string\n * - action: 'deny' → Claude skips the question\n */\nexport type QuestionResult =\n | { action: 'answer'; answer: string }\n | { action: 'skip' }\n | { action: 'deny'; message?: string };\n\nexport interface CanCallToolCallback {\n (toolName: string, input: unknown, options: { signal: AbortSignal }): Promise<PermissionResult>;\n}\n\nexport interface CanAnswerQuestionCallback {\n (question: string, options: { signal: AbortSignal }): Promise<QuestionResult>;\n}\n\nexport interface QueryOptions {\n abort?: AbortSignal;\n allowedTools?: string[];\n appendSystemPrompt?: string;\n customSystemPrompt?: string;\n cwd?: string;\n disallowedTools?: string[];\n executable?: string;\n executableArgs?: string[];\n maxTurns?: number;\n mcpServers?: Record<string, unknown>;\n pathToClaudeCodeExecutable?: string;\n permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan';\n continue?: boolean;\n resume?: string;\n model?: string;\n fallbackModel?: string;\n strictMcpConfig?: boolean;\n canCallTool?: CanCallToolCallback;\n canAnswerQuestion?: CanAnswerQuestionCallback;\n settingsPath?: string;\n /** Disable hooks, LSP, plugin sync, etc. for cleaner remote mode */\n bare?: boolean;\n env?: Record<string, string | undefined>;\n}\n\nexport type QueryPrompt = string | AsyncIterable<SDKMessage>;\n\nexport class AbortError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'AbortError';\n }\n}\n","/** Claude Code hook event names */\nexport type ClaudeHookEventType =\n | 'SessionStart'\n | 'SessionEnd'\n | 'PreToolUse'\n | 'PermissionRequest'\n | 'PostToolUse'\n | 'PostToolUseFailure'\n | 'Stop';\n\n/** Valid Claude hook event types */\nconst VALID_CLAUDE_EVENTS: ClaudeHookEventType[] = [\n 'SessionStart',\n 'SessionEnd',\n 'PreToolUse',\n 'PermissionRequest',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'Stop',\n];\n\n/**\n * Check if a string is a valid Claude hook event type\n */\nexport function isClaudeHookEventType(eventType: string): eventType is ClaudeHookEventType {\n return VALID_CLAUDE_EVENTS.includes(eventType as ClaudeHookEventType);\n}\n","export { CodexAppAgentAdapter } from './CodexAppAgentAdapter.js';\nexport { CodexAppServerClient } from './codexAppServerClient.js';\nexport * from './codexAppServerTypes.js';\n","import { randomUUID } from 'crypto';\nimport { BaseAgentAdapter } from '../../../core/agent/BaseAgentAdapter.js';\nimport type { AgentBridgePort } from '../../../core/agent/AgentBridgePort.js';\nimport type { TransportState } from '../../../core/adapter/AgentAdapter.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { Logger } from 'pino';\nimport { EventNormalizer } from '../../../core/agent/EventNormalizer.js';\nimport type { InteractionRequest } from '../../../core/interaction/types.js';\nimport { CodexAppServerClient, type ApprovalHandler } from './codexAppServerClient.js';\nimport type { ApprovalPolicy, ReviewDecision } from './codexAppServerTypes.js';\nimport type { AgentCommand, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport type { MergedTool } from '../../../core/agent/TurnAggregator.js';\n\ninterface CodexTransportState extends TransportState {\n client: CodexAppServerClient;\n threadId: string;\n chatId: string;\n channel: string;\n cwd?: string;\n}\n\nexport class CodexAppAgentAdapter extends BaseAgentAdapter {\n readonly agentType = 'codex' as const;\n readonly transportType = 'stdio' as const;\n readonly version = '1.0.0';\n private token: string;\n private turnInProgress = new Set<string>();\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n private defaultWorkDir?: string;\n private defaultModel?: string;\n private defaultApprovalPolicy?: ApprovalPolicy;\n\n constructor(options: {\n bus: EventBus;\n logger: Logger;\n bridge: AgentBridgePort;\n token: string;\n command?: string[];\n cwd?: string;\n env?: Record<string, string>;\n defaultWorkDir?: string;\n defaultModel?: string;\n defaultApprovalPolicy?: ApprovalPolicy;\n }) {\n super(options);\n this.token = options.token;\n this.command = options.command?.length ? options.command : ['codex', 'app-server', '--listen', 'stdio://'];\n this.spawnCwd = options.cwd;\n this.envExtra = options.env ?? {};\n this.defaultWorkDir = options.defaultWorkDir;\n this.defaultModel = options.defaultModel;\n this.defaultApprovalPolicy = options.defaultApprovalPolicy;\n }\n\n async initialize(): Promise<void> {\n this.logger.info('Codex adapter initializing');\n try {\n const { execSync } = await import('child_process');\n execSync('codex --version', { encoding: 'utf8', windowsHide: true });\n this.logger.info('Codex CLI detected');\n } catch (err) {\n this.logger.warn('Codex CLI not found. Install with: npm install -g @openai/codex');\n throw err;\n }\n\n await super.initialize();\n }\n\n async createTransportState(opts: CreateSessionOptions): Promise<TransportState> {\n const sessionId = opts.sessionId ?? `codex-${randomUUID().slice(0, 8)}`;\n const chatId = opts.chatId ?? sessionId;\n const channel = opts.channel ?? 'broadcast';\n const cwd = opts.cwd || this.defaultWorkDir || process.cwd();\n this.logger.info({ sessionId, chatId, cwd, optsCwd: opts.cwd, defaultWorkDir: this.defaultWorkDir }, 'Creating Codex transport state');\n\n const client = new CodexAppServerClient({ logger: this.logger, command: this.command, cwd: this.spawnCwd, env: this.envExtra });\n await client.connect();\n\n const approvalPolicy = (opts.agentOptions?.approvalPolicy as ApprovalPolicy)\n ?? this.defaultApprovalPolicy\n ?? undefined;\n\n const { threadId } = await client.startThread({\n cwd,\n model: opts.model ?? this.defaultModel,\n approvalPolicy,\n });\n\n const state: CodexTransportState = {\n sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n client,\n threadId,\n chatId,\n channel,\n cwd,\n };\n\n client.setEventHandler((msg) => this.handleCodexEvent(msg, sessionId, state));\n client.setApprovalHandler((params) => this.handleApproval(params, sessionId));\n\n this.transports.set(sessionId, state);\n\n this.logger.info({ sessionId, threadId }, 'Codex transport state created');\n\n return state;\n }\n\n async closeTransportState(state: TransportState, reason = 'close'): Promise<void> {\n const codexState = state as CodexTransportState;\n try {\n await codexState.client.disconnect();\n } catch (err) {\n this.logger.warn({ sessionId: state.sessionId, error: err }, 'Error disconnecting Codex client during closeTransportState');\n }\n this.emitEvent(EventNormalizer.sessionEnd(state.sessionId, this.agentType, this.transportType, reason));\n this.transports.delete(state.sessionId);\n }\n\n async sendCommand(state: TransportState, command: AgentCommand): Promise<void> {\n const codexState = state as CodexTransportState;\n const { client, chatId, channel } = codexState;\n const sessionId = state.sessionId;\n\n this.logger.info({ sessionId, commandType: command.type }, 'Handling command');\n\n switch (command.type) {\n case 'user:message': {\n if (this.turnInProgress.has(sessionId)) {\n this.logger.warn({ sessionId }, 'Concurrent turn rejected');\n this.bus.publishOutbound({\n channel,\n chatId,\n text: 'Codex is still processing the previous message. Please wait.',\n });\n return;\n }\n this.turnInProgress.add(sessionId);\n this.emitEvent(EventNormalizer.turnStarted(sessionId, this.agentType, this.transportType));\n try {\n this.logger.debug({ sessionId, contentLength: command.content.length }, 'Sending turn to Codex');\n await client.sendTurnAndWait(command.content, {\n cwd: codexState.cwd ?? process.cwd(),\n });\n this.logger.info({ sessionId }, 'Turn completed');\n } finally {\n this.turnInProgress.delete(sessionId);\n }\n break;\n }\n case 'permission:response': {\n this.logger.warn('Manual permission:response via sendCommand not implemented for Codex v1');\n break;\n }\n case 'interrupt': {\n this.logger.info({ sessionId }, 'Interrupting turn');\n await client.interruptTurn();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n await this.closeTransportState(codexState);\n break;\n }\n }\n }\n\n private async handleCodexEvent(msg: { type: string } & Record<string, unknown>, sessionId: string, state: CodexTransportState): Promise<void> {\n const timestamp = new Date().toISOString();\n this.logger.info({ sessionId, eventType: msg.type }, 'Codex event received from client');\n\n switch (msg.type) {\n case 'agent_message': {\n const content = typeof msg.message === 'string' ? msg.message : '';\n this.logger.debug({ sessionId, contentPreview: content.slice(0, 80) }, 'Publishing agent_message');\n this.emitEvent(EventNormalizer.turnFinished(sessionId, this.agentType, this.transportType, {\n lastAssistantMessage: content,\n thinking: '',\n tools: [],\n }));\n break;\n }\n\n case 'exec_command_begin':\n case 'patch_apply_begin': {\n // Codex tool begin events are tracked internally; we emit on end\n break;\n }\n\n case 'exec_command_end':\n case 'patch_apply_end': {\n const toolName = msg.type === 'exec_command_end' ? 'codex_exec_command' : 'codex_patch_apply';\n this.logger.debug({ sessionId, toolName, eventType: msg.type }, 'Publishing tool:executed');\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, {\n toolCallId: `${sessionId}-${toolName}`,\n toolName,\n summary: `${toolName}: ${typeof msg.output === 'string' ? msg.output.slice(0, 100) : ''}`,\n toolInput: msg.command ? { command: msg.command } : msg.changes ? { changes: msg.changes } : {},\n output: typeof msg.output === 'string' ? msg.output : undefined,\n isTimeout: false,\n }));\n break;\n }\n\n case 'task_complete': {\n this.logger.info({ sessionId }, 'Task complete');\n // Note: session remains active for follow-up messages.\n // session:end is only emitted by closeTransportState (/clear, /stop, shutdown).\n break;\n }\n\n case 'turn_aborted': {\n const reason = (msg.reason as string | undefined) ?? 'aborted';\n this.logger.info({ sessionId, reason }, 'Turn aborted');\n // Note: session remains active for follow-up messages.\n break;\n }\n\n case 'tool:post':\n case 'tool:failure': {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Forwarding tool event');\n const toolCallId = typeof msg.toolCallId === 'string' ? msg.toolCallId : `${sessionId}-tool`;\n const toolName = typeof msg.toolName === 'string' ? msg.toolName : 'unknown';\n const tool: MergedTool = {\n toolCallId,\n toolName,\n summary: typeof msg.summary === 'string' ? msg.summary : `${toolName}: tool event`,\n toolInput: (msg.toolInput as Record<string, unknown>) || {},\n output: typeof msg.output === 'string' ? msg.output : undefined,\n isTimeout: false,\n };\n if (msg.type === 'tool:failure') {\n this.emitEvent(EventNormalizer.toolFailure(sessionId, this.agentType, this.transportType, tool, typeof msg.error === 'string' ? msg.error : undefined));\n } else {\n this.emitEvent(EventNormalizer.toolExecuted(sessionId, this.agentType, this.transportType, tool));\n }\n break;\n }\n\n default: {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Unhandled Codex event type');\n break;\n }\n }\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0], sessionId: string): Promise<ReviewDecision> {\n const state = this.transports.get(sessionId) as CodexTransportState | undefined;\n if (!state) {\n this.logger.warn({ sessionId, callId: params.callId }, 'Approval request but session not found, auto-denying');\n return 'denied';\n }\n\n const toolNameMap: Record<string, string> = {\n exec: 'codex_exec_command',\n patch: 'codex_patch_apply',\n mcp: 'codex_mcp_elicitation',\n };\n\n const toolName = toolNameMap[params.type] || params.type;\n this.logger.info({ sessionId, callId: params.callId, toolName }, 'Codex approval request');\n\n const interactionRequest: InteractionRequest = {\n requestId: params.callId,\n sessionId,\n type: 'permission',\n toolName,\n toolInput: params.command ? { command: params.command } :\n params.fileChanges ? { fileChanges: params.fileChanges } :\n params.input ? { input: params.input } : {},\n timestamp: Date.now(),\n };\n\n try {\n const response = await this.bridge.evaluateInteraction(interactionRequest);\n const decision: ReviewDecision = response.action === 'allow' ? 'approved' : 'denied';\n this.logger.info({ sessionId, callId: params.callId, toolName, decision }, 'Codex approval resolved');\n return decision;\n } catch (err) {\n this.logger.error({ error: err, sessionId, callId: params.callId }, 'Codex approval handler error');\n return 'denied';\n }\n }\n}\n","/**\n * Codex App Server Client — drives Codex via the v2 JSON-RPC protocol\n * (`codex app-server`), replacing the legacy MCP-based CodexMcpClient.\n *\n * Protocol: JSON-RPC 2.0 over stdio (newline-delimited JSON).\n * Adapted from happy project for handsoff.\n */\n\nimport { spawn, type ChildProcess, execFileSync } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport type {\n InitializeParams,\n NewConversationParams,\n NewConversationResponse,\n ResumeConversationParams,\n ResumeConversationResponse,\n InterruptConversationParams,\n ReviewDecision,\n EventMsg,\n JsonRpcRequest,\n JsonRpcResponse,\n ApprovalPolicy,\n SandboxMode,\n InputItem,\n ReasoningEffort,\n McpServerElicitationRequestResponse,\n} from './codexAppServerTypes.js';\n\ntype PendingRequest = {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n method: string;\n epoch: number;\n};\n\ntype LegacyPatchChanges = Record<string, Record<string, unknown>>;\n\nexport type ApprovalHandler = (params: {\n type: 'exec' | 'patch' | 'mcp';\n callId: string;\n command?: string[];\n cwd?: string;\n fileChanges?: Record<string, unknown>;\n reason?: string | null;\n toolName?: string;\n input?: unknown;\n serverName?: string;\n message?: string;\n}) => Promise<ReviewDecision>;\n\ntype LoggerLike = {\n debug: (msg: string, ...args: unknown[]) => void;\n info: (msg: string, ...args: unknown[]) => void;\n warn: (msg: string, ...args: unknown[]) => void;\n error: (msg: string, ...args: unknown[]) => void;\n};\n\nfunction isAppServerAvailable(command = 'codex'): boolean {\n try {\n execFileSync(command, ['--version'], { encoding: 'utf8', windowsHide: true });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalizeRawFileChangeList(changes: unknown): LegacyPatchChanges | undefined {\n if (!Array.isArray(changes)) {\n return undefined;\n }\n\n const normalized: LegacyPatchChanges = {};\n for (const change of changes) {\n if (!change || typeof change !== 'object' || Array.isArray(change)) {\n continue;\n }\n\n const path = typeof change.path === 'string' ? change.path : null;\n if (!path) {\n continue;\n }\n\n const entry: Record<string, unknown> = {};\n if (typeof change.diff === 'string') {\n entry.diff = change.diff;\n }\n if (change.kind && typeof change.kind === 'object' && !Array.isArray(change.kind)) {\n entry.kind = change.kind;\n }\n\n normalized[path] = entry;\n }\n\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\nexport class CodexAppServerClient {\n private process: ChildProcess | null = null;\n private readline: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private processEpoch = 0;\n private connected = false;\n private logger: LoggerLike | undefined;\n private command: string[];\n private spawnCwd?: string;\n private envExtra: Record<string, string>;\n\n // Session state\n private _threadId: string | null = null;\n private _turnId: string | null = null;\n private threadDefaults: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n } | null = null;\n\n // Turn completion tracking for the currently active sendTurnAndWait call.\n private pendingTurnCompletion: {\n resolve: (aborted: boolean) => void;\n started: boolean;\n turnId: string | null;\n } | null = null;\n\n // Tracks in-flight interruptTurn() RPCs so sendTurnAndWait can wait for them\n private pendingInterrupt: Promise<void> | null = null;\n private notificationProtocol: 'unknown' | 'legacy' | 'raw' = 'unknown';\n private completedTurnIds = new Set<string>();\n private rawFileChangesByItemId = new Map<string, LegacyPatchChanges>();\n\n // Handlers set by the consumer\n private eventHandler: ((msg: EventMsg) => void) | null = null;\n private approvalHandler: ApprovalHandler | null = null;\n\n constructor(options?: { logger?: LoggerLike; command?: string[]; cwd?: string; env?: Record<string, string> }) {\n this.logger = options?.logger;\n this.command = options?.command?.length ? options.command : ['codex', 'app-server', '--listen', 'stdio://'];\n this.spawnCwd = options?.cwd;\n this.envExtra = options?.env ?? {};\n }\n\n get threadId(): string | null {\n return this._threadId;\n }\n\n get turnId(): string | null {\n return this._turnId;\n }\n\n setEventHandler(handler: (msg: EventMsg) => void): void {\n this.eventHandler = handler;\n }\n\n setApprovalHandler(handler: ApprovalHandler): void {\n this.approvalHandler = handler;\n }\n\n private extractTurnId(params: any): string | null {\n const turnId = params?.turn?.id ?? params?.turnId ?? params?.turn_id ?? null;\n return typeof turnId === 'string' && turnId.length > 0 ? turnId : null;\n }\n\n private extractTurnStatus(params: any): string | null {\n const status = params?.turn?.status ?? params?.status ?? null;\n return typeof status === 'string' && status.length > 0 ? status : null;\n }\n\n private shouldHandleRawNotification(method: string): boolean {\n const isRawNotification = method === 'thread/started'\n || method === 'turn/started'\n || method === 'turn/completed'\n || method === 'thread/status/changed'\n || method === 'thread/tokenUsage/updated'\n || method.startsWith('item/');\n\n if (!isRawNotification) {\n return false;\n }\n\n if (this.notificationProtocol === 'legacy') {\n return false;\n }\n\n if (this.notificationProtocol === 'unknown') {\n this.notificationProtocol = 'raw';\n }\n\n return true;\n }\n\n private emitRawTurnCompletion(\n turnId: string | null,\n status: string | null,\n error: unknown,\n source: string,\n ): void {\n const aborted = status === 'cancelled' || status === 'canceled' || status === 'aborted' || status === 'interrupted';\n\n this.tryResolvePendingTurn(aborted, turnId, source);\n this._turnId = null;\n\n if (turnId && this.completedTurnIds.has(turnId)) {\n return;\n }\n if (turnId) {\n this.completedTurnIds.add(turnId);\n }\n\n if (aborted) {\n this.eventHandler?.({\n type: 'turn_aborted',\n ...(turnId ? { turn_id: turnId } : {}),\n ...(status ? { status } : {}),\n ...(error !== undefined && error !== null ? { error } : {}),\n });\n return;\n }\n\n this.eventHandler?.({\n type: 'task_complete',\n ...(turnId ? { turn_id: turnId } : {}),\n ...(status ? { status } : {}),\n ...(error !== undefined && error !== null ? { error } : {}),\n });\n }\n\n private handleRawNotification(method: string, params: any): boolean {\n if (!this.shouldHandleRawNotification(method)) {\n return false;\n }\n\n if (method === 'turn/started') {\n const turnId = this.extractTurnId(params);\n if (turnId) {\n this._turnId = turnId;\n }\n this.markPendingTurnStarted(turnId);\n this.eventHandler?.({\n type: 'task_started',\n ...(turnId ? { turn_id: turnId } : {}),\n });\n return true;\n }\n\n if (method === 'turn/completed') {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n this.extractTurnStatus(params),\n params?.turn?.error ?? params?.error,\n method,\n );\n return true;\n }\n\n if (method === 'thread/status/changed') {\n const statusType = params?.status?.type;\n if (statusType === 'idle' && this.pendingTurnCompletion?.started) {\n this.emitRawTurnCompletion(this._turnId, 'completed', null, method);\n }\n return true;\n }\n\n if (method === 'thread/tokenUsage/updated') {\n const tokenUsage = params?.tokenUsage;\n if (tokenUsage && typeof tokenUsage === 'object') {\n this.eventHandler?.({\n type: 'token_count',\n ...tokenUsage,\n });\n }\n return true;\n }\n\n const item = params?.item;\n if (!item || typeof item !== 'object') {\n return method.startsWith('item/');\n }\n\n if (method === 'item/started' && item.type === 'commandExecution') {\n const callId = typeof item.id === 'string' ? item.id : '';\n this.eventHandler?.({\n type: 'exec_command_begin',\n call_id: callId,\n callId,\n command: item.command,\n cwd: item.cwd,\n description: item.command,\n });\n return true;\n }\n\n if (method === 'item/completed' && item.type === 'commandExecution') {\n const callId = typeof item.id === 'string' ? item.id : '';\n this.eventHandler?.({\n type: 'exec_command_end',\n call_id: callId,\n callId,\n output: item.aggregatedOutput ?? '',\n exit_code: item.exitCode ?? null,\n duration_ms: item.durationMs ?? null,\n status: item.status,\n cwd: item.cwd,\n command: item.command,\n });\n return true;\n }\n\n if (item.type === 'fileChange') {\n const callId = typeof item.id === 'string' ? item.id : '';\n const changes = normalizeRawFileChangeList(item.changes);\n\n if (callId && changes) {\n this.rawFileChangesByItemId.set(callId, changes);\n }\n\n if (method === 'item/started') {\n this.eventHandler?.({\n type: 'patch_apply_begin',\n call_id: callId,\n callId,\n changes: changes ?? {},\n });\n return true;\n }\n\n if (method === 'item/completed') {\n this.eventHandler?.({\n type: 'patch_apply_end',\n call_id: callId,\n callId,\n status: item.status,\n });\n\n if (callId && (item.status === 'completed' || item.status === 'failed' || item.status === 'declined')) {\n this.rawFileChangesByItemId.delete(callId);\n }\n return true;\n }\n }\n\n if (method === 'item/completed' && item.type === 'agentMessage') {\n const text = typeof item.text === 'string' ? item.text : '';\n if (text.length > 0) {\n this.eventHandler?.({\n type: 'agent_message',\n message: text,\n item_id: item.id,\n phase: item.phase,\n });\n }\n\n if (item.phase === 'final_answer' && this.pendingTurnCompletion?.started) {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n 'completed',\n null,\n `${method}:final_answer`,\n );\n }\n return true;\n }\n\n return method.startsWith('item/');\n }\n\n // --- Lifecycle ---\n\n async connect(): Promise<void> {\n if (this.connected) return;\n\n const cmd = this.command[0];\n const args = this.command.slice(1);\n\n if (!isAppServerAvailable(cmd)) {\n throw new Error(\n 'Codex CLI is not installed\\n\\n' +\n 'Please install Codex CLI using:\\n npm install -g @openai/codex\\n'\n );\n }\n\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (typeof value === 'string') env[key] = value;\n }\n for (const [key, value] of Object.entries(this.envExtra)) {\n env[key] = value;\n }\n const filter = 'codex_core::rollout::list=off';\n if (!env.RUST_LOG) {\n env.RUST_LOG = filter;\n } else if (!env.RUST_LOG.includes('codex_core::rollout::list=')) {\n env.RUST_LOG += `,${filter}`;\n }\n\n this.logger?.debug(`Spawning: ${cmd} ${args.join(' ')}`);\n\n const epoch = ++this.processEpoch;\n const spawnOpts: import('node:child_process').SpawnOptions = {\n stdio: ['pipe', 'pipe', 'pipe'],\n env,\n windowsHide: true,\n };\n if (this.spawnCwd) {\n spawnOpts.cwd = this.spawnCwd;\n }\n const proc = spawn(cmd, args, spawnOpts);\n this.process = proc;\n\n proc.on('error', (err) => {\n this.logger?.debug('Process error:', err);\n });\n\n proc.on('exit', (code, signal) => {\n this.logger?.debug(`Process exited: code=${code} signal=${signal}`);\n if (this.process !== proc || this.processEpoch !== epoch) {\n this.logger?.debug('Ignoring stale process exit');\n return;\n }\n this.connected = false;\n for (const [id, req] of this.pending) {\n if (req.epoch !== epoch) continue;\n req.reject(new Error(`Codex process exited (code=${code}) while waiting for ${req.method}`));\n this.pending.delete(id);\n }\n this.resolvePendingTurn(true);\n });\n\n proc.stderr?.on('data', (chunk: Buffer) => {\n if (this.process !== proc || this.processEpoch !== epoch) return;\n const text = chunk.toString().trim();\n if (text) this.logger?.debug(`[CodexAppServer:stderr] ${text}`);\n });\n\n this.readline = createInterface({ input: proc.stdout! });\n this.readline.on('line', (line) => {\n if (this.process !== proc || this.processEpoch !== epoch) return;\n this.handleLine(line, epoch);\n });\n\n const initParams: InitializeParams = {\n clientInfo: {\n name: 'handsoff-codex',\n title: 'Handsoff Codex Client',\n version: '1.0.0',\n },\n capabilities: {\n experimentalApi: true,\n },\n };\n await this.request('initialize', initParams);\n this.notify('initialized');\n this.connected = true;\n this.logger?.debug('Connected and initialized');\n }\n\n private async disconnectInternal(opts?: { preserveThreadState?: boolean }): Promise<void> {\n if (!this.connected && !this.process) return;\n\n const proc = this.process;\n const pid = proc?.pid;\n const epoch = this.processEpoch;\n this.logger?.debug(`Disconnecting; pid=${pid ?? 'none'}`);\n\n this.readline?.close();\n this.readline = null;\n\n try {\n proc?.stdin?.end();\n proc?.kill('SIGTERM');\n } catch { /* ignore */ }\n\n if (pid) {\n const killTimer = setTimeout(() => {\n try {\n process.kill(pid, 0);\n process.kill(pid, 'SIGKILL');\n } catch { /* already dead */ }\n }, 2000);\n killTimer.unref();\n }\n\n this.process = null;\n this.connected = false;\n this._turnId = null;\n this.notificationProtocol = 'unknown';\n this.completedTurnIds.clear();\n if (!opts?.preserveThreadState) {\n this._threadId = null;\n this.threadDefaults = null;\n }\n\n for (const [id, req] of this.pending) {\n if (req.epoch !== epoch) continue;\n req.reject(new Error(`Codex process disconnected while waiting for ${req.method}`));\n this.pending.delete(id);\n }\n\n this.resolvePendingTurn(true);\n this.logger?.debug('Disconnected');\n }\n\n async disconnect(): Promise<void> {\n await this.disconnectInternal();\n }\n\n private buildThreadConfig(mcpServers?: Record<string, unknown>): Record<string, unknown> | null {\n return mcpServers ? { mcp_servers: mcpServers } : null;\n }\n\n private rememberThreadDefaults(opts: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): void {\n this.threadDefaults = {\n model: opts.model,\n cwd: opts.cwd,\n approvalPolicy: opts.approvalPolicy,\n sandbox: opts.sandbox,\n mcpServers: opts.mcpServers,\n };\n }\n\n // --- Thread management ---\n\n async startThread(opts: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): Promise<{ threadId: string; model: string }> {\n const params: NewConversationParams = {\n model: opts.model ?? null,\n modelProvider: null,\n profile: null,\n cwd: opts.cwd ?? process.cwd(),\n approvalPolicy: opts.approvalPolicy ?? null,\n sandbox: opts.sandbox ?? null,\n config: this.buildThreadConfig(opts.mcpServers),\n baseInstructions: null,\n developerInstructions: null,\n compactPrompt: null,\n includeApplyPatchTool: null,\n experimentalRawEvents: false,\n persistExtendedHistory: true,\n };\n\n const result = await this.request('thread/start', params) as NewConversationResponse;\n this._threadId = result.thread.id;\n this._turnId = null;\n this.rememberThreadDefaults(opts);\n this.logger?.debug(`Thread started: ${this._threadId}`);\n return { threadId: result.thread.id, model: result.model };\n }\n\n async resumeThread(opts?: {\n threadId?: string;\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n mcpServers?: Record<string, unknown>;\n }): Promise<{ threadId: string; model: string }> {\n const threadId = opts?.threadId ?? this._threadId;\n if (!threadId) {\n throw new Error('No thread available to resume.');\n }\n\n const defaults = this.threadDefaults ?? {};\n const params: ResumeConversationParams = {\n threadId,\n model: opts?.model ?? defaults.model ?? null,\n modelProvider: null,\n cwd: opts?.cwd ?? defaults.cwd ?? process.cwd(),\n approvalPolicy: opts?.approvalPolicy ?? defaults.approvalPolicy ?? null,\n sandbox: opts?.sandbox ?? defaults.sandbox ?? null,\n config: this.buildThreadConfig(opts?.mcpServers ?? defaults.mcpServers),\n baseInstructions: null,\n developerInstructions: null,\n persistExtendedHistory: true,\n };\n\n const result = await this.request('thread/resume', params) as ResumeConversationResponse;\n this._threadId = result.thread.id;\n this._turnId = null;\n this.rememberThreadDefaults({\n model: opts?.model ?? defaults.model,\n cwd: opts?.cwd ?? defaults.cwd,\n approvalPolicy: opts?.approvalPolicy ?? defaults.approvalPolicy,\n sandbox: opts?.sandbox ?? defaults.sandbox,\n mcpServers: opts?.mcpServers ?? defaults.mcpServers,\n });\n this.logger?.debug(`Thread resumed: ${this._threadId}`);\n return { threadId: result.thread.id, model: result.model };\n }\n\n async reconnectAndResumeThread(): Promise<boolean> {\n const threadId = this._threadId;\n await this.disconnectInternal({ preserveThreadState: !!threadId });\n await this.connect();\n\n if (!threadId) {\n return false;\n }\n\n try {\n await this.resumeThread({ threadId });\n return true;\n } catch (error) {\n this.logger?.warn('Failed to resume thread after reconnect', error);\n this._threadId = null;\n this.threadDefaults = null;\n return false;\n }\n }\n\n // --- Turn management ---\n\n private static readonly ABORT_GRACE_MS = 3_000;\n\n private hasPendingTurnCompletion(): boolean {\n return this.pendingTurnCompletion !== null;\n }\n\n private resolvePendingTurn(aborted: boolean): void {\n if (!this.pendingTurnCompletion) return;\n this.pendingTurnCompletion.resolve(aborted);\n this.pendingTurnCompletion = null;\n }\n\n private markPendingTurnStarted(turnId?: string | null): void {\n if (!this.pendingTurnCompletion) return;\n this.pendingTurnCompletion.started = true;\n if (turnId) {\n this.pendingTurnCompletion.turnId = turnId;\n }\n }\n\n private tryResolvePendingTurn(aborted: boolean, turnId: string | null, source: string): void {\n const pending = this.pendingTurnCompletion;\n if (!pending) return;\n\n if (!pending.started) {\n this.logger?.debug(`Ignoring ${source} before task_started`);\n return;\n }\n\n if (pending.turnId && turnId && pending.turnId !== turnId) {\n this.logger?.debug(\n `Ignoring ${source} for turn ${turnId}; awaiting ${pending.turnId}`,\n );\n return;\n }\n\n this.resolvePendingTurn(aborted);\n }\n\n private async waitForTurnCompletion(timeoutMs: number): Promise<boolean> {\n if (!this.hasPendingTurnCompletion()) {\n return true;\n }\n\n const deadline = Date.now() + Math.max(0, timeoutMs);\n while (this.hasPendingTurnCompletion()) {\n if (Date.now() >= deadline) {\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n return true;\n }\n\n async abortTurnWithFallback(opts?: {\n gracePeriodMs?: number;\n forceRestartOnTimeout?: boolean;\n }): Promise<{ hadActiveTurn: boolean; aborted: boolean; forcedRestart: boolean; resumedThread: boolean }> {\n const hadActiveTurn = this.hasPendingTurnCompletion();\n\n if (!hadActiveTurn) {\n return { hadActiveTurn: false, aborted: false, forcedRestart: false, resumedThread: false };\n }\n\n await this.interruptTurn();\n\n const gracePeriodMs = opts?.gracePeriodMs ?? CodexAppServerClient.ABORT_GRACE_MS;\n const settled = await this.waitForTurnCompletion(gracePeriodMs);\n if (settled) {\n return { hadActiveTurn: true, aborted: true, forcedRestart: false, resumedThread: false };\n }\n\n const shouldForceRestart = opts?.forceRestartOnTimeout ?? true;\n if (!shouldForceRestart) {\n return { hadActiveTurn: true, aborted: false, forcedRestart: false, resumedThread: false };\n }\n\n this.logger?.warn(`interrupt did not settle turn in ${gracePeriodMs}ms; force-restarting app-server`);\n const pendingTurnId = this.pendingTurnCompletion?.turnId ?? this._turnId;\n if (this.pendingTurnCompletion?.started) {\n this.eventHandler?.({\n type: 'turn_aborted',\n reason: 'interrupted',\n ...(pendingTurnId ? { turn_id: pendingTurnId } : {}),\n forced_restart: true,\n });\n }\n const resumedThread = await this.reconnectAndResumeThread();\n return { hadActiveTurn: true, aborted: true, forcedRestart: true, resumedThread };\n }\n\n async sendTurn(prompt: string, opts?: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n effort?: ReasoningEffort;\n }): Promise<void> {\n if (!this._threadId) {\n throw new Error('No active thread. Call startThread first.');\n }\n\n const input: InputItem[] = [\n { type: 'text', text: prompt },\n ];\n\n const params: Record<string, unknown> = {\n threadId: this._threadId,\n input,\n };\n if (opts?.cwd) params.cwd = opts.cwd;\n if (opts?.approvalPolicy) params.approvalPolicy = opts.approvalPolicy;\n if (opts?.model) params.model = opts.model;\n if (opts?.effort) params.effort = opts.effort;\n\n if (opts?.sandbox) {\n switch (opts.sandbox) {\n case 'workspace-write':\n params.sandboxPolicy = { type: 'workspaceWrite' };\n break;\n case 'danger-full-access':\n params.sandboxPolicy = { type: 'dangerFullAccess' };\n break;\n case 'read-only':\n params.sandboxPolicy = { type: 'readOnly' };\n break;\n }\n }\n\n const result = await this.request('turn/start', params) as { turn?: { id?: string | null } };\n const turnId = result?.turn?.id;\n if (typeof turnId === 'string' && turnId.length > 0) {\n this._turnId = turnId;\n if (this.pendingTurnCompletion) {\n this.pendingTurnCompletion.turnId = turnId;\n }\n }\n }\n\n private static readonly TURN_TIMEOUT_MS = 10 * 60 * 1000;\n\n async sendTurnAndWait(prompt: string, opts?: {\n model?: string;\n cwd?: string;\n approvalPolicy?: ApprovalPolicy;\n sandbox?: SandboxMode;\n effort?: ReasoningEffort;\n turnTimeoutMs?: number;\n }): Promise<{ aborted: boolean }> {\n if (this.pendingInterrupt) {\n await this.pendingInterrupt;\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n\n const timeoutMs = opts?.turnTimeoutMs ?? CodexAppServerClient.TURN_TIMEOUT_MS;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const completion = new Promise<boolean>((resolve) => {\n this.pendingTurnCompletion = {\n resolve,\n started: false,\n turnId: null,\n };\n\n timer = setTimeout(() => {\n if (this.pendingTurnCompletion) {\n this.logger?.warn(`Turn timed out after ${timeoutMs}ms — treating as abort`);\n this.resolvePendingTurn(true);\n }\n }, timeoutMs);\n });\n\n try {\n await this.sendTurn(prompt, opts);\n } catch (err) {\n if (timer) clearTimeout(timer);\n this.pendingTurnCompletion = null;\n throw err;\n }\n\n const aborted = await completion;\n if (timer) clearTimeout(timer);\n return { aborted };\n }\n\n async interruptTurn(): Promise<void> {\n if (!this._threadId) return;\n if (!this._turnId) {\n this.logger?.debug('interruptTurn: no active turnId, skipping');\n return;\n }\n const params: InterruptConversationParams = {\n threadId: this._threadId,\n turnId: this._turnId,\n };\n const doInterrupt = async () => {\n try {\n await this.request('turn/interrupt', params);\n } catch (err) {\n this.logger?.debug('interruptTurn error (may be expected):', err);\n } finally {\n this.pendingInterrupt = null;\n }\n };\n this.pendingInterrupt = doInterrupt();\n return this.pendingInterrupt;\n }\n\n hasActiveThread(): boolean {\n return this._threadId !== null;\n }\n\n // --- JSON-RPC transport ---\n\n private static readonly REQUEST_TIMEOUT_MS = 30_000;\n\n private request(method: string, params?: unknown, timeoutMs?: number): Promise<unknown> {\n const timeout = timeoutMs ?? CodexAppServerClient.REQUEST_TIMEOUT_MS;\n return new Promise((resolve, reject) => {\n if (!this.process?.stdin?.writable) {\n reject(new Error(`Cannot send ${method}: stdin not writable`));\n return;\n }\n const id = this.nextId++;\n\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`${method} timed out after ${timeout}ms (id=${id})`));\n }, timeout);\n\n this.pending.set(id, {\n resolve: (result) => { clearTimeout(timer); resolve(result); },\n reject: (err) => { clearTimeout(timer); reject(err); },\n method,\n epoch: this.processEpoch,\n });\n\n const msg: JsonRpcRequest = { jsonrpc: '2.0', id, method, params };\n const line = JSON.stringify(msg) + '\\n';\n this.logger?.debug(`-> ${method} (id=${id})`);\n this.process.stdin.write(line);\n });\n }\n\n private notify(method: string, params?: unknown): void {\n if (!this.process?.stdin?.writable) return;\n const msg: JsonRpcRequest = { jsonrpc: '2.0', method, params };\n this.process.stdin.write(JSON.stringify(msg) + '\\n');\n this.logger?.debug(`-> ${method} (notification)`);\n }\n\n private respond(id: number, result: unknown): void {\n if (!this.process?.stdin?.writable) return;\n const msg: JsonRpcResponse = { jsonrpc: '2.0', id, result };\n this.process.stdin.write(JSON.stringify(msg) + '\\n');\n this.logger?.debug(`-> response (id=${id})`);\n }\n\n private handleLine(line: string, sourceEpoch: number = this.processEpoch): void {\n if (sourceEpoch !== this.processEpoch) {\n return;\n }\n if (!line.trim()) return;\n\n let msg: any;\n try {\n msg = JSON.parse(line);\n } catch {\n this.logger?.debug('Non-JSON line:', line.substring(0, 200));\n return;\n }\n\n if (msg.id != null && (msg.result !== undefined || msg.error !== undefined)) {\n const pending = this.pending.get(msg.id);\n if (pending) {\n if (pending.epoch !== sourceEpoch) {\n this.logger?.debug(`Ignoring response from stale epoch for id=${msg.id}`);\n return;\n }\n this.pending.delete(msg.id);\n if (msg.error) {\n pending.reject(new Error(`${pending.method}: ${msg.error.message} (code=${msg.error.code})`));\n } else {\n pending.resolve(msg.result);\n }\n }\n return;\n }\n\n if (msg.id != null && msg.method) {\n this.handleServerRequest(msg.id, msg.method, msg.params).catch((err) => {\n this.logger?.debug('Error handling server request:', err);\n });\n return;\n }\n\n if (msg.method) {\n this.handleNotification(msg.method, msg.params);\n return;\n }\n\n this.logger?.debug('Unhandled message:', JSON.stringify(msg).substring(0, 300));\n }\n\n private mapDecisionToWire(decision: ReviewDecision, legacy: boolean): string | Record<string, unknown> {\n if (typeof decision === 'string') {\n if (legacy) {\n return decision;\n }\n switch (decision) {\n case 'approved': return 'accept';\n case 'approved_for_session': return 'acceptForSession';\n case 'denied': return 'decline';\n case 'abort': return 'cancel';\n default: return 'decline';\n }\n }\n if ('approved_execpolicy_amendment' in decision) {\n return decision;\n }\n return legacy ? 'denied' : 'decline';\n }\n\n private parseToolNameFromElicitationMessage(message: unknown): string | null {\n if (typeof message !== 'string') {\n return null;\n }\n const match = message.match(/tool \"([^\"]+)\"/i);\n return match?.[1] ?? null;\n }\n\n private mapDecisionToMcpElicitationResponse(\n decision: ReviewDecision,\n params: any,\n ): McpServerElicitationRequestResponse {\n if (typeof decision === 'string') {\n switch (decision) {\n case 'approved':\n case 'approved_for_session':\n return {\n action: 'accept',\n content: params?.mode === 'form' ? {} : null,\n _meta: null,\n };\n case 'abort':\n return {\n action: 'cancel',\n content: null,\n _meta: null,\n };\n case 'denied':\n default:\n return {\n action: 'decline',\n content: null,\n _meta: null,\n };\n }\n }\n\n return {\n action: 'decline',\n content: null,\n _meta: null,\n };\n }\n\n private async handleServerRequest(id: number, method: string, params: any): Promise<void> {\n if (method === 'mcpServer/elicitation/request') {\n const toolName = this.parseToolNameFromElicitationMessage(params?.message) ?? params?.serverName ?? 'McpTool';\n const decision = await this.handleApproval({\n type: 'mcp',\n callId: `${params?.serverName ?? 'mcp'}:${id}`,\n toolName,\n input: params?._meta?.tool_params ?? {},\n serverName: params?.serverName,\n message: params?.message,\n });\n this.respond(id, this.mapDecisionToMcpElicitationResponse(decision, params));\n return;\n }\n\n if (method === 'item/commandExecution/requestApproval' || method === 'execCommandApproval') {\n const legacy = method === 'execCommandApproval';\n const callId = params.itemId ?? params.callId ?? String(id);\n const decision = await this.handleApproval({\n type: 'exec',\n callId,\n command: params.command != null ? [params.command] : [],\n cwd: params.cwd,\n reason: params.reason,\n });\n this.respond(id, { decision: this.mapDecisionToWire(decision, legacy) });\n return;\n }\n\n if (method === 'item/fileChange/requestApproval' || method === 'applyPatchApproval') {\n const legacy = method === 'applyPatchApproval';\n const callId = params.itemId ?? params.callId ?? String(id);\n const decision = await this.handleApproval({\n type: 'patch',\n callId,\n fileChanges: params.fileChanges ?? (typeof callId === 'string'\n ? this.rawFileChangesByItemId.get(callId)\n : undefined),\n reason: params.reason,\n });\n this.respond(id, { decision: this.mapDecisionToWire(decision, legacy) });\n return;\n }\n\n this.logger?.debug(`Unknown server request: ${method}`);\n this.respond(id, {});\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0]): Promise<ReviewDecision> {\n if (this.approvalHandler) {\n try {\n return await this.approvalHandler(params);\n } catch (err) {\n this.logger?.debug('Approval handler error:', err);\n return 'denied';\n }\n }\n return 'denied';\n }\n\n private handleNotification(method: string, params: any): void {\n if (method === 'codex/event' || method.startsWith('codex/event/')) {\n this.notificationProtocol = 'legacy';\n const msg = params?.msg;\n if (msg) {\n if (msg.type === 'task_started' && msg.turn_id) {\n this._turnId = msg.turn_id;\n }\n if (msg.type === 'task_started') {\n this.markPendingTurnStarted(msg.turn_id ?? msg.turnId ?? null);\n }\n this.eventHandler?.(msg);\n if (msg.type === 'task_complete' || msg.type === 'turn_aborted') {\n const turnId = msg.turn_id ?? msg.turnId ?? null;\n if (turnId) {\n this.completedTurnIds.add(turnId);\n }\n this.tryResolvePendingTurn(\n msg.type === 'turn_aborted',\n turnId,\n `codex/event/${msg.type}`,\n );\n this._turnId = null;\n }\n }\n return;\n }\n\n if (this.handleRawNotification(method, params)) {\n return;\n }\n\n if (method === 'thread/started' || method === 'turn/started' ||\n method === 'turn/completed' || method === 'thread/status/changed') {\n if (method === 'turn/started') {\n const turnId = this.extractTurnId(params);\n if (turnId) {\n this._turnId = turnId;\n }\n this.markPendingTurnStarted(turnId);\n }\n if (method === 'turn/completed') {\n this.emitRawTurnCompletion(\n this.extractTurnId(params),\n this.extractTurnStatus(params),\n params?.turn?.error ?? params?.error,\n method,\n );\n }\n return;\n }\n\n this.logger?.debug(`Notification: ${method}`);\n }\n}\n","/**\n * Cherry-picked types from `codex app-server generate-ts` (Codex 0.107.0).\n * Only the essential types needed for our integration.\n */\n\nexport type ThreadId = string;\n\n// --- Initialize ---\n\nexport type InitializeParams = {\n clientInfo: { name: string; title: string | null; version: string };\n capabilities: { experimentalApi: boolean; optOutNotificationMethods?: string[] | null } | null;\n};\n\nexport type InitializeResponse = { userAgent: string };\n\n// --- Thread lifecycle ---\n\nexport type NewConversationParams = {\n model: string | null;\n modelProvider: string | null;\n profile: string | null;\n cwd: string | null;\n approvalPolicy: ApprovalPolicy | null;\n sandbox: SandboxMode | null;\n config: Record<string, unknown> | null;\n baseInstructions: string | null;\n developerInstructions: string | null;\n compactPrompt: string | null;\n includeApplyPatchTool: boolean | null;\n experimentalRawEvents: boolean;\n persistExtendedHistory: boolean;\n};\n\nexport type NewConversationResponse = {\n thread: {\n id: ThreadId;\n path: string;\n [key: string]: unknown;\n };\n model: string;\n modelProvider: string;\n cwd: string;\n approvalPolicy: ApprovalPolicy;\n sandbox: unknown;\n reasoningEffort: ReasoningEffort | null;\n};\n\nexport type ResumeConversationParams = {\n threadId: ThreadId;\n model: string | null;\n modelProvider: string | null;\n cwd: string | null;\n approvalPolicy: ApprovalPolicy | null;\n sandbox: SandboxMode | null;\n config: Record<string, unknown> | null;\n baseInstructions: string | null;\n developerInstructions: string | null;\n persistExtendedHistory: boolean;\n};\n\nexport type ResumeConversationResponse = NewConversationResponse;\n\n// --- Turn lifecycle ---\n\nexport type SendUserTurnParams = {\n threadId: ThreadId;\n input: InputItem[];\n cwd: string;\n approvalPolicy: ApprovalPolicy;\n sandboxPolicy: SandboxPolicy;\n model: string;\n effort: ReasoningEffort | null;\n summary: ReasoningSummary;\n outputSchema: unknown | null;\n};\n\nexport type InterruptConversationParams = {\n threadId: ThreadId;\n turnId: string;\n};\n\nexport type InterruptConversationResponse = {\n abortReason: TurnAbortReason;\n};\n\n// --- Approvals (server -> client requests) ---\n\nexport type ExecCommandApprovalParams = {\n conversationId: ThreadId;\n callId: string;\n approvalId: string | null;\n command: string[];\n cwd: string;\n reason: string | null;\n parsedCmd: unknown[];\n};\n\nexport type ApplyPatchApprovalParams = {\n conversationId: ThreadId;\n callId: string;\n fileChanges: Record<string, FileChange>;\n reason: string | null;\n grantRoot: string | null;\n};\n\nexport type ApprovalResponse = {\n decision: ReviewDecision;\n};\n\nexport type McpServerElicitationAction = \"accept\" | \"decline\" | \"cancel\";\n\nexport type McpServerElicitationRequestResponse = {\n action: McpServerElicitationAction;\n content: Record<string, unknown> | null;\n _meta: Record<string, unknown> | null;\n};\n\nexport type ReviewDecision =\n | \"approved\"\n | { approved_execpolicy_amendment: { proposed_execpolicy_amendment: string[] } }\n | \"approved_for_session\"\n | \"denied\"\n | \"abort\";\n\n// --- Shared enums ---\n\nexport type ApprovalPolicy = \"untrusted\" | \"on-failure\" | \"on-request\" | \"never\";\nexport type SandboxMode = \"read-only\" | \"workspace-write\" | \"danger-full-access\";\nexport type ReasoningEffort = \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\nexport type ReasoningSummary = \"auto\" | \"concise\" | \"detailed\" | \"none\";\nexport type TurnAbortReason = \"interrupted\" | \"replaced\" | \"review_ended\";\n\nexport type InputItem =\n | { type: \"text\"; text: string; text_elements?: unknown[] }\n | { type: \"image\"; url: string }\n | { type: \"localImage\"; path: string };\n\nexport type SandboxPolicy =\n | { type: \"dangerFullAccess\" }\n | { type: \"readOnly\" }\n | { type: \"externalSandbox\"; networkAccess: boolean }\n | {\n type: \"workspaceWrite\";\n writableRoots?: string[];\n networkAccess: boolean;\n excludeTmpdirEnvVar: boolean;\n excludeSlashTmp: boolean;\n };\n\nexport type FileChange =\n | { type: \"add\"; content: string }\n | { type: \"delete\"; content: string }\n | { type: \"update\"; unified_diff: string; move_path: string | null };\n\n// --- Events ---\n// Events arrive as `codex/event` notifications with `{ msg: EventMsg }`.\n// EventMsg uses the same type discriminators as the MCP server.\nexport type EventMsg = { type: string } & Record<string, unknown>;\n\n// --- JSON-RPC 2.0 wire types ---\n\nexport type JsonRpcRequest = {\n jsonrpc?: \"2.0\";\n id?: number;\n method: string;\n params?: unknown;\n};\n\nexport type JsonRpcResponse = {\n jsonrpc?: \"2.0\";\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n};\n","import { appendFile, mkdir, readdir, readFile } from 'fs/promises';\nimport { readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport interface SessionFile {\n sessionId: string;\n agentType: string;\n date: string;\n path: string;\n size: number;\n}\n\ninterface PersistedEvent {\n v: number;\n ts: string;\n [key: string]: unknown;\n}\n\nexport class Persistence {\n private baseDir: string;\n\n constructor(baseDir: string) {\n this.baseDir = baseDir;\n }\n\n /**\n * Write event to session's JSONL file (append-only)\n * File structure: {baseDir}/{YYYY-MM-DD}/{agentType}-{sessionId}.jsonl\n */\n async write(sessionId: string, agentType: string, event: unknown): Promise<void> {\n const date = new Date().toISOString().split('T')[0];\n const dateDir = join(this.baseDir, date);\n const filePath = join(dateDir, `${agentType}-${sessionId}.jsonl`);\n\n // Create date directory if it doesn't exist\n if (!existsSync(dateDir)) {\n await mkdir(dateDir, { recursive: true });\n }\n\n // Create the persisted event with version and timestamp\n const persistedEvent: PersistedEvent = {\n v: 1,\n ts: new Date().toISOString(),\n ...(event as Record<string, unknown>),\n };\n\n // Append to file with newline\n const line = JSON.stringify(persistedEvent) + '\\n';\n await appendFile(filePath, line, { flag: 'a' });\n }\n\n /**\n * Read all events for a session\n */\n async *read(sessionId: string): AsyncIterable<unknown> {\n // Find the session file by scanning date directories\n const entries = await readdir(this.baseDir, { withFileTypes: true });\n const dateDirs = entries.filter(e => e.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(e.name));\n\n for (const dateDir of dateDirs) {\n const dirPath = join(this.baseDir, dateDir.name);\n const files = await readdir(dirPath);\n\n // Find file matching sessionId\n const fileName = files.find(f => f.endsWith(`-${sessionId}.jsonl`));\n if (fileName) {\n const filePath = join(dirPath, fileName);\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.length > 0);\n\n for (const line of lines) {\n try {\n yield JSON.parse(line);\n } catch {\n // Skip invalid JSON lines\n continue;\n }\n }\n return; // Found and yielded all events, stop searching\n }\n }\n }\n\n /**\n * List all session files\n */\n list(): SessionFile[] {\n const sessions: SessionFile[] = [];\n\n if (!existsSync(this.baseDir)) {\n return sessions;\n }\n\n const entries = readdirSync(this.baseDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(entry.name)) {\n const date = entry.name;\n const dateDir = join(this.baseDir, date);\n const files = readdirSync(dateDir);\n\n for (const fileName of files) {\n if (fileName.endsWith('.jsonl')) {\n const filePath = join(dateDir, fileName);\n const stats = statSync(filePath);\n\n // Parse filename: {agentType}-{sessionId}.jsonl\n // agentType is the first part, sessionId is everything after the first dash\n const match = fileName.match(/^([^-]+)-(.+)\\.jsonl$/);\n if (match) {\n const [, agentType, sessionId] = match;\n sessions.push({\n sessionId,\n agentType,\n date,\n path: filePath,\n size: stats.size,\n });\n }\n }\n }\n }\n }\n\n return sessions;\n }\n}\n","import { createServer, IncomingMessage, Server, ServerResponse } from 'http';\nimport { URL } from 'url';\nimport { getLogger } from '../shared/logger.js';\nimport type { Gateway } from '../gateway/index.js';\nimport type { InteractionResponse } from '../core/interaction/types.js';\nimport { AgentAdapterRegistry } from '../core/adapter/AgentAdapterRegistry.js';\nimport { ClaudeHookAgentAdapter } from '../adapters/agent/claude/ClaudeHookAgentAdapter.js';\nimport { isClaudeHookEventType } from '../adapters/agent/claude/hook-types.js';\nimport type { AgentType } from '../core/adapter/types.js';\n\nexport type RequestHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;\nexport type UpgradeHandler = (request: IncomingMessage, socket: import('stream').Duplex, head: Buffer) => void;\n\ninterface Route {\n method: string;\n path: string | RegExp;\n handler: RequestHandler;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * HTTP Server for the Gateway\n */\nexport class HttpServer {\n private server: Server | null = null;\n private routes: Route[] = [];\n private upgradeHandlers = new Map<string, UpgradeHandler>();\n\n constructor(private port: number) {}\n\n /**\n * Register a route handler\n */\n registerRoute(method: string, path: string | RegExp, handler: RequestHandler): void {\n this.routes.push({ method: method.toUpperCase(), path, handler });\n logger.debug(`Registered route: ${method} ${path}`);\n }\n\n /**\n * Register a WebSocket upgrade handler for a specific path\n */\n onUpgrade(path: string, handler: UpgradeHandler): () => void {\n this.upgradeHandlers.set(path, handler);\n logger.debug(`Registered upgrade handler: ${path}`);\n return () => {\n this.upgradeHandlers.delete(path);\n logger.debug(`Unregistered upgrade handler: ${path}`);\n };\n }\n\n /**\n * Start the HTTP server\n */\n async start(): Promise<void> {\n this.server = createServer(this.handleRequest.bind(this));\n\n // Handle upgrade requests\n this.server.on('upgrade', (request, socket, head) => {\n const pathname = request.url\n ? new URL(request.url, `http://localhost:${this.port}`).pathname\n : '';\n\n const handler = this.upgradeHandlers.get(pathname);\n if (handler) {\n handler(request, socket, head);\n } else {\n socket.destroy();\n }\n });\n\n return new Promise((resolve, reject) => {\n this.server?.listen(this.port, () => {\n logger.info(`HTTP server listening on port ${this.port}`);\n resolve();\n });\n this.server?.on('error', reject);\n });\n }\n\n /**\n * Stop the HTTP server\n */\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.server?.close(() => {\n logger.info('HTTP server stopped');\n resolve();\n });\n });\n }\n\n /**\n * Get the underlying server instance\n */\n getServer(): Server | null {\n return this.server;\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n (async () => {\n const url = new URL(req.url || '/', `http://localhost:${this.port}`);\n const pathname = url.pathname;\n const method = (req.method || 'GET').toUpperCase();\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Find matching route\n const route = this.routes.find((r) => {\n if (r.method !== method) return false;\n if (typeof r.path === 'string') {\n return r.path === pathname;\n }\n return r.path.test(pathname);\n });\n\n if (route) {\n await route.handler(req, res);\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n })().catch((error) => {\n logger.error('Error handling HTTP request:', error);\n if (!res.headersSent) {\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n }\n}\n\n/**\n * Parse JSON body from incoming request\n */\nexport function parseJsonBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n try {\n if (!body) {\n resolve({});\n return;\n }\n resolve(JSON.parse(body));\n } catch (error) {\n reject(error);\n }\n });\n req.on('error', reject);\n });\n}\n\n/**\n * Send JSON response helper\n */\nexport function sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.writeHead(statusCode, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\n/**\n * Format hook response per Claude Code hook protocol.\n *\n * | EventType | Tool | Response Format |\n * |-----------|------|-----------------|\n * | PermissionRequest (non-AskUserQuestion) | any | hookSpecificOutput.decision |\n * | PreToolUse (AskUserQuestion) | AskUserQuestion | hookSpecificOutput.decision with updatedInput.answers |\n * | PreToolUse (other tool) | any | { accepted, message?, data? } |\n */\nfunction formatHookResponse(\n eventType: string,\n toolName: string,\n result: InteractionResponse\n): string {\n const isAskUserQuestion = toolName === 'AskUserQuestion';\n\n if (isAskUserQuestion) {\n // AskUserQuestion uses PermissionRequest format with updatedInput\n const questions = result._toolInput?.questions as Array<{\n question: string;\n header?: string;\n options?: Array<{ label: string; value?: unknown }>;\n }> | undefined;\n const question = questions?.[0];\n\n const selectedValueStr =\n result.selectedValues && result.selectedValues.length > 0\n ? result.selectedValues.map(String).join(', ')\n : undefined;\n const answerValue = result.customInput ?? selectedValueStr ?? '';\n\n const updatedInput: Record<string, unknown> = {\n ...result._toolInput,\n answers: question?.question\n ? { [question.question]: answerValue }\n : {},\n };\n\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: 'allow',\n updatedInput,\n },\n },\n });\n }\n\n if (eventType === 'PermissionRequest') {\n // PermissionRequest uses PermissionRequest format\n let updatedPermissions: unknown[] | undefined;\n if (result.permissionUpdates && result.permissionUpdates.length > 0) {\n updatedPermissions = result.permissionUpdates.map((rule) => ({\n type: rule.type,\n ...(rule.rules && { rules: rule.rules }),\n ...(rule.behavior && { behavior: rule.behavior }),\n destination: rule.destination ?? (result.permanent ? 'userSettings' : 'session'),\n ...(rule.mode && { mode: rule.mode }),\n ...(rule.directories && { directories: rule.directories }),\n }));\n }\n\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: result.action === 'select' ? 'allow' : result.action,\n ...(result.message !== undefined && { message: result.message }),\n ...(result.selectedValues !== undefined && {\n data: result.selectedValues.map(String).join(', '),\n }),\n ...(updatedPermissions !== undefined && { updatedPermissions }),\n },\n },\n });\n }\n\n // For PreToolUse and other hooks\n return JSON.stringify({\n accepted: ['allow', 'select', 'confirm'].includes(result.action),\n message: result.message,\n ...(result.selectedValues !== undefined && {\n data: result.selectedValues.map(String).join(', '),\n }),\n });\n}\n\n/**\n * Setup HTTP routes for the Gateway\n */\nexport function setupRoutes(\n httpServer: HttpServer,\n gateway: Gateway,\n getClientCount: () => number\n): void {\n // Health check\n httpServer.registerRoute('GET', '/health', (_req, res) => {\n sendJson(res, 200, { status: 'ok', version: VERSION });\n });\n\n // Status\n httpServer.registerRoute('GET', '/status', (_req, res) => {\n const sessions = gateway.listSessions();\n sendJson(res, 200, {\n running: true,\n sessions: sessions.map((s) => ({\n sessionId: s.id,\n agentType: s.agentType,\n status: s.status,\n startedAt: new Date(s.createdAt).toISOString(),\n updatedAt: new Date(s.updatedAt).toISOString(),\n })),\n clients: getClientCount(),\n });\n });\n\n // Register agent\n httpServer.registerRoute('POST', '/api/v1/agents', async (req, res) => {\n try {\n const body = await parseJsonBody(req);\n\n if (!body.agentType || typeof body.agentType !== 'string' || body.agentType.trim() === '') {\n sendJson(res, 400, { error: 'Missing or invalid agentType' });\n return;\n }\n\n const agentType = body.agentType.trim();\n const token = gateway.registerAgent(agentType);\n\n logger.info(`Registered agent: ${agentType} with token: ${token.substring(0, 8)}...`);\n\n sendJson(res, 201, {\n token,\n hooks: {\n endpoint: `/hook/${token}/{event}`,\n events: [\n 'SessionStart',\n 'SessionEnd',\n 'Stop',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'PreToolUse',\n 'PermissionRequest',\n 'SubagentStart',\n 'SubagentStop',\n 'UserPromptSubmit',\n ],\n },\n });\n } catch (error) {\n logger.error('Error registering agent:', error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n\n // List agents\n httpServer.registerRoute('GET', '/api/v1/agents', (_req, res) => {\n const registeredAgents = gateway.listRegisteredAgents();\n const sessions = gateway.listSessions({ includeEnded: true });\n const sessionCounts = new Map<string, number>();\n\n for (const session of sessions) {\n const token = session.token || 'unknown';\n sessionCounts.set(token, (sessionCounts.get(token) || 0) + 1);\n }\n\n const agents = registeredAgents.map(({ token, agentType }) => ({\n token,\n agentType,\n sessionCount: sessionCounts.get(token) || 0,\n }));\n\n sendJson(res, 200, { agents });\n });\n\n /**\n * Hook endpoint: /hook/{token}/{event}\n *\n * Claude Hook Protocol Contract:\n * - PreToolUse (non-AskUserQuestion): responds with { accepted: boolean }\n * - PreToolUse (AskUserQuestion): responds with hookSpecificOutput.decision.updatedInput.answers\n * - PermissionRequest: responds with hookSpecificOutput.decision.behavior\n * - Other events: responds with 202 { accepted: true }\n *\n * Supports both legacy format (/hook/{token}/Stop) and unified format (/hook/{token}/event).\n */\n httpServer.registerRoute('POST', /^\\/hook\\/[^/]+\\/(.+)$/, async (req, res) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const match = url.pathname.match(/^\\/hook\\/([^/]+)\\/(.+)$/);\n if (!match) {\n sendJson(res, 404, { error: 'Not found' });\n return;\n }\n\n const [, token, pathEventType] = match;\n const body = await parseJsonBody(req);\n\n // Support unified hook format: /hook/{token}/event\n // In unified format, event type is passed in body.hook_event_name\n const eventType = pathEventType === 'event' && body.hook_event_name\n ? String(body.hook_event_name)\n : pathEventType;\n\n if (!isClaudeHookEventType(eventType)) {\n sendJson(res, 202, { accepted: true, warning: 'Unknown event type' });\n return;\n }\n\n // DEBUG: Log the full token being used\n logger.debug({ token: token.substring(0, 8), fullToken: token, eventType }, 'Processing hook request');\n\n try {\n // Token validation / auto-registration\n let agentType = gateway.getAgentRegistry().getAgentType(token);\n if (!agentType) {\n logger.warn(`Auto-registering unknown token from hook request: ${token.substring(0, 8)}...`);\n agentType = 'claude';\n gateway.registerAgent(agentType, token);\n }\n\n logger.info({ eventType, token: token.substring(0, 8), body }, 'Hook payload received');\n\n // Get hook adapter for this agent type\n const adapter = AgentAdapterRegistry.getInstance()\n .get(agentType as AgentType, 'hook') as ClaudeHookAgentAdapter | undefined;\n\n if (!adapter) {\n logger.warn({ agentType, eventType }, 'Hook adapter not available');\n sendJson(res, 503, { error: 'Hook adapter not available' });\n return;\n }\n\n // Route to adapter\n if (eventType === 'PreToolUse' || eventType === 'PermissionRequest') {\n const requestId = typeof body.request_id === 'string'\n ? body.request_id\n : typeof body.session_id === 'string'\n ? body.session_id\n : `req-${Date.now()}`;\n const toolName = typeof body.tool_name === 'string' ? body.tool_name : 'unknown';\n\n // Permission hooks wait for user decision; timeout is managed by InteractionQueue\n const result = await adapter.processPermissionRequest(eventType, body, requestId);\n const responseBody = formatHookResponse(eventType, toolName, result);\n logger.info({ eventType, response: responseBody }, 'Sending hook response');\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(responseBody);\n } else {\n adapter.processHookEvent(eventType, body).catch((err) => {\n logger.warn({ eventType, error: err instanceof Error ? err.message : String(err) }, 'Hook event processing failed');\n });\n sendJson(res, 202, { accepted: true });\n }\n } catch (error) {\n logger.error(`Error processing hook for token ${token.substring(0, 8)}...:`, error);\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n}\n","import { WebSocketServer as WSWebSocketServer, WebSocket } from 'ws';\nimport { IncomingMessage } from 'http';\nimport { URL } from 'url';\nimport { getLogger } from '../shared/logger.js';\nimport type { HttpServer } from './http.js';\nimport type { Gateway } from '../gateway/index.js';\nimport type { EventFrame, ResponseFrame } from '../gateway/events.js';\nimport type { InteractionQueue } from '../adapters/interaction/index.js';\n\nexport interface Client {\n id: string;\n ws: WebSocket;\n isAlive: boolean;\n filters?: ClientFilters;\n}\n\nexport interface ClientFilters {\n agentTypes?: string[];\n sessionIds?: string[];\n}\n\nexport type MessageHandler = (clientId: string, message: WebSocketMessage) => void;\nexport type ConnectionHandler = (clientId: string) => void;\n\nexport interface WebSocketMessage {\n type: string;\n id?: string;\n requestId?: string;\n allow?: boolean;\n reason?: string;\n filters?: ClientFilters;\n [key: string]: unknown;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * WebSocket Server for the Gateway\n */\nexport class WebSocketServer {\n private wss: WSWebSocketServer | null = null;\n private clients = new Map<string, Client>();\n private messageHandlers: MessageHandler[] = [];\n private connectionHandlers: ConnectionHandler[] = [];\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private clientIdCounter = 0;\n\n constructor(\n private httpServer: HttpServer,\n private options: { heartbeatIntervalMs?: number; path?: string } = {}\n ) {}\n\n /**\n * Start the WebSocket server\n */\n async start(): Promise<void> {\n const httpSvr = this.httpServer.getServer();\n if (!httpSvr) {\n throw new Error('HTTP server must be started before WebSocket server');\n }\n\n this.wss = new WSWebSocketServer({ noServer: true });\n this.setupConnectionHandlers();\n this.startHeartbeat();\n\n // Register upgrade handler with HTTP server\n const path = this.options.path || '/ws';\n this.httpServer.onUpgrade(path, (request, socket, head) => {\n this.wss?.handleUpgrade(request, socket, head, (ws) => {\n this.wss?.emit('connection', ws, request);\n });\n });\n\n logger.info(`WebSocket server registered on path: ${path}`);\n }\n\n /**\n * Stop the WebSocket server\n */\n async stop(): Promise<void> {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n\n this.closeAll();\n\n return new Promise((resolve) => {\n this.wss?.close(() => {\n logger.info('WebSocket server stopped');\n resolve();\n });\n });\n }\n\n /**\n * Add a message handler\n */\n onMessage(handler: MessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Add a connection handler\n */\n onConnection(handler: ConnectionHandler): void {\n this.connectionHandlers.push(handler);\n }\n\n /**\n * Add a new client connection\n */\n add(ws: WebSocket, req?: IncomingMessage): string {\n const clientId = `client-${++this.clientIdCounter}`;\n const client: Client = {\n id: clientId,\n ws,\n isAlive: true,\n };\n this.clients.set(clientId, client);\n\n // Parse query parameters for pre-filters\n if (req?.url) {\n const url = new URL(req.url, 'http://localhost');\n const agentType = url.searchParams.get('agentType');\n const sessionId = url.searchParams.get('sessionId');\n\n if (agentType || sessionId) {\n client.filters = {\n agentTypes: agentType ? [agentType] : undefined,\n sessionIds: sessionId ? [sessionId] : undefined,\n };\n }\n }\n\n ws.on('pong', () => {\n client.isAlive = true;\n });\n\n ws.on('message', (data: Buffer) => {\n try {\n const message = JSON.parse(data.toString()) as WebSocketMessage;\n this.handleMessage(clientId, message);\n } catch (error) {\n logger.error('Invalid WebSocket message:', error);\n this.send(clientId, {\n type: 'res',\n id: 'error',\n error: { code: 400, message: 'Invalid JSON message' },\n });\n }\n });\n\n ws.on('close', () => {\n this.remove(clientId);\n });\n\n ws.on('error', (error) => {\n logger.error(`WebSocket error for client ${clientId}:`, error);\n this.remove(clientId);\n });\n\n logger.info(`WebSocket client connected: ${clientId}`);\n\n for (const handler of this.connectionHandlers) {\n try {\n handler(clientId);\n } catch (error) {\n logger.error('Error in connection handler:', error);\n }\n }\n\n return clientId;\n }\n\n /**\n * Remove a client connection\n */\n remove(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n this.clients.delete(clientId);\n logger.info(`WebSocket client disconnected: ${clientId}`);\n }\n }\n\n /**\n * Get a client by ID\n */\n get(clientId: string): Client | undefined {\n return this.clients.get(clientId);\n }\n\n /**\n * Get count of connected clients\n */\n getClientCount(): number {\n return this.clients.size;\n }\n\n /**\n * Send a message to a specific client\n */\n send(clientId: string, message: unknown): boolean {\n const client = this.clients.get(clientId);\n if (client && client.ws.readyState === WebSocket.OPEN) {\n client.ws.send(JSON.stringify(message));\n return true;\n }\n return false;\n }\n\n /**\n * Broadcast a message to all connected clients\n */\n broadcast(message: unknown, filter?: (client: Client) => boolean): void {\n const messageStr = JSON.stringify(message);\n for (const [, client] of this.clients) {\n if (client.ws.readyState === WebSocket.OPEN) {\n if (!filter || filter(client)) {\n client.ws.send(messageStr);\n }\n }\n }\n }\n\n /**\n * Close all client connections\n */\n closeAll(): void {\n for (const [, client] of this.clients) {\n client.ws.close();\n }\n this.clients.clear();\n }\n\n /**\n * Set client filters\n */\n setFilters(clientId: string, filters: ClientFilters): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = filters;\n }\n }\n\n /**\n * Clear client filters\n */\n clearFilters(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = undefined;\n }\n }\n\n private setupConnectionHandlers(): void {\n this.wss?.on('connection', (ws: WebSocket, req: IncomingMessage) => {\n this.add(ws, req);\n });\n }\n\n private handleMessage(clientId: string, message: WebSocketMessage): void {\n for (const handler of this.messageHandlers) {\n try {\n handler(clientId, message);\n } catch (error) {\n logger.error('Error in WebSocket message handler:', error);\n }\n }\n }\n\n private startHeartbeat(): void {\n const intervalMs = this.options.heartbeatIntervalMs || 30000;\n this.heartbeatInterval = setInterval(() => {\n for (const [, client] of this.clients) {\n if (!client.isAlive) {\n client.ws.terminate();\n this.remove(client.id);\n continue;\n }\n client.isAlive = false;\n client.ws.ping();\n }\n }, intervalMs);\n }\n}\n\nexport interface WebSocketSetupOptions {\n interactionQueue?: InteractionQueue;\n}\n\n/**\n * Setup WebSocket message handlers\n */\nexport function setupWebSocketHandlers(\n wsServer: WebSocketServer,\n gateway: Gateway,\n options: WebSocketSetupOptions = {}\n): void {\n const { interactionQueue } = options;\n // Send welcome message on new connection\n wsServer.onConnection((clientId) => {\n const welcomeFrame: ResponseFrame = {\n type: 'res',\n id: 'welcome',\n result: {\n message: 'Connected to Handsoff Gateway',\n version: VERSION,\n clientId,\n },\n };\n wsServer.send(clientId, welcomeFrame);\n });\n\n // Handle subscription messages\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'subscribe') {\n const filters = message.filters as { agentTypes?: string[]; sessionIds?: string[] } | undefined;\n wsServer.setFilters(clientId, filters || {});\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'subscribe',\n result: { subscribed: true },\n });\n } else if (message.type === 'unsubscribe') {\n wsServer.clearFilters(clientId);\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'unsubscribe',\n result: { unsubscribed: true },\n });\n }\n });\n\n // Handle list_sessions message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'list_sessions') {\n const sessions = gateway.listSessions();\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'list_sessions',\n result: {\n sessions: sessions.map((s) => ({\n id: s.id,\n agentType: s.agentType,\n status: s.status,\n startedAt: new Date(s.createdAt).toISOString(),\n updatedAt: new Date(s.updatedAt).toISOString(),\n })),\n },\n });\n }\n });\n\n // Handle unknown message types\n wsServer.onMessage((clientId, message) => {\n const knownTypes = ['subscribe', 'unsubscribe', 'list_sessions', 'welcome', 'permission_decision', 'list_pending_permissions'];\n if (!knownTypes.includes(message.type)) {\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'unknown',\n error: { code: 400, message: `Unknown message type: ${message.type}` },\n });\n }\n });\n\n // Handle permission_decision message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'permission_decision' && interactionQueue) {\n const { requestId, allow, reason } = message as {\n requestId: string;\n allow: boolean;\n reason?: string;\n };\n\n const success = interactionQueue.respond(requestId, {\n requestId,\n action: allow ? 'allow' : 'deny',\n message: reason,\n });\n\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'permission_decision',\n result: {\n success,\n message: success ? 'Decision recorded' : 'Request not found or already decided',\n },\n });\n }\n });\n\n // Handle list_pending_permissions message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'list_pending_permissions' && interactionQueue) {\n const pending = interactionQueue.listPending();\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'list_pending_permissions',\n result: { pending },\n });\n }\n });\n}\n\n/**\n * Broadcast event to WebSocket clients with filtering\n */\nexport function broadcastEvent(wsServer: WebSocketServer, frame: EventFrame): void {\n wsServer.broadcast(frame, (client) => {\n if (!client.filters) return true;\n\n const { agentTypes, sessionIds } = client.filters;\n const { agentType, sessionId } = frame.payload;\n\n if (agentTypes && agentTypes.length > 0 && !agentTypes.includes(agentType)) {\n return false;\n }\n\n if (sessionIds && sessionIds.length > 0 && !sessionIds.includes(sessionId)) {\n return false;\n }\n\n return true;\n });\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\n\nexport interface Credentials {\n version: string;\n hookToken: string;\n createdAt: string;\n}\n\nconst CREDENTIALS_VERSION = '1';\nconst DEFAULT_TOKEN_LENGTH = 8;\n\nfunction getCredentialsPath(): string {\n return join(homedir(), '.handsoff', 'credentials.json');\n}\n\nfunction generateToken(): string {\n return randomBytes(DEFAULT_TOKEN_LENGTH).toString('hex');\n}\n\nexport function loadCredentials(): Credentials | null {\n const path = getCredentialsPath();\n\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n console.error(`Failed to load credentials from ${path}:`, error);\n return null;\n }\n}\n\nexport function saveCredentials(credentials: Credentials): void {\n const path = getCredentialsPath();\n // Ensure directory exists before writing\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(credentials, null, 2), { mode: 0o600 });\n}\n\nexport function getOrCreateHookToken(): string {\n const existing = loadCredentials();\n\n if (existing?.hookToken) {\n return existing.hookToken;\n }\n\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n\nexport function getHookToken(): string | null {\n return loadCredentials()?.hookToken ?? null;\n}\n\nexport function resetCredentials(): string {\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n","export * from './types.js';\nexport * from './queue.js';\n","import type { InteractionResponse, PendingInteractionInfo } from '../../core/interaction/types.js';\n\nexport type { InteractionResponse };\nexport type { PendingInteractionInfo };\n\n/**\n * Result of queuing an interaction request\n */\nexport interface InteractionRequestResult {\n requestId: string;\n responsePromise: Promise<InteractionResponse>;\n}\n\n/**\n * Options for InteractionQueue\n */\nexport interface InteractionQueueOptions {\n timeoutMs?: number;\n defaultOnTimeout?: 'allow' | 'deny';\n}\n\n/**\n * Pending interaction in queue\n */\nexport interface PendingInteraction {\n requestId: string;\n sessionId: string;\n type: string;\n toolName: string;\n toolInput: Record<string, unknown>;\n timestamp: number;\n resolve: (response: InteractionResponse) => void;\n reject: (error: Error) => void;\n timeoutId: NodeJS.Timeout;\n}\n","import { randomUUID } from 'crypto';\nimport { getLogger } from '../../shared/logger.js';\nimport type {\n InteractionResponse,\n InteractionRequestResult,\n InteractionQueueOptions,\n PendingInteraction,\n PendingInteractionInfo,\n} from './types.js';\nimport type { InteractionRequest } from '../../core/interaction/types.js';\n\nexport class InteractionQueue {\n private pending = new Map<string, PendingInteraction>();\n private timeoutMs: number;\n private defaultOnTimeout: 'allow' | 'deny';\n\n constructor(options: InteractionQueueOptions = {}) {\n this.timeoutMs = options.timeoutMs ?? 300000; // 5 minutes\n this.defaultOnTimeout = options.defaultOnTimeout ?? 'deny';\n }\n\n request(request: InteractionRequest): InteractionRequestResult {\n const requestId = randomUUID();\n\n const responsePromise = new Promise<InteractionResponse>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pending.delete(requestId);\n getLogger().info(\n `[Interaction] Timeout: ${request.toolName} | requestId=${requestId} | default=${this.defaultOnTimeout}`\n );\n resolve({\n requestId,\n action: this.defaultOnTimeout,\n message: `Interaction request timed out after ${this.timeoutMs}ms`,\n });\n }, this.timeoutMs);\n\n const pending: PendingInteraction = {\n requestId,\n sessionId: request.sessionId,\n type: request.type,\n toolName: request.toolName,\n toolInput: request.toolInput,\n timestamp: request.timestamp,\n timeoutId,\n resolve: (response) => {\n clearTimeout(timeoutId);\n this.pending.delete(requestId);\n resolve(response);\n },\n reject: (error) => {\n clearTimeout(timeoutId);\n this.pending.delete(requestId);\n reject(error);\n },\n };\n\n this.pending.set(requestId, pending);\n });\n\n return { requestId, responsePromise };\n }\n\n respond(requestId: string, response: InteractionResponse): boolean {\n const pending = this.pending.get(requestId);\n if (!pending) {\n getLogger().warn(`[Interaction] Response failed: requestId=${requestId} not found`);\n return false;\n }\n\n const elapsed = Date.now() - pending.timestamp;\n const dataInfo = response.selectedValues?.length || response.customInput !== undefined\n ? ` | value=${response.selectedValues?.join(', ') ?? response.customInput}`\n : '';\n getLogger().info(\n `[Interaction] Response: ${pending.toolName} | requestId=${requestId} | action=${response.action}${dataInfo} | waited=${elapsed}ms`\n );\n\n // Include original toolInput in the response for formatting\n const fullResponse: InteractionResponse = {\n ...response,\n _toolInput: pending.toolInput,\n };\n\n pending.resolve(fullResponse);\n return true;\n }\n\n get(requestId: string): PendingInteraction | undefined {\n return this.pending.get(requestId);\n }\n\n listPending(): PendingInteractionInfo[] {\n const now = Date.now();\n return Array.from(this.pending.values()).map((p) => ({\n requestId: p.requestId,\n sessionId: p.sessionId,\n type: p.type as InteractionRequest['type'],\n toolName: p.toolName,\n elapsedMs: now - p.timestamp,\n }));\n }\n\n cancelAll(reason: string): void {\n const count = this.pending.size;\n if (count === 0) return;\n\n getLogger().info(`[Interaction] Cancel all: ${count} pending | reason=${reason}`);\n for (const [, pending] of this.pending) {\n pending.reject(new Error(`Cancelled: ${reason}`));\n }\n this.pending.clear();\n }\n\n cancelBySession(sessionId: string, reason: string): number {\n let count = 0;\n for (const [id, pending] of this.pending) {\n if (pending.sessionId === sessionId) {\n pending.reject(new Error(`Cancelled: ${reason}`));\n this.pending.delete(id);\n count++;\n }\n }\n if (count > 0) {\n getLogger().info(`[Interaction] Cancel session: ${count} pending | sessionId=${sessionId} | reason=${reason}`);\n }\n return count;\n }\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport dotenv from 'dotenv';\n// Note: Notification types removed - using EventBus architecture now\n\n// Load .env file if exists\ndotenv.config();\n\nexport interface GeneralConfig {\n log_level: string;\n hook_server_port: number;\n}\n\nexport interface TelegramConfig {\n enabled: boolean;\n bot_token: string;\n allowed_users: string[];\n notify_types?: string[];\n}\n\nexport interface FeishuConfig {\n enabled: boolean;\n app_id: string;\n app_secret: string;\n allowed_users?: string[];\n notify_types?: string[];\n}\n\nexport interface ClaudeAgentConfig {\n adapter?: 'hooks' | 'remote';\n binary: string;\n work_dir: string;\n model: string;\n permission_mode?: string;\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n}\n\nexport interface LoggerConfig {\n enabled: boolean;\n notify_types?: string[];\n}\n\nexport interface PermissionConfig {\n timeout_ms: number;\n default_on_timeout: 'allow' | 'deny';\n}\n\nexport interface ChannelConfig {\n logger?: LoggerConfig;\n telegram?: TelegramConfig;\n feishu?: FeishuConfig;\n permission?: PermissionConfig;\n app?: AppChannelConfig;\n}\n\nexport interface AppChannelConfig {\n enabled: boolean;\n channel_id: string;\n auth_token: string;\n heartbeat_interval_ms?: number;\n notify_types?: string[];\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig;\n codex?: CodexAgentConfig;\n}\n\nexport interface BindingsConfig {\n claude?: string; // \"channelType:channelInstanceId\" e.g. \"telegram:abc123\"\n codex?: string;\n}\n\nexport interface Config {\n general: GeneralConfig;\n channel: ChannelConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n log_level: 'info',\n hook_server_port: 9876,\n },\n channel: {\n logger: {\n enabled: true,\n },\n telegram: {\n enabled: true,\n bot_token: '',\n allowed_users: [],\n },\n feishu: {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [],\n notify_types: [],\n },\n permission: {\n timeout_ms: 300000, // 5 minutes\n default_on_timeout: 'deny',\n },\n app: {\n enabled: false,\n channel_id: '',\n auth_token: '',\n },\n },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n },\n },\n bindings: {},\n};\n\nfunction getConfigPath(): string {\n return join(homedir(), '.handsoff', 'config.toml');\n}\n\nfunction mergeWithDefaults(raw: any): Config {\n return {\n general: {\n ...DEFAULT_CONFIG.general,\n ...(raw.general || {}),\n hook_server_port: parseInt(\n process.env.HANDSOFF_HOOK_SERVER_PORT ||\n String(raw.general?.hook_server_port || DEFAULT_CONFIG.general.hook_server_port),\n 10\n ),\n },\n channel: {\n logger: {\n ...DEFAULT_CONFIG.channel.logger,\n ...(raw.channel?.logger || {}),\n notify_types: raw.channel?.logger?.notify_types,\n },\n telegram: {\n ...DEFAULT_CONFIG.channel.telegram,\n ...(raw.channel?.telegram || {}),\n allowed_users: (raw.channel?.telegram?.allowed_users || []).map(String),\n bot_token:\n process.env.HANDSOFF_TELEGRAM_BOT_TOKEN ||\n raw.channel?.telegram?.bot_token ||\n '',\n notify_types: raw.channel?.telegram?.notify_types,\n },\n feishu: {\n ...DEFAULT_CONFIG.channel.feishu,\n ...(raw.channel?.feishu || {}),\n allowed_users: raw.channel?.feishu?.allowed_users || [],\n app_id:\n process.env.HANDSOFF_FEISHU_APP_ID || raw.channel?.feishu?.app_id || '',\n app_secret:\n process.env.HANDSOFF_FEISHU_APP_SECRET ||\n raw.channel?.feishu?.app_secret ||\n '',\n notify_types: raw.channel?.feishu?.notify_types,\n },\n permission: {\n ...DEFAULT_CONFIG.channel.permission,\n ...(raw.channel?.permission || {}),\n // Support env var override\n timeout_ms: parseInt(\n process.env.HANDSOFF_PERMISSION_TIMEOUT_MS ||\n String(\n raw.channel?.permission?.timeout_ms ||\n DEFAULT_CONFIG.channel.permission!.timeout_ms\n ),\n 10\n ),\n default_on_timeout:\n (process.env.HANDSOFF_PERMISSION_DEFAULT as 'allow' | 'deny') ||\n raw.channel?.permission?.default_on_timeout ||\n DEFAULT_CONFIG.channel.permission!.default_on_timeout,\n },\n app: {\n ...DEFAULT_CONFIG.channel.app!,\n ...(raw.channel?.app || {}),\n enabled: raw.channel?.app?.enabled === true,\n channel_id: String(raw.channel?.app?.channel_id || ''),\n auth_token: String(raw.channel?.app?.auth_token || ''),\n heartbeat_interval_ms: raw.channel?.app?.heartbeat_interval_ms\n ? parseInt(String(raw.channel?.app?.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channel?.app?.notify_types)\n ? raw.channel.app.notify_types.map(String)\n : undefined,\n },\n },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n },\n codex: {\n ...DEFAULT_CONFIG.agent.codex!,\n ...(raw.agent?.codex || {}),\n command: raw.agent?.codex?.command\n ? raw.agent.codex.command\n : DEFAULT_CONFIG.agent.codex!.command,\n work_dir: raw.agent?.codex?.work_dir || DEFAULT_CONFIG.agent.codex!.work_dir,\n model: raw.agent?.codex?.model || DEFAULT_CONFIG.agent.codex!.model,\n approval_policy: raw.agent?.codex?.approval_policy || DEFAULT_CONFIG.agent.codex!.approval_policy,\n },\n },\n bindings: {\n ...DEFAULT_CONFIG.bindings,\n ...(raw.bindings || {}),\n },\n };\n}\n\nexport function loadConfig(): Config {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return DEFAULT_CONFIG;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const raw = TOML.parse(content) as any;\n return mergeWithDefaults(raw);\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return DEFAULT_CONFIG;\n }\n}\n","import EventEmitter from 'events';\nimport { getLogger } from '../../shared/logger.js';\nimport { BusEvent, EventHandler } from './types.js';\nimport {\n InboundMessage,\n OutboundMessage,\n InteractionRequestEvent,\n InteractionResponseEvent,\n CommandEvent,\n SessionStartEvent,\n SessionEndEvent,\n ToolPostEvent,\n ToolFailureEvent,\n TurnFinishedEvent,\n ToolExecutedEvent,\n TurnThinkingEvent,\n FinishedEvent,\n NotificationEvent,\n AllBusEvents,\n ProtocolEvent,\n} from './events.js';\n\n/**\n * 类型安全的事件总线\n * 支持 Inbound/Outbound 双向事件流\n */\nexport class EventBus {\n private emitter: EventEmitter;\n private logger: ReturnType<typeof getLogger>;\n\n constructor() {\n this.emitter = new EventEmitter();\n this.logger = getLogger();\n this.logger.debug('EventBus initialized');\n }\n\n /**\n * 通用事件发布\n */\n emit<T extends AllBusEvents>(event: T): void {\n this.emitter.emit(event.type, event);\n }\n\n /**\n * 通用事件订阅\n */\n on<T extends AllBusEvents>(\n eventType: T['type'],\n handler: EventHandler<T>\n ): () => void {\n this.emitter.on(eventType, handler);\n return () => {\n this.emitter.off(eventType, handler);\n };\n }\n\n /**\n * 发布入站消息\n */\n publishInbound(message: Omit<InboundMessage, 'type' | 'timestamp'>): void {\n const event: InboundMessage = {\n ...message,\n type: 'inbound:message',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅入站消息\n */\n onInbound(handler: EventHandler<InboundMessage>): () => void {\n return this.on('inbound:message', handler);\n }\n\n /**\n * 发布出站消息\n */\n publishOutbound(message: Omit<OutboundMessage, 'type' | 'timestamp'>): void {\n const event: OutboundMessage = {\n ...message,\n type: 'outbound:message',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅出站消息\n */\n onOutbound(handler: EventHandler<OutboundMessage>): () => void {\n return this.on('outbound:message', handler);\n }\n\n /**\n * @deprecated Use publishInteractionRequest instead\n * 发布权限申请事件 (backward compatibility - converts to interaction:request)\n */\n publishPermissionRequest(\n request: {\n requestId: string;\n sessionId: string;\n toolName: string;\n args: Record<string, unknown>;\n chatId: string;\n messageId: string;\n cwd?: string;\n }\n ): void {\n const event: InteractionRequestEvent = {\n requestId: request.requestId,\n sessionId: request.sessionId,\n interactionType: 'permission',\n content: {\n title: `Permission Required: ${request.toolName}`,\n description: `${request.toolName} ${JSON.stringify(request.args)}`,\n permission: {\n riskLevel: 'medium',\n args: request.args,\n },\n },\n chatId: request.chatId,\n messageId: request.messageId,\n cwd: request.cwd,\n type: 'interaction:request',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限申请事件\n * Now filters interaction:request events for permission type\n */\n onPermissionRequest(handler: EventHandler<InteractionRequestEvent>): () => void {\n return this.on('interaction:request', (event: InteractionRequestEvent) => {\n if (event.interactionType === 'permission') {\n handler(event);\n }\n });\n }\n\n /**\n * @deprecated Use publishInteractionResponse instead\n * 发布权限决策事件 (backward compatibility - converts to interaction:response)\n */\n publishPermissionDecision(\n decision: {\n requestId: string;\n decision: 'allow' | 'deny' | 'always_allow';\n reason?: string;\n }\n ): void {\n const event: InteractionResponseEvent = {\n requestId: decision.requestId,\n response: {\n requestId: decision.requestId,\n action: decision.decision === 'always_allow' ? 'allow' : decision.decision,\n message: decision.reason,\n },\n reason: decision.reason,\n type: 'interaction:response',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限决策事件\n * Now subscribes to interaction:response\n */\n onPermissionDecision(handler: EventHandler<InteractionResponseEvent>): () => void {\n return this.on('interaction:response', handler);\n }\n\n /**\n * Publish interaction request event\n */\n publishInteractionRequest(\n request: Omit<InteractionRequestEvent, 'type' | 'timestamp'>\n ): void {\n const event: InteractionRequestEvent = {\n ...request,\n type: 'interaction:request',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * Subscribe to interaction request events\n */\n onInteractionRequest(\n handler: EventHandler<InteractionRequestEvent>\n ): () => void {\n return this.on('interaction:request', handler);\n }\n\n /**\n * Publish interaction response event\n */\n publishInteractionResponse(\n response: Omit<InteractionResponseEvent, 'type' | 'timestamp'>\n ): void {\n const event: InteractionResponseEvent = {\n ...response,\n type: 'interaction:response',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * Subscribe to interaction response events\n */\n onInteractionResponse(\n handler: EventHandler<InteractionResponseEvent>\n ): () => void {\n return this.on('interaction:response', handler);\n }\n\n /**\n * 发布 Session 开始事件\n */\n publishSessionStart(\n session: Omit<SessionStartEvent, 'type' | 'timestamp'>\n ): void {\n const event: SessionStartEvent = {\n ...session,\n type: 'session:start',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅 Session 开始事件\n */\n onSessionStart(handler: EventHandler<SessionStartEvent>): () => void {\n return this.on('session:start', handler);\n }\n\n /**\n * 发布 Session 结束事件\n */\n publishSessionEnd(\n session: Omit<SessionEndEvent, 'type' | 'timestamp'>\n ): void {\n const event: SessionEndEvent = {\n ...session,\n type: 'session:end',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅 Session 结束事件\n */\n onSessionEnd(handler: EventHandler<SessionEndEvent>): () => void {\n return this.on('session:end', handler);\n }\n\n publishToolPost(tool: Omit<ToolPostEvent, 'type' | 'timestamp'>): void {\n const event: ToolPostEvent = { ...tool, type: 'tool:post', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolPost(handler: EventHandler<ToolPostEvent>): () => void {\n return this.on('tool:post', handler);\n }\n\n publishToolFailure(tool: Omit<ToolFailureEvent, 'type' | 'timestamp'>): void {\n const event: ToolFailureEvent = { ...tool, type: 'tool:failure', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolFailure(handler: EventHandler<ToolFailureEvent>): () => void {\n return this.on('tool:failure', handler);\n }\n\n publishToolExecuted(tool: Omit<ToolExecutedEvent, 'type' | 'timestamp'>): void {\n const event: ToolExecutedEvent = { ...tool, type: 'tool:executed', timestamp: new Date() };\n this.emit(event);\n }\n\n onToolExecuted(handler: EventHandler<ToolExecutedEvent>): () => void {\n return this.on('tool:executed', handler);\n }\n\n publishFinished(finished: Omit<FinishedEvent, 'type' | 'timestamp'>): void {\n const event: FinishedEvent = { ...finished, type: 'turn:finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onFinished(handler: EventHandler<FinishedEvent>): () => void {\n return this.on('turn:finished', handler);\n }\n\n publishTurnFinished(finished: Omit<TurnFinishedEvent, 'type' | 'timestamp'>): void {\n const event: TurnFinishedEvent = { ...finished, type: 'turn:finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onTurnFinished(handler: EventHandler<TurnFinishedEvent>): () => void {\n return this.on('turn:finished', handler);\n }\n\n publishTurnThinking(sessionId: string, thinking: string): void {\n // [Extension Point — Streaming Thinking]\n // Called once per turn with complete thinking (current), and once per chunk (streaming).\n // Consumers (NotificationHandler) treat both cases identically — no streaming logic needed here.\n // Streaming upgrade: call this more frequently with incremental content; no consumer changes required.\n const event: TurnThinkingEvent = { type: 'turn:thinking', sessionId, thinking, timestamp: new Date() };\n this.emit(event);\n }\n\n onTurnThinking(handler: EventHandler<TurnThinkingEvent>): () => void {\n return this.on('turn:thinking', handler);\n }\n\n /**\n * 发布命令事件\n */\n publishCommand(command: Omit<CommandEvent, 'type' | 'timestamp'>): void {\n const event: CommandEvent = {\n ...command,\n type: 'command',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅命令事件\n */\n onCommand(handler: EventHandler<CommandEvent>): () => void {\n return this.on('command', handler);\n }\n\n /**\n * 发布通知事件\n */\n publishNotification(\n notification: Omit<NotificationEvent, 'type' | 'timestamp'>\n ): void {\n const event: NotificationEvent = {\n ...notification,\n type: 'notification',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅通知事件\n */\n onNotification(handler: EventHandler<NotificationEvent>): () => void {\n return this.on('notification', handler);\n }\n\n /**\n * 移除所有监听器\n */\n removeAllListeners(): void {\n this.emitter.removeAllListeners();\n this.logger.debug('All event listeners removed');\n }\n\n /**\n * 获取监听器数量\n */\n listenerCount(eventType: AllBusEvents['type']): number {\n return this.emitter.listenerCount(eventType);\n }\n\n}\n\n/**\n * 创建 EventBus 实例\n */\nexport function createEventBus(): EventBus {\n return new EventBus();\n}\n\n// 导出所有类型\nexport * from './types.js';\nexport * from './events.js';\n","/**\n * 基础事件接口,所有事件必须实现\n */\nexport interface BusEvent {\n type: string;\n timestamp: Date;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * 事件处理器类型\n */\nexport type EventHandler<T extends BusEvent> = (event: T) => void | Promise<void>;\n\n/**\n * 按钮结构(用于内联键盘)\n */\nexport interface Button {\n text: string;\n data: string;\n}\n","import type { NotificationContext } from '../../gateway/notification-context.js';\nimport type { InteractionResponse } from '../interaction/types.js';\nimport { BusEvent, Button } from './types.js';\n\n/**\n * 从聊天平台收到的消息\n */\nexport interface InboundMessage extends BusEvent {\n type: 'inbound:message';\n /** 来源 channel 名称 */\n channel: string;\n /** 来源 channel 实例 ID,用于精确绑定路由 */\n channelInstanceId: string;\n chatId: string;\n messageId: string;\n text: string;\n sender: {\n id: string;\n username?: string;\n firstName?: string;\n lastName?: string;\n };\n /** 路由目标 agent,由 InboundRouter 自动填充 */\n targetAgent?: 'claude' | 'codex';\n /** 是否为显式 agent 指令(如 /codex help) */\n agentCommand?: boolean;\n /** 标记为系统命令已处理,不再路由 */\n systemCommand?: boolean;\n}\n\n/**\n * 发送到聊天平台的消息\n */\nexport interface OutboundMessage extends BusEvent {\n type: 'outbound:message';\n /** Channel 名称 (telegram, logger, feishu) 或 'broadcast' */\n channel: string;\n chatId: string;\n /** 格式化后的文本(向后兼容) */\n text?: string;\n /** 原始通知上下文,Channel 自行格式化 */\n context?: NotificationContext;\n replyToMessageId?: string;\n buttons?: Button[][];\n metadata?: Record<string, unknown>;\n}\n\n/**\n * 问题请求事件 (legacy, will be replaced by InteractionRequestEvent)\n */\nexport interface QuestionRequestEvent extends BusEvent {\n type: 'question:request';\n sessionId: string;\n requestId: string;\n question: string;\n options: Array<{\n label: string;\n value: unknown;\n description?: string;\n }>;\n multiSelect: boolean;\n chatId: string;\n messageId: string;\n header?: string;\n}\n\n/**\n * Unified Interaction Request Event\n * Replaces QuestionRequestEvent\n */\nexport interface InteractionRequestEvent extends BusEvent {\n type: 'interaction:request';\n requestId: string;\n sessionId: string;\n interactionType: 'permission' | 'question' | 'input' | 'confirm';\n content: {\n title: string;\n description?: string;\n permission?: {\n riskLevel: 'low' | 'medium' | 'high';\n args: Record<string, unknown>;\n };\n question?: {\n text: string;\n header?: string;\n options: Array<{\n id: string;\n label: string;\n value: unknown;\n description?: string;\n isCustom?: boolean;\n }>;\n allowCustomInput: boolean;\n multiSelect: boolean;\n };\n };\n chatId: string;\n messageId: string;\n cwd?: string;\n}\n\n/**\n * Unified Interaction Response Event\n */\nexport interface InteractionResponseEvent extends BusEvent {\n type: 'interaction:response';\n requestId: string;\n response: InteractionResponse;\n reason?: string;\n}\n\n/**\n * 命令事件\n */\nexport interface CommandEvent extends BusEvent {\n type: 'command';\n command: string;\n args: string[];\n chatId: string;\n messageId: string;\n sender: {\n id: string;\n username?: string;\n };\n}\n\n/**\n * Session 开始事件\n */\nexport interface SessionStartEvent extends BusEvent {\n type: 'session:start';\n sessionId: string;\n chatId?: string;\n userId: string;\n agentType?: 'claude' | 'codex';\n cwd?: string;\n}\n\n/**\n * Session 结束事件\n */\nexport interface SessionEndEvent extends BusEvent {\n type: 'session:end';\n sessionId: string;\n chatId?: string;\n userId: string;\n reason?: string;\n}\n\n/**\n * Tool 执行成功事件\n */\nexport interface ToolPostEvent extends BusEvent {\n type: 'tool:post';\n sessionId: string;\n toolCallId?: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n output?: string;\n}\n\n/**\n * Tool 执行失败事件\n */\nexport interface ToolFailureEvent extends BusEvent {\n type: 'tool:failure';\n sessionId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n error?: string;\n}\n\n/**\n * Turn finished event (one model response complete)\n * @deprecated Use TurnFinishedEvent instead\n */\nexport interface FinishedEvent extends BusEvent {\n type: 'turn:finished';\n sessionId: string;\n chatId: string;\n userId: string;\n reason?: string;\n lastAssistantMessage?: string;\n transcriptPath?: string;\n}\n\n/**\n * Turn thinking event (model is thinking)\n */\nexport interface TurnThinkingEvent extends BusEvent {\n type: 'turn:thinking';\n sessionId: string;\n thinking: string;\n}\n\n/**\n * Turn finished event (one model response complete)\n */\nexport interface TurnFinishedEvent extends BusEvent {\n type: 'turn:finished';\n sessionId: string;\n chatId: string;\n userId: string;\n agentType?: 'claude' | 'codex';\n cwd?: string;\n reason?: string;\n lastAssistantMessage?: string;\n thinking?: string;\n durationMs?: number;\n usage?: {\n inputTokens: number;\n outputTokens: number;\n };\n}\n\n/**\n * Tool executed event (tool call completed)\n */\nexport interface ToolExecutedEvent extends BusEvent {\n type: 'tool:executed';\n sessionId: string;\n toolCallId: string;\n toolName: string;\n summary: string;\n toolInput: unknown;\n output?: string;\n isTimeout: boolean;\n}\n\n/**\n * 通知事件\n */\nexport interface NotificationEvent extends BusEvent {\n type: 'notification';\n level: 'info' | 'warn' | 'error' | 'success';\n title: string;\n message: string;\n chatId?: string;\n}\n\n/**\n * Agent Event (Protocol Event)\n */\nexport interface ProtocolEvent extends BusEvent {\n type: 'agent:event';\n event: unknown;\n}\n\n/**\n * AgentEvent ACK Event\n */\nexport interface AgentEventACKEvent extends BusEvent {\n type: 'agent:ack';\n originalId: string;\n status: 'received' | 'processing' | 'completed' | 'failed';\n result?: unknown;\n}\n\n/**\n * 所有 Handsoff 事件的联合类型\n */\nexport type AllBusEvents =\n | InboundMessage\n | OutboundMessage\n | InteractionRequestEvent\n | InteractionResponseEvent\n | QuestionRequestEvent\n | CommandEvent\n | SessionStartEvent\n | SessionEndEvent\n | ToolPostEvent\n | ToolFailureEvent\n | TurnThinkingEvent\n | TurnFinishedEvent\n | ToolExecutedEvent\n | FinishedEvent\n | NotificationEvent\n | ProtocolEvent;\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { OutboundMessage } from '../bus/events.js';\nimport type { Button } from '../bus/types.js';\nimport type { Channel, ChannelConfig, ConnectionHealth } from './types.js';\nimport { ChannelRegistry } from './registry.js';\nimport { getLogger, createChannelLogger } from '../../shared/logger.js';\n\n/**\n * Channels 配置映射\n */\nexport interface ChannelsConfig {\n [channelName: string]: ChannelConfig;\n}\n\n/**\n * Channel 状态信息\n */\nexport interface ChannelStatus {\n name: string;\n displayName: string;\n isRunning: boolean;\n capabilities: {\n supportsButtons: boolean;\n supportsMarkdown: boolean;\n supportsImages: boolean;\n supportsStreaming: boolean;\n };\n}\n\n/**\n * Channel 连接状态信息\n */\nexport interface ChannelConnectionStatus {\n name: string;\n displayName: string;\n isRunning: boolean;\n connectionState: ConnectionHealth['state'];\n lastPingTime?: Date;\n reconnectCount: number;\n errorMessage?: string;\n}\n\n/**\n * ChannelManager\n * 统一管理所有 Channel 的生命周期和消息路由\n */\nexport class ChannelManager {\n /** EventBus 实例 */\n private bus: EventBus;\n\n /** 日志记录器 */\n private logger: Logger;\n\n /** 已创建的 Channel 实例映射 */\n private channels: Map<string, Channel> = new Map();\n\n /** 出站消息处理器取消函数 */\n private unsubscribeOutbound: (() => void) | null = null;\n\n /** 健康检查定时器 */\n private healthCheckTimer: NodeJS.Timeout | null = null;\n\n /** 健康检查间隔(毫秒) */\n private readonly HEALTH_CHECK_INTERVAL = 30000; // 30秒\n\n /**\n * 构造函数\n * @param bus - EventBus 实例\n * @param logger - 可选的日志记录器\n */\n constructor(bus: EventBus, logger?: Logger) {\n this.bus = bus;\n this.logger = logger || getLogger();\n this.logger.debug('ChannelManager initialized');\n }\n\n /**\n * 从配置初始化所有启用的 Channel\n * @param channelsConfig - Channel 配置映射\n */\n initializeFromConfig(channelsConfig: ChannelsConfig): void {\n const registry = ChannelRegistry.getInstance();\n\n for (const [name, config] of Object.entries(channelsConfig)) {\n if (!config.enabled) {\n this.logger.debug({ channel: name }, '[Channel] Disabled, skipping');\n continue;\n }\n\n const ChannelClass = registry.get(name);\n if (!ChannelClass) {\n this.logger.warn(\n { channel: name },\n '[Channel] Class not found in registry'\n );\n continue;\n }\n\n try {\n const channelLogger = createChannelLogger(name);\n const channel = new ChannelClass(config, this.bus, channelLogger);\n this.channels.set(name, channel);\n this.logger.info({ channel: name }, '[Channel] Initialized');\n } catch (error) {\n this.logger.error(\n { channel: name, error },\n 'Failed to initialize channel'\n );\n }\n }\n }\n\n /**\n * 启动所有 Channel(带重试机制)\n */\n async startAll(): Promise<void> {\n this.logger.info(\n { count: this.channels.size },\n '[Channel] Starting all'\n );\n\n // 启动所有 Channel\n for (const [name, channel] of this.channels) {\n await this.startChannelWithRetry(name, channel);\n }\n\n // 设置出站消息路由\n this.setupOutboundRouting();\n\n // 启动健康检查\n this.startHealthCheck();\n\n this.logger.info('[Channel] All started');\n }\n\n /**\n * 启动单个 Channel(带重试)\n */\n private async startChannelWithRetry(\n name: string,\n channel: Channel,\n maxRetries = 3\n ): Promise<void> {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n await channel.start();\n this.logger.debug({ channel: name }, '[Channel] Started');\n return;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(\n { channel: name, attempt, error: errorMessage },\n '[Channel] Start failed'\n );\n\n if (attempt === maxRetries) {\n this.logger.error({ channel: name }, '[Channel] Start failed after retries');\n return;\n }\n\n // 指数退避重试\n const delay = 1000 * Math.pow(2, attempt - 1);\n this.logger.debug({ channel: name, delay }, '[Channel] Retrying');\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n /**\n * 停止所有 Channel(优雅关闭)\n */\n async stopAll(): Promise<void> {\n this.logger.info(\n { count: this.channels.size },\n '[Channel] Stopping all'\n );\n\n // 停止健康检查\n this.stopHealthCheck();\n\n // 取消出站消息监听\n if (this.unsubscribeOutbound) {\n this.unsubscribeOutbound();\n this.unsubscribeOutbound = null;\n this.logger.debug('[Channel] Outbound routing stopped');\n }\n\n // 优雅关闭所有 Channel(带超时)\n const stopPromises = Array.from(this.channels.entries()).map(\n async ([name, channel]) => {\n try {\n // 5秒超时\n await Promise.race([\n channel.stop(),\n new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Stop timeout')), 5000)\n ),\n ]);\n this.logger.debug({ channel: name }, '[Channel] Stopped');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ channel: name, error: errorMessage }, '[Channel] Stop failed');\n }\n }\n );\n\n await Promise.all(stopPromises);\n this.logger.info('[Channel] All stopped');\n }\n\n /**\n * 启动健康检查定时器\n */\n private startHealthCheck(): void {\n this.healthCheckTimer = setInterval(() => {\n this.performHealthCheck();\n }, this.HEALTH_CHECK_INTERVAL);\n this.logger.debug('Health check started');\n }\n\n /**\n * 停止健康检查定时器\n */\n private stopHealthCheck(): void {\n if (this.healthCheckTimer) {\n clearInterval(this.healthCheckTimer);\n this.healthCheckTimer = null;\n this.logger.debug('Health check stopped');\n }\n }\n\n /**\n * 执行健康检查\n */\n private performHealthCheck(): void {\n for (const [name, channel] of this.channels) {\n const health = channel.getConnectionHealth?.();\n if (health) {\n this.logger.debug(\n { channel: name, state: health.state, reconnectCount: health.reconnectCount },\n 'Health check'\n );\n\n // 告警:重连次数过多\n if (health.state === 'error' && health.reconnectCount > 5) {\n this.logger.warn(\n { channel: name, reconnectCount: health.reconnectCount },\n 'Channel connection unstable'\n );\n }\n }\n }\n }\n\n /**\n * 注册一个已初始化的 Channel\n * @param channel - Channel 实例\n */\n register(channel: Channel): void {\n const name = channel.name;\n if (this.channels.has(name)) {\n this.logger.warn({ channel: name }, '[Channel] Already registered, replacing');\n }\n this.channels.set(name, channel);\n this.logger.info({ channel: name }, '[Channel] Registered');\n }\n\n /**\n * 获取指定 Channel\n * @param name - Channel 名称\n * @returns Channel 实例,如果不存在则返回 undefined\n */\n getChannel(name: string): Channel | undefined {\n return this.channels.get(name);\n }\n\n /**\n * 获取所有 Channel 状态\n * @returns Channel 状态数组\n */\n getStatus(): ChannelStatus[] {\n const status: ChannelStatus[] = [];\n\n for (const channel of this.channels.values()) {\n status.push({\n name: channel.name,\n displayName: channel.displayName,\n isRunning: channel.isRunning,\n capabilities: {\n supportsButtons: channel.capabilities.supportsButtons,\n supportsMarkdown: channel.capabilities.supportsMarkdown,\n supportsImages: channel.capabilities.supportsImages,\n supportsStreaming: channel.capabilities.supportsStreaming,\n },\n });\n }\n\n return status;\n }\n\n /**\n * 获取所有 Channel 的连接状态\n */\n getConnectionStatus(): ChannelConnectionStatus[] {\n const status: ChannelConnectionStatus[] = [];\n\n for (const [name, channel] of this.channels) {\n const health = channel.getConnectionHealth?.() || {\n state: 'unknown' as const,\n reconnectCount: 0,\n };\n\n status.push({\n name: channel.name,\n displayName: channel.displayName,\n isRunning: channel.isRunning,\n connectionState: health.state,\n lastPingTime: health.lastPingTime,\n reconnectCount: health.reconnectCount,\n errorMessage: health.errorMessage,\n });\n }\n\n return status;\n }\n\n /**\n * 获取已启用的 Channel 数量\n */\n get count(): number {\n return this.channels.size;\n }\n\n /**\n * 设置出站消息路由\n * 监听 EventBus 的 outbound 事件,根据 channel 路由到对应的 Channel\n */\n private setupOutboundRouting(): void {\n this.unsubscribeOutbound = this.bus.onOutbound(\n async (event: OutboundMessage) => {\n // 从 event 中获取 channel 信息\n const channelName = (event as OutboundMessage & { channel?: string }).channel;\n const eventType = event.metadata?.eventType as string | undefined;\n const channelInstanceId = event.metadata?.channelInstanceId as string | undefined;\n const resolvedChatId = event.metadata?.resolvedChatId as string | undefined;\n const sessionId = event.metadata?.sessionId as string | undefined;\n\n if (!channelName) {\n this.logger.warn(\n { event },\n 'Outbound message missing channel field'\n );\n return;\n }\n\n // 广播到所有 Channel\n if (channelName === 'broadcast') {\n await this.broadcastMessage(event);\n return;\n }\n\n this.logger.debug(\n {\n channel: channelName,\n eventType,\n chatId: event.chatId,\n resolvedChatId,\n channelInstanceId,\n sessionId,\n },\n '[Channel] Routing outbound message'\n );\n\n // 单 Channel 路由\n await this.routeToChannel(channelName, event);\n }\n );\n\n this.logger.debug('Outbound message routing setup complete');\n }\n\n /**\n * 广播消息到所有 Channel\n * 每个 Channel 会根据 shouldNotify() 决定是否处理\n */\n private async broadcastMessage(event: OutboundMessage): Promise<void> {\n const eventType = event.metadata?.eventType as string;\n\n this.logger.debug(\n { eventType, channelCount: this.channels.size },\n '[Channel] Broadcasting'\n );\n\n for (const [name, channel] of this.channels) {\n // Channel 自己决定是否处理\n if (!channel.shouldNotify(eventType)) {\n continue;\n }\n\n if (!channel.isRunning) {\n continue;\n }\n\n try {\n await channel.send(event);\n this.logger.debug(\n {\n channel: name,\n eventType,\n chatId: event.chatId,\n resolvedChatId: event.metadata?.resolvedChatId,\n sessionId: event.metadata?.sessionId,\n },\n '[Channel] Sent'\n );\n } catch (error) {\n this.logger.error({ channel: name, error: error instanceof Error ? error.message : String(error) }, '[Channel] Send failed');\n }\n }\n }\n\n /**\n * 路由消息到指定 Channel\n * 增加对流式消息的特殊处理\n */\n private async routeToChannel(\n channelName: string,\n event: OutboundMessage\n ): Promise<void> {\n const channel = this.channels.get(channelName);\n if (!channel) {\n this.logger.warn({ channel: channelName }, 'Channel not found');\n return;\n }\n\n if (!channel.isRunning) {\n this.logger.warn({ channel: channelName }, 'Channel is not running');\n return;\n }\n\n try {\n // 检查是否为流式消息(_streamDelta 标记)\n const isDelta = event.metadata?._streamDelta === true;\n const hasSendDelta = typeof channel.sendDelta === 'function';\n\n // 流式消息:使用 sendDelta\n if (isDelta && channel.supportsStreaming && hasSendDelta && channel.sendDelta) {\n await channel.sendDelta(\n event.chatId,\n event.text || '',\n {\n _streamId: event.metadata?._streamId as string | undefined,\n _streamEnd: event.metadata?._streamEnd as boolean | undefined,\n }\n );\n this.logger.debug(\n { channel: channelName, streamId: event.metadata?._streamId },\n 'Stream delta sent'\n );\n return;\n }\n\n // 普通消息:检查是否包含按钮且 Channel 支持按钮\n const buttons = (event as OutboundMessage & { buttons?: Button[][] }).buttons;\n if (\n buttons &&\n Array.isArray(buttons) &&\n buttons.length > 0 &&\n channel.capabilities.supportsButtons\n ) {\n await channel.sendWithButtons(event, buttons);\n this.logger.debug({ channel: channelName, hasButtons: true }, 'Message sent with buttons');\n } else {\n await channel.send(event);\n this.logger.debug(\n {\n channel: channelName,\n chatId: event.chatId,\n resolvedChatId: event.metadata?.resolvedChatId,\n eventType: event.metadata?.eventType,\n sessionId: event.metadata?.sessionId,\n },\n 'Message sent'\n );\n }\n } catch (error) {\n this.logger.error({ channel: channelName, error }, 'Failed to send message');\n }\n }\n}\n\n/**\n * 创建 ChannelManager 实例\n * @param bus - EventBus 实例\n * @param logger - 可选的日志记录器\n * @returns ChannelManager 实例\n */\nexport function createChannelManager(\n bus: EventBus,\n logger?: Logger\n): ChannelManager {\n return new ChannelManager(bus, logger);\n}\n","import type { Channel, ChannelConstructor } from './types.js';\n\n/**\n * Channel 注册表类(单例模式)\n * 用于管理所有 Channel 类的注册和发现\n */\nexport class ChannelRegistry {\n private static instance: ChannelRegistry | null = null;\n private registry: Map<string, ChannelConstructor> = new Map();\n\n /**\n * 私有构造函数,防止外部实例化\n */\n private constructor() {}\n\n /**\n * 获取 ChannelRegistry 单例实例\n * @returns ChannelRegistry 实例\n */\n static getInstance(): ChannelRegistry {\n if (!ChannelRegistry.instance) {\n ChannelRegistry.instance = new ChannelRegistry();\n }\n return ChannelRegistry.instance;\n }\n\n /**\n * 注册 Channel 类\n * @param name - Channel 唯一标识名\n * @param channelClass - Channel 构造函数\n */\n register(name: string, channelClass: ChannelConstructor): void {\n if (this.registry.has(name)) {\n console.warn(`Channel \"${name}\" is already registered, overwriting...`);\n }\n this.registry.set(name, channelClass);\n }\n\n /**\n * 获取已注册的 Channel 类\n * @param name - Channel 唯一标识名\n * @returns Channel 构造函数,如果不存在则返回 undefined\n */\n get(name: string): ChannelConstructor | undefined {\n return this.registry.get(name);\n }\n\n /**\n * 检查是否已注册指定 Channel\n * @param name - Channel 唯一标识名\n * @returns 是否已注册\n */\n has(name: string): boolean {\n return this.registry.has(name);\n }\n\n /**\n * 列出所有已注册的 Channel 名称\n * @returns Channel 名称数组\n */\n list(): string[] {\n return Array.from(this.registry.keys());\n }\n\n /**\n * 清空注册表(主要用于测试)\n */\n clear(): void {\n this.registry.clear();\n }\n\n /**\n * 重置单例实例(主要用于测试)\n */\n static resetInstance(): void {\n ChannelRegistry.instance = null;\n }\n}\n\n/**\n * Channel 装饰器\n * 用于自动注册 Channel 类到注册表\n *\n * 使用示例:\n * ```typescript\n * @Channel('telegram')\n * export class TelegramChannel extends BaseChannel {\n * // ...\n * }\n * ```\n *\n * @param name - Channel 唯一标识名\n * @returns 类装饰器函数\n */\nexport function Channel(name: string): ClassDecorator {\n return function <T extends Function>(target: T): T {\n const registry = ChannelRegistry.getInstance();\n registry.register(name, target as unknown as ChannelConstructor);\n return target;\n };\n}\n","export { InboundRouter } from './InboundRouter.js';\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { InboundMessage } from '../bus/events.js';\nimport { BindingService } from '../binding/index.js';\nimport { getLogger } from '../../shared/logger.js';\nimport {\n getSlashCommandRoot,\n isSystemCommandText,\n} from '../command/routing.js';\n\n/**\n * InboundRouter\n *\n * 统一处理 channel 入站消息:\n * 1. 系统命令标记为 systemCommand,由 CommandHandler 执行\n * 2. agent 显式命令(如 /codex help)标记为 agentCommand,转给绑定 agent\n * 3. 普通文本默认转发给当前 channel 绑定的 agent\n */\nexport class InboundRouter {\n private readonly bus: EventBus;\n private readonly bindingService: BindingService;\n private readonly logger: Logger;\n private unsubscribe: (() => void) | null = null;\n\n constructor(bus: EventBus, logger?: Logger) {\n this.bus = bus;\n this.bindingService = new BindingService(logger);\n this.logger = logger ?? getLogger();\n }\n\n start(): void {\n if (this.unsubscribe) {\n this.logger.warn('InboundRouter already started');\n return;\n }\n\n this.unsubscribe = this.bus.onInbound(this.handleInbound.bind(this));\n this.logger.info('InboundRouter started');\n }\n\n stop(): void {\n if (!this.unsubscribe) {\n return;\n }\n\n this.unsubscribe();\n this.unsubscribe = null;\n this.logger.info('InboundRouter stopped');\n }\n\n private handleInbound(message: InboundMessage): void {\n if (message.targetAgent || message.systemCommand) {\n return;\n }\n\n const boundAgent = this.bindingService.getBoundAgent(message.channelInstanceId);\n const commandRoot = getSlashCommandRoot(message.text);\n\n if (isSystemCommandText(message.text)) {\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n commandRoot,\n },\n '[InboundRouter] Routed inbound message to system command handler'\n );\n this.bus.publishInbound({\n ...message,\n systemCommand: true,\n });\n return;\n }\n\n if (!boundAgent) {\n if (commandRoot) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'No agent is bound to this channel. Run /bind <agent> first.',\n replyToMessageId: message.messageId,\n });\n } else {\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n },\n '[InboundRouter] Dropping plain text because no agent is bound'\n );\n }\n return;\n }\n\n this.logger.debug(\n {\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n textPreview: message.text.slice(0, 120),\n targetAgent: boundAgent,\n commandRoot,\n },\n '[InboundRouter] Routed inbound message to bound agent'\n );\n this.bus.publishInbound({\n ...message,\n targetAgent: boundAgent,\n agentCommand: false,\n });\n }\n\n}\n","export { BindingService, type AgentType } from './BindingService.js';","import type { Logger } from 'pino';\nimport { getLogger } from '../../shared/logger.js';\nimport { loadConfig, type BindingsConfig } from '../../config.js';\nimport { writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\n\nexport type AgentType = 'claude' | 'codex';\n\nexport class BindingService {\n private logger: Logger;\n /** Cache the config to avoid repeated disk reads. Refreshed on each bind/unbind since we write to disk. */\n private cachedConfig: ReturnType<typeof loadConfig> | null = null;\n\n constructor(logger?: Logger) {\n this.logger = logger ?? getLogger();\n }\n\n private getConfig() {\n if (!this.cachedConfig) {\n this.cachedConfig = loadConfig();\n }\n return this.cachedConfig;\n }\n\n /** Invalidate cache after writes so the next read picks up fresh data. */\n private invalidateCache(): void {\n this.cachedConfig = null;\n }\n\n /**\n * Get the current bindings config.\n */\n getBindings(): BindingsConfig {\n const config = this.getConfig();\n const bindings = config.bindings;\n // Return undefined when bindings is not present (not set in config)\n if (!bindings || Object.keys(bindings).length === 0) {\n return {};\n }\n return bindings;\n }\n\n /**\n * Get the channel instance ID that a given agent is bound to.\n */\n getBoundChannel(agent: AgentType): string | undefined {\n return this.getBindings()[agent];\n }\n\n /**\n * Get the agent bound to a given channel instance ID.\n */\n getBoundAgent(channelInstanceId: string): AgentType | undefined {\n const bindings = this.getBindings();\n for (const [agent, channelId] of Object.entries(bindings)) {\n if (channelId === channelInstanceId) {\n return agent as AgentType;\n }\n }\n return undefined;\n }\n\n /**\n * Bind an agent to a channel instance.\n * If the agent is already bound to another channel, it will be migrated.\n * If the target channel is already bound to another agent, that binding is replaced.\n * Returns the old channel instance ID that the agent was bound to (if any).\n */\n bindAgent(agent: AgentType, channelInstanceId: string): string | undefined {\n // Validate format: must be \"type:hash\"\n if (!channelInstanceId.includes(':')) {\n this.logger.error({ channelInstanceId }, '[Binding] Invalid channel instance ID format');\n return undefined;\n }\n\n const config = this.getConfig();\n const bindings = { ...(config.bindings ?? {}) } as Record<string, string | undefined>;\n const oldChannelId = bindings[agent];\n\n // Remove any existing binding where this channel was bound (swap/migration case)\n for (const [a, cid] of Object.entries(bindings)) {\n if (cid === channelInstanceId && a !== agent) {\n this.logger.debug({ agent: a, oldChannel: cid }, '[Binding] Removing conflicting binding');\n delete bindings[a];\n }\n }\n\n bindings[agent] = channelInstanceId;\n this.saveBindings(bindings as BindingsConfig);\n\n return oldChannelId;\n }\n\n /**\n * Unbind an agent from its current channel.\n * Returns the old channel instance ID (if any).\n */\n unbindAgent(agent: AgentType): string | undefined {\n const config = this.getConfig();\n const bindings = { ...(config.bindings ?? {}) };\n const oldChannelId = bindings[agent];\n\n if (!oldChannelId) {\n return undefined;\n }\n\n delete bindings[agent];\n this.saveBindings(bindings);\n\n this.logger.info({ agent, oldChannelId }, '[Binding] Agent unbound');\n return oldChannelId;\n }\n\n /**\n * Check if an agent is configured (i.e., can be bound).\n * An agent is configurable if it has a non-empty config entry.\n */\n isAgentConfigurable(agent: AgentType): boolean {\n const config = this.getConfig();\n if (agent === 'claude') {\n return !!config.agent.claude;\n }\n if (agent === 'codex') {\n return config.agent.codex?.enabled === true;\n }\n return false;\n }\n\n private saveBindings(bindings: BindingsConfig): void {\n const config = this.getConfig();\n const merged = {\n ...config,\n bindings,\n };\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n writeFileSync(configPath, TOML.stringify(merged as unknown as Parameters<typeof TOML.stringify>[0]));\n this.invalidateCache();\n }\n}","export const COMMAND_ROOT_SUBCOMMAND = '__root__';\n\nexport const SYSTEM_COMMAND_ROOTS = new Set([\n 'start',\n 'help',\n 'status',\n 'ping',\n 'bind',\n 'unbind',\n 'new',\n 'clear',\n 'stop',\n 'session',\n 'system',\n]);\n\nexport function getSlashCommandRoot(text: string): string | null {\n const trimmed = text.trim();\n if (!trimmed.startsWith('/')) {\n return null;\n }\n\n const withoutSlash = trimmed.slice(1);\n if (!withoutSlash) {\n return null;\n }\n\n const firstToken = withoutSlash.split(/\\s+/, 1)[0] ?? '';\n const root = firstToken.split(':', 1)[0] ?? '';\n return root.toLowerCase() || null;\n}\n\nexport function isSystemCommandText(text: string): boolean {\n const root = getSlashCommandRoot(text);\n return !!root && SYSTEM_COMMAND_ROOTS.has(root);\n}\n","import { setupCommandHandler } from './command.js';\nimport { setupPermissionHandler } from './permission.js';\n\nexport { setupCommandHandler, setupPermissionHandler };\n\nimport type { Logger } from 'pino';\nimport type { EventBus } from '../../core/bus/index.js';\nimport type { SessionManager } from '../../core/session/SessionManager.js';\nimport type { InteractionQueue } from '../../adapters/interaction/index.js';\nimport type { Gateway } from '../index.js';\n\n/**\n * Setup all gateway handlers\n */\nexport function setupAllHandlers(\n bus: EventBus,\n gateway: Gateway,\n interactionQueue: InteractionQueue,\n logger: Logger\n): () => void {\n const cleanupFns: Array<() => void> = [];\n\n cleanupFns.push(setupCommandHandler(bus, gateway.getSessionManager(), logger));\n cleanupFns.push(setupPermissionHandler(bus, interactionQueue, logger));\n\n return () => {\n for (const fn of cleanupFns) {\n fn();\n }\n };\n}\n","import type { Logger } from 'pino';\nimport { EventBus } from '../../core/bus/index.js';\nimport type { SessionManager } from '../../core/session/SessionManager.js';\nimport {\n registerBuiltinCommands,\n commandRegistry,\n CommandExecutor,\n} from '../../core/command/index.js';\nimport type { InboundMessage } from '../../core/bus/events.js';\n\n/**\n * Setup command handler to process only system commands.\n *\n * InboundRouter is responsible for classifying inbound messages and republishing\n * system commands with `systemCommand: true`.\n */\nexport function setupCommandHandler(\n bus: EventBus,\n sessionManager: SessionManager,\n logger: Logger\n): () => void {\n registerBuiltinCommands(commandRegistry);\n logger.debug('Builtin commands registered');\n\n const executor = new CommandExecutor(commandRegistry, logger);\n\n return bus.onInbound(async (message: InboundMessage) => {\n if (!message.systemCommand) {\n return;\n }\n\n const result = await executor.execute(message.text, {\n source: message,\n bus,\n sessionManager,\n });\n\n if (result === null) {\n logger.warn(\n {\n text: message.text,\n textPreview: message.text.slice(0, 120),\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n },\n '[Command] Routed as system command but no handler was found'\n );\n return;\n }\n\n bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: result,\n replyToMessageId: message.messageId,\n });\n\n logger.info(\n {\n command: message.text.slice(0, 80),\n chatId: message.chatId,\n messageId: message.messageId,\n channelInstanceId: message.channelInstanceId,\n },\n '[Command] Executed system command'\n );\n });\n}\n","import { getLogger } from '../../shared/logger.js';\nimport {\n CommandContext,\n CommandHandler,\n CommandGroup,\n CommandHandlerFunction,\n} from './types.js';\n\n/**\n * 命令注册表\n * 管理所有可用命令的注册和检索\n */\nexport class CommandRegistry {\n private commands = new Map<string, Map<string, CommandHandler>>();\n private logger = getLogger();\n\n /**\n * 注册单个命令\n * @param group - 命令组名称(如 'session')\n * @param subcommand - 子命令名称(如 'list')\n * @param handler - 命令处理器\n */\n register(\n group: string,\n subcommand: string,\n handler: CommandHandler\n ): void {\n if (!this.commands.has(group)) {\n this.commands.set(group, new Map());\n }\n const groupMap = this.commands.get(group)!;\n groupMap.set(subcommand, handler);\n this.logger.debug(\n { group, subcommand },\n 'Command registered'\n );\n }\n\n /**\n * 批量注册命令组\n * @param group - 命令组名称\n * @param handlers - 命令组(包含多个子命令)\n */\n registerGroup(group: string, handlers: CommandGroup): void {\n for (const [subcommand, handler] of Object.entries(handlers)) {\n this.register(group, subcommand, handler);\n }\n }\n\n /**\n * 获取命令处理器\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理器,如果不存在则返回 undefined\n */\n get(group: string, subcommand: string): CommandHandler | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n return groupMap.get(subcommand);\n }\n\n /**\n * 获取命令处理函数(便捷方法)\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理函数,如果不存在则返回 undefined\n */\n getHandler(group: string, subcommand: string): CommandHandlerFunction | undefined {\n return this.get(group, subcommand)?.handler;\n }\n\n /**\n * 检查命令是否存在\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否存在\n */\n has(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n return groupMap.has(subcommand);\n }\n\n /**\n * 检查命令组是否存在\n * @param group - 命令组名称\n * @returns 是否存在\n */\n hasGroup(group: string): boolean {\n return this.commands.has(group);\n }\n\n /**\n * 列出所有命令\n * @returns 所有命令的列表,格式为 { group, subcommand, description, usage }\n */\n list(): Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> {\n const result: Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> = [];\n\n for (const [group, groupMap] of this.commands.entries()) {\n for (const [subcommand, handler] of groupMap.entries()) {\n result.push({\n group,\n subcommand,\n description: handler.description,\n usage: handler.usage,\n });\n }\n }\n\n // 按组名和子命令名排序\n result.sort((a, b) => {\n if (a.group !== b.group) {\n return a.group.localeCompare(b.group);\n }\n return a.subcommand.localeCompare(b.subcommand);\n });\n\n return result;\n }\n\n /**\n * 获取命令组中的所有子命令\n * @param group - 命令组名称\n * @returns 命令组,如果不存在则返回 undefined\n */\n getGroup(group: string): CommandGroup | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n const result: CommandGroup = {};\n for (const [subcommand, handler] of groupMap.entries()) {\n result[subcommand] = handler;\n }\n return result;\n }\n\n /**\n * 获取所有命令组名称\n * @returns 命令组名称列表\n */\n getGroups(): string[] {\n return Array.from(this.commands.keys()).sort();\n }\n\n /**\n * 注销单个命令\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否成功注销\n */\n unregister(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n const result = groupMap.delete(subcommand);\n if (result) {\n this.logger.debug({ group, subcommand }, 'Command unregistered');\n }\n // 如果组为空,删除组\n if (groupMap.size === 0) {\n this.commands.delete(group);\n }\n return result;\n }\n\n /**\n * 清空所有命令\n */\n clear(): void {\n this.commands.clear();\n this.logger.debug('All commands cleared');\n }\n}\n\n/**\n * 全局命令注册表单例\n */\nexport const commandRegistry = new CommandRegistry();\n\n// 导出类型\nexport * from './types.js';\n\n// 导出命令执行器\nexport { CommandExecutor } from './executor.js';\n\n// 导出内置命令注册函数\nexport { registerBuiltinCommands } from './builtin/index.js';\n","import { InboundMessage } from '../bus/events.js';\nimport { EventBus } from '../bus/index.js';\nimport type { SessionManager } from '../session/SessionManager.js';\n\n/**\n * 命令上下文\n * 提供给命令处理器的执行环境\n */\nexport interface CommandContext {\n /** 原始入站消息 */\n source: InboundMessage;\n /** 事件总线 */\n bus: EventBus;\n /** 会话管理器 */\n sessionManager: SessionManager;\n}\n\n/**\n * 命令处理器函数类型\n */\nexport type CommandHandlerFunction = (\n args: string[],\n context: CommandContext\n) => Promise<string>;\n\n/**\n * 命令处理器\n * 定义一个命令的处理逻辑和元数据\n */\nexport interface CommandHandler {\n /** 命令描述 */\n description: string;\n /** 使用示例 */\n usage?: string;\n /** 处理函数 */\n handler: CommandHandlerFunction;\n}\n\n/**\n * 命令组\n * 包含一组相关的子命令(如 session list, session status)\n * key 是子命令名称,value 是命令处理器\n */\nexport type CommandGroup = Record<string, CommandHandler>;\n","import type { Logger } from 'pino';\nimport { CommandRegistry } from './index.js';\nimport { CommandParser, ParsedCommand } from './parser.js';\nimport { CommandContext } from './types.js';\nimport { getLogger } from '../../shared/logger.js';\nimport { COMMAND_ROOT_SUBCOMMAND } from './routing.js';\n\n/**\n * Command executor\n * Parses and executes commands using the registry\n */\nexport class CommandExecutor {\n private parser: CommandParser;\n private registry: CommandRegistry;\n private logger: Logger;\n\n /**\n * Create a command executor\n * @param registry - Command registry for looking up handlers\n * @param logger - Optional logger instance\n */\n constructor(registry: CommandRegistry, logger?: Logger) {\n this.parser = new CommandParser();\n this.registry = registry;\n this.logger = logger ?? getLogger();\n }\n\n /**\n * Check if content is a command\n * @param content - Content to check\n * @returns true if content is a command\n */\n isCommand(content: string): boolean {\n return this.parser.isCommand(content);\n }\n\n /**\n * Execute a command\n * @param content - Command content to execute\n * @param context - Command execution context\n * @returns Command result string, or null if not a command\n */\n async execute(\n content: string,\n context: CommandContext\n ): Promise<string | null> {\n // Parse the command\n const parsed = this.parser.parse(content);\n if (!parsed) {\n return null;\n }\n\n this.logger.debug(\n { command: parsed.command, subcommand: parsed.subcommand, args: parsed.args },\n 'Executing command'\n );\n\n // Look up the handler\n const handler = this.registry.get(parsed.command, parsed.subcommand);\n\n if (!handler) {\n // Command not found - provide helpful message\n if (this.registry.hasGroup(parsed.command)) {\n // Group exists but subcommand doesn't\n const availableSubcommands = Object.keys(\n this.registry.getGroup(parsed.command) ?? {}\n )\n .filter((name) => name !== COMMAND_ROOT_SUBCOMMAND)\n .join(', ');\n\n if (parsed.subcommand === COMMAND_ROOT_SUBCOMMAND) {\n return `/${parsed.command} needs a subcommand. Available: ${availableSubcommands || 'none'}`;\n }\n\n return `Unknown subcommand \"${parsed.subcommand}\" for /${parsed.command}. Available: ${availableSubcommands || 'none'}`;\n }\n // Group doesn't exist\n const availableGroups = this.registry.getGroups();\n if (availableGroups.length === 0) {\n return `Unknown command /${parsed.command}. No commands are currently registered.`;\n }\n return `Unknown command /${parsed.command}. Available commands: ${availableGroups.join(', ')}`;\n }\n\n // Execute the handler\n try {\n const result = await handler.handler(parsed.args, context);\n return result;\n } catch (error) {\n this.logger.error(\n {\n command: parsed.command,\n subcommand: parsed.subcommand,\n error: error instanceof Error ? error.message : String(error),\n },\n 'Command execution failed'\n );\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n return `Error executing /${parsed.command} ${parsed.subcommand}: ${errorMessage}`;\n }\n }\n\n /**\n * Get the parsed command without executing\n * @param content - Content to parse\n * @returns ParsedCommand or null\n */\n parse(content: string): ParsedCommand | null {\n return this.parser.parse(content);\n }\n}\n","import { COMMAND_ROOT_SUBCOMMAND } from './routing.js';\n\n/**\n * Parsed command structure\n */\nexport interface ParsedCommand {\n /** Main command */\n command: string;\n /** Subcommand */\n subcommand: string;\n /** Argument list */\n args: string[];\n}\n\n/**\n * Command parser\n * Parses command strings in various formats\n */\nexport class CommandParser {\n /**\n * Check if content is a command (starts with /)\n * @param content - Content to check\n * @returns true if content is a command\n */\n isCommand(content: string): boolean {\n if (!content || typeof content !== 'string') {\n return false;\n }\n return content.trim().startsWith('/');\n }\n\n /**\n * Parse command content\n * Supports formats:\n * - /command subcommand arg1 arg2\n * - /command:subcommand arg1 arg2\n * - /command (root command)\n * @param content - Content to parse\n * @returns ParsedCommand or null if not a command\n */\n parse(content: string): ParsedCommand | null {\n if (!this.isCommand(content)) {\n return null;\n }\n\n const trimmed = content.trim();\n\n // Remove the leading '/' and split by whitespace\n const withoutSlash = trimmed.slice(1);\n\n // Check for /command:subcommand format\n const colonIndex = withoutSlash.indexOf(':');\n const spaceIndex = withoutSlash.indexOf(' ');\n\n let command: string;\n let subcommand: string;\n let argsString: string;\n\n if (colonIndex !== -1 && (spaceIndex === -1 || colonIndex < spaceIndex)) {\n // Format: /command:subcommand arg1 arg2\n command = withoutSlash.slice(0, colonIndex);\n const afterColon = withoutSlash.slice(colonIndex + 1);\n const firstSpaceAfterColon = afterColon.indexOf(' ');\n\n if (firstSpaceAfterColon === -1) {\n // No args: /command:subcommand\n subcommand = afterColon;\n argsString = '';\n } else {\n subcommand = afterColon.slice(0, firstSpaceAfterColon);\n argsString = afterColon.slice(firstSpaceAfterColon + 1);\n }\n } else {\n // Format: /command subcommand arg1 arg2\n const parts = withoutSlash.split(/\\s+/);\n command = parts[0];\n\n if (parts.length === 1) {\n // Only command: /command\n subcommand = COMMAND_ROOT_SUBCOMMAND;\n argsString = '';\n } else {\n subcommand = parts[1];\n argsString = parts.slice(2).join(' ');\n }\n }\n\n // Parse arguments, handling multiple spaces\n const args = argsString\n .trim()\n .split(/\\s+/)\n .filter(arg => arg.length > 0);\n\n return {\n command,\n subcommand,\n args,\n };\n }\n}\n\n/**\n * Global command parser instance\n */\nexport const commandParser = new CommandParser();\n","import { CommandRegistry } from '../index.js';\nimport { bindCommand, unbindAgentCommand } from './bind.js';\nimport { helpCommand } from './help.js';\nimport {\n clearCommand,\n newCommand,\n registerSessionCommands,\n sessionRootCommand,\n stopCommand,\n} from './session.js';\nimport { startCommand } from './start.js';\nimport { pingCommand, registerSystemCommands, statusCommand } from './system.js';\nimport { COMMAND_ROOT_SUBCOMMAND } from '../routing.js';\n\nexport { bindCommand, unbindCommand, unbindAgentCommand } from './bind.js';\nexport { helpCommand, registerHelpCommand } from './help.js';\nexport {\n clearCommand,\n newCommand,\n registerSessionCommands,\n sessionCommands,\n sessionRootCommand,\n stopCommand,\n} from './session.js';\nexport { startCommand, registerStartCommand } from './start.js';\nexport { pingCommand, registerSystemCommands, statusCommand, systemCommands } from './system.js';\n\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n registry.register('start', COMMAND_ROOT_SUBCOMMAND, startCommand);\n registry.register('help', COMMAND_ROOT_SUBCOMMAND, helpCommand);\n registry.register('status', COMMAND_ROOT_SUBCOMMAND, statusCommand);\n registry.register('ping', COMMAND_ROOT_SUBCOMMAND, pingCommand);\n registry.register('bind', COMMAND_ROOT_SUBCOMMAND, bindCommand);\n registry.register('unbind', COMMAND_ROOT_SUBCOMMAND, unbindAgentCommand);\n registry.register('new', COMMAND_ROOT_SUBCOMMAND, newCommand);\n registry.register('clear', COMMAND_ROOT_SUBCOMMAND, clearCommand);\n registry.register('stop', COMMAND_ROOT_SUBCOMMAND, stopCommand);\n registry.register('session', COMMAND_ROOT_SUBCOMMAND, sessionRootCommand);\n\n registerSessionCommands((group, subcommand, handler) => {\n registry.register(group, subcommand, handler);\n });\n\n registerSystemCommands((group, subcommand, handler) => {\n registry.register(group, subcommand, handler);\n });\n}\n","import { CommandHandler } from '../types.js';\nimport { BindingService, type AgentType } from '../../binding/index.js';\nimport { getLogger } from '../../../shared/logger.js';\n\nconst bindingService = new BindingService();\n\nexport const bindCommand: CommandHandler = {\n description: 'Bind this channel to an agent',\n usage: '/bind <claude|codex>',\n\n async handler(args: string[], context) {\n const logger = getLogger();\n const [agentArg] = args;\n\n if (!agentArg) {\n return 'Usage: /bind <claude|codex>';\n }\n\n const agent = agentArg as AgentType;\n if (agent !== 'claude' && agent !== 'codex') {\n return `Unknown agent \"${agentArg}\". Available: claude, codex`;\n }\n\n if (!bindingService.isAgentConfigurable(agent)) {\n return `\"${agent}\" is not configured and cannot be bound. Run the wizard first.`;\n }\n\n const instanceId = context.source.channelInstanceId;\n const oldChannelId = bindingService.bindAgent(agent, instanceId);\n logger.info({ agent, channelInstanceId: instanceId, oldChannelId }, '[bind] Binding changed');\n\n if (oldChannelId && oldChannelId !== instanceId) {\n return `${agent} has been moved from ${oldChannelId} to this channel (${instanceId}).`;\n }\n\n return `${agent} is now bound to this channel (${instanceId}).`;\n },\n};\n\nexport const unbindCommand: CommandHandler = {\n description: 'Unbind the current channel from its agent',\n usage: '/unbind',\n\n async handler() {\n return 'Use /unbind <agent> to remove a binding explicitly.';\n },\n};\n\nexport const unbindAgentCommand: CommandHandler = {\n description: 'Unbind an agent from its current channel',\n usage: '/unbind <claude|codex>',\n\n async handler(args: string[], context) {\n const logger = getLogger();\n const [agentArg] = args;\n\n if (agentArg) {\n if (agentArg !== 'claude' && agentArg !== 'codex') {\n return `Unknown agent \"${agentArg}\". Available: claude, codex`;\n }\n\n const oldChannelId = bindingService.unbindAgent(agentArg);\n if (!oldChannelId) {\n return `${agentArg} is not currently bound.`;\n }\n\n logger.info({ agent: agentArg, oldChannelId }, '[unbind] Agent unbound');\n return `${agentArg} has been unbound from ${oldChannelId}.`;\n }\n\n const currentAgent = bindingService.getBoundAgent(context.source.channelInstanceId);\n if (!currentAgent) {\n return 'No agent is bound to this channel.';\n }\n\n const oldChannelId = bindingService.unbindAgent(currentAgent);\n logger.info({ agent: currentAgent, oldChannelId }, '[unbind] Agent unbound');\n return `${currentAgent} has been unbound from this channel.`;\n },\n};\n","import { CommandHandler } from '../types.js';\n\nexport const helpCommand: CommandHandler = {\n description: 'Show system and agent command help',\n usage: '/help',\n handler: async (): Promise<string> => {\n return [\n '**Command Model**',\n '',\n '**Core System Commands**',\n '- `/start` show the quick-start message',\n '- `/help` show this help',\n '- `/status` show Handsoff runtime status',\n '- `/bind <agent>` bind this channel to an agent',\n '- `/unbind` remove the current binding',\n '- `/new` start fresh for this chat',\n '- `/clear` clear the current chat session',\n '- `/stop` stop the current chat session',\n '- `/session` inspect the current chat session',\n '',\n 'Plain text and any non-system commands are forwarded to the bound agent.',\n ].join('\\n');\n },\n};\n\nexport function registerHelpCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('help', 'help', helpCommand);\n}\n","import { CommandContext, CommandGroup, CommandHandler } from '../types.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { BindingService } from '../../binding/index.js';\nimport type { AgentType, SessionInfo } from '../../../core/adapter/types.js';\n\nconst bindingService = new BindingService();\n\nfunction formatDuration(start: Date, end?: Date): string {\n const endTime = end ?? new Date();\n const diff = endTime.getTime() - start.getTime();\n\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`;\n if (hours > 0) return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n\nfunction getBoundAgentContext(context: CommandContext): {\n agentType?: AgentType;\n sessionId?: string;\n session?: ReturnType<CommandContext['sessionManager']['getSession']>;\n} {\n const agentType = bindingService.getBoundAgent(context.source.channelInstanceId);\n if (!agentType) {\n return {};\n }\n\n const sessionId = `${agentType}-${context.source.chatId}`;\n return {\n agentType,\n sessionId,\n session: context.sessionManager.getSession(sessionId),\n };\n}\n\nconst listHandler: CommandHandler = {\n description: 'List active sessions',\n usage: '/session list [--agent <type>] [--all]',\n handler: async (args: string[]): Promise<string> => {\n let agentFilter: string | undefined;\n let includeEnded = false;\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--agent' && i + 1 < args.length) {\n agentFilter = args[i + 1];\n i++;\n } else if (args[i] === '--all') {\n includeEnded = true;\n }\n }\n\n const registry = SessionScannerRegistry.getInstance();\n let sessions: SessionInfo[] = agentFilter\n ? await registry.scanByAgent(agentFilter as AgentType)\n : await registry.scanAll();\n\n if (!includeEnded) {\n sessions = sessions.filter((s) => s.status === 'active');\n }\n\n if (sessions.length === 0) {\n return includeEnded ? 'No sessions found.' : 'No active sessions.';\n }\n\n const byAgent = new Map<string, SessionInfo[]>();\n for (const session of sessions) {\n const list = byAgent.get(session.agentType) ?? [];\n list.push(session);\n byAgent.set(session.agentType, list);\n }\n\n const lines: string[] = [includeEnded ? '**All Sessions**' : '**Active Sessions**', ''];\n for (const [agentType, agentSessions] of byAgent) {\n lines.push(`**${agentType}** (${agentSessions.length})`);\n for (const session of agentSessions) {\n lines.push(`- \\`${session.id}\\` (${session.status}, ${formatDuration(new Date(session.createdAt))})`);\n }\n lines.push('');\n }\n\n return lines.join('\\n').trim();\n },\n};\n\nconst statusHandler: CommandHandler = {\n description: 'Show details for a specific session',\n usage: '/session status <session-id>',\n handler: async (args: string[]): Promise<string> => {\n const sessionId = args[0];\n if (!sessionId) {\n return 'Usage: /session status <session-id>';\n }\n\n const registry = SessionScannerRegistry.getInstance();\n const session = (await registry.scanAll()).find((entry) => entry.id === sessionId);\n if (!session) {\n return `Session \\`${sessionId}\\` not found.`;\n }\n\n const lines = [\n `**Session ${session.id}**`,\n '',\n `Agent: ${session.agentType}`,\n `Transport: ${session.transportType}`,\n `Status: ${session.status}`,\n `Started: ${new Date(session.createdAt).toISOString()}`,\n `Duration: ${formatDuration(new Date(session.createdAt))}`,\n ];\n\n if (session.cwd) {\n lines.push(`Workdir: \\`${session.cwd}\\``);\n }\n\n return lines.join('\\n');\n },\n};\n\nconst countHandler: CommandHandler = {\n description: 'Show session counts',\n usage: '/session count',\n handler: async (_args, context): Promise<string> => {\n const allSessions = context.sessionManager.listSessions();\n const active = allSessions.filter((s) => s.status === 'active');\n const closed = allSessions.filter((s) => s.status !== 'active');\n\n return [\n '**Session Statistics**',\n '',\n `Active: ${active.length}`,\n `Closed: ${closed.length}`,\n `Total: ${allSessions.length}`,\n ].join('\\n');\n },\n};\n\nexport const sessionRootCommand: CommandHandler = {\n description: 'Show the current chat session for the bound agent',\n usage: '/session',\n handler: async (_args, context): Promise<string> => {\n const bound = getBoundAgentContext(context);\n if (!bound.agentType) {\n return 'No agent is bound to this channel.';\n }\n\n if (!bound.session || bound.session.getStatus() !== 'active') {\n if (bound.agentType === 'claude') {\n return 'This channel is bound to Claude. Claude sessions are started from the local Claude Code client, so use `/claude status` to inspect hook state and active Claude sessions.';\n }\n return `This channel is bound to ${bound.agentType}, but there is no active session for this chat yet. Send a message to start one.`;\n }\n\n const lines = [\n '**Current Session**',\n '',\n `Agent: ${bound.agentType}`,\n `Session ID: \\`${bound.sessionId}\\``,\n `Status: ${bound.session.getStatus()}`,\n `Started: ${new Date(bound.session.createdAt).toISOString()}`,\n ];\n\n if (bound.session.cwd) {\n lines.push(`CWD: \\`${bound.session.cwd}\\``);\n }\n\n return lines.join('\\n');\n },\n};\n\nasync function resetCurrentSession(context: CommandContext): Promise<string> {\n const bound = getBoundAgentContext(context);\n if (!bound.agentType) {\n return 'No agent is bound to this channel.';\n }\n\n if (bound.agentType === 'claude') {\n return 'Claude sessions are managed by the local Claude Code client. Stop or restart Claude locally, then use this channel for approvals and notifications.';\n }\n\n if (!bound.session || bound.session.getStatus() !== 'active') {\n return `No active ${bound.agentType} session for this chat. The next message will start a fresh session.`;\n }\n\n await context.sessionManager.closeSession(bound.session.id);\n return `Closed the active ${bound.agentType} session. The next message will start a fresh session.`;\n}\n\nexport const clearCommand: CommandHandler = {\n description: 'Clear the current chat session',\n usage: '/clear',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const newCommand: CommandHandler = {\n description: 'Start fresh for the current chat',\n usage: '/new',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const stopCommand: CommandHandler = {\n description: 'Stop the current chat session',\n usage: '/stop',\n handler: async (_args, context): Promise<string> => resetCurrentSession(context),\n};\n\nexport const sessionCommands: CommandGroup = {\n list: listHandler,\n status: statusHandler,\n count: countHandler,\n};\n\nexport function registerSessionCommands(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n for (const [subcommand, handler] of Object.entries(sessionCommands)) {\n registerFn('session', subcommand, handler);\n }\n}\n","import { CommandHandler } from '../types.js';\nimport { BindingService } from '../../binding/index.js';\n\nconst bindingService = new BindingService();\n\nexport const startCommand: CommandHandler = {\n description: 'Show the quick-start guide for this channel',\n usage: '/start',\n handler: async (_args, context): Promise<string> => {\n const boundAgent = bindingService.getBoundAgent(context.source.channelInstanceId);\n\n return [\n '**Handsoff**',\n '',\n boundAgent\n ? `This channel is currently bound to **${boundAgent}**.`\n : 'This channel is not bound to an agent yet.',\n '',\n '**How to use it**',\n '- Send plain text to talk to the bound agent.',\n '- Use `/new` or `/clear` to start fresh in this chat.',\n '- Use `/session` to inspect the current chat session.',\n '- Use `/help` to see system commands.',\n ].join('\\n');\n },\n};\n\nexport function registerStartCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('start', 'start', startCommand);\n}\n","import { CommandGroup, CommandHandler } from '../types.js';\nimport process from 'process';\nimport os from 'os';\n\nconst systemStartTime = Date.now();\n\nfunction formatBytes(bytes: number): string {\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(2)} ${units[unitIndex]}`;\n}\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours % 24}h`);\n if (minutes > 0) parts.push(`${minutes % 60}m`);\n if (seconds > 0 || parts.length === 0) parts.push(`${seconds % 60}s`);\n return parts.join(' ');\n}\n\nexport const statusCommand: CommandHandler = {\n description: 'Show Handsoff runtime status',\n usage: '/status',\n handler: async (): Promise<string> => {\n const uptime = Date.now() - systemStartTime;\n const memoryUsage = process.memoryUsage();\n const totalMem = os.totalmem();\n const freeMem = os.freemem();\n const cpus = os.cpus();\n\n return [\n '**Handsoff Status**',\n '',\n `Uptime: ${formatDuration(uptime)}`,\n `Sessions: runtime process alive`,\n '',\n '**Runtime**',\n `Node.js: ${process.version}`,\n `Platform: ${process.platform} (${process.arch})`,\n '',\n '**Memory**',\n `RSS: ${formatBytes(memoryUsage.rss)}`,\n `Heap: ${formatBytes(memoryUsage.heapUsed)} / ${formatBytes(memoryUsage.heapTotal)}`,\n `System free: ${formatBytes(freeMem)} / ${formatBytes(totalMem)}`,\n '',\n '**CPU**',\n `Model: ${cpus[0]?.model ?? 'Unknown'}`,\n `Cores: ${cpus.length}`,\n `Load avg: ${os.loadavg().map((value) => value.toFixed(2)).join(', ')}`,\n ].join('\\n');\n },\n};\n\nexport const pingCommand: CommandHandler = {\n description: 'Check whether the gateway is responsive',\n usage: '/ping',\n handler: async (): Promise<string> => 'Pong. Handsoff is running.',\n};\n\nexport const systemCommands: CommandGroup = {\n status: statusCommand,\n ping: pingCommand,\n};\n\nexport function registerSystemCommands(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n for (const [subcommand, handler] of Object.entries(systemCommands)) {\n registerFn('system', subcommand, handler);\n }\n}\n","import type { Logger } from 'pino';\nimport { EventBus } from '../../core/bus/index.js';\nimport { InteractionQueue } from '../../adapters/interaction/queue.js';\nimport { InteractionResponseEvent } from '../../core/bus/events.js';\n\n/**\n * Setup permission handler to route decisions to InteractionQueue\n * @param bus - EventBus instance\n * @param interactionQueue - Interaction queue for managing permission requests\n * @param logger - Logger instance\n * @returns Cleanup function to remove event listeners\n */\nexport function setupPermissionHandler(\n bus: EventBus,\n interactionQueue: InteractionQueue,\n logger: Logger\n): () => void {\n // Subscribe to interaction response events\n const unsubscribe = bus.onInteractionResponse((event: InteractionResponseEvent) => {\n const { requestId, response, reason } = event;\n\n logger.debug(\n { requestId, action: response.action, reason },\n 'Processing interaction response'\n );\n\n // Apply response to queue\n const success = interactionQueue.respond(requestId, response);\n\n if (success) {\n logger.debug(\n { requestId, action: response.action },\n 'Interaction response applied'\n );\n } else {\n logger.warn(\n { requestId },\n 'Interaction response failed: request not found or already responded'\n );\n }\n });\n\n logger.debug('Permission handler setup complete');\n\n // Return cleanup function\n return unsubscribe;\n}\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../core/bus/index.js';\nimport { BindingService } from '../core/binding/index.js';\nimport type {\n SessionStartEvent,\n SessionEndEvent,\n ToolFailureEvent,\n InteractionRequestEvent,\n TurnFinishedEvent,\n ToolExecutedEvent,\n TurnThinkingEvent,\n ToolPostEvent,\n} from '../core/bus/events.js';\nimport type { NotificationContext } from './notification-context.js';\n\n/**\n * NotificationHandler 将 Gateway 事件转换为 OutboundMessage\n *\n * 职责:\n * 1. 监听 Gateway 事件 (session_start, session_end, permission_request, finished, tool_failure)\n * 2. 构建 NotificationContext\n * 3. 广播原始上下文到 EventBus\n * 4. 各 Channel 自行格式化\n */\nexport class NotificationHandler {\n private unsubscribeFns: Array<() => void> = [];\n private sessionAgentMap = new Map<string, 'claude' | 'codex'>();\n constructor(\n private bus: EventBus,\n private logger: Logger,\n private getSessionAgentType?: (sessionId: string) => 'claude' | 'codex' | undefined,\n private getSessionInfo?: (sessionId: string) => { model?: string } | undefined,\n private bindingService?: BindingService,\n ) {\n // Lazy instantiation if not provided (for backward compatibility)\n if (!this.bindingService) {\n this.bindingService = new BindingService(logger);\n }\n }\n\n /**\n * 启动监听\n */\n start(): void {\n if (this.unsubscribeFns.length > 0) {\n this.logger.warn('NotificationHandler already started');\n return;\n }\n this.unsubscribeFns.push(\n this.bus.onTurnFinished(this.handleTurnFinished.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolPost(this.handleToolPost.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolExecuted(this.handleToolExecuted.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onTurnThinking(this.handleTurnThinking.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionStart(this.handleSessionStart.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onSessionEnd(this.handleSessionEnd.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolFailure(this.handleToolFailure.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onInteractionRequest(this.handleInteractionRequest.bind(this))\n );\n\n this.logger.info('NotificationHandler started');\n }\n\n /**\n * 停止监听\n */\n stop(): void {\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n this.logger.info('NotificationHandler stopped');\n }\n\n private async handleSessionStart(event: SessionStartEvent): Promise<void> {\n if (event.agentType) {\n this.sessionAgentMap.set(event.sessionId, event.agentType);\n }\n\n this.logger.debug({ sessionId: event.sessionId, cwd: event.cwd }, '[NotificationHandler] handleSessionStart');\n\n const context: NotificationContext = {\n eventType: 'session:start',\n sessionId: event.sessionId,\n agentType: event.agentType,\n userId: event.userId,\n chatId: event.chatId,\n cwd: event.cwd,\n };\n\n await this.publishContext(context);\n }\n\n private async handleSessionEnd(event: SessionEndEvent): Promise<void> {\n this.sessionAgentMap.delete(event.sessionId);\n await this.publishContext({\n eventType: 'session:end',\n sessionId: event.sessionId,\n userId: event.userId,\n chatId: event.chatId,\n reason: event.reason,\n });\n }\n\n private async handleInteractionRequest(event: InteractionRequestEvent): Promise<void> {\n // Map interaction type to event type\n const eventType = event.interactionType === 'permission'\n ? 'permission:request'\n : 'question:request';\n\n // Safely extract toolName from title\n const toolName = event.content.title?.replace(/^Permission Required: /, '') ?? '';\n\n const interaction = {\n type: eventType === 'permission:request' ? 'permission' as const : 'question' as const,\n requestId: event.requestId,\n toolName,\n title: event.content.title,\n description: event.content.description,\n permission: event.content.permission ? {\n riskLevel: event.content.permission.riskLevel,\n args: event.content.permission.args,\n } : undefined,\n question: event.content.question ? {\n question: event.content.question.text,\n header: event.content.question.header,\n options: event.content.question.options?.map(o => ({\n id: o.id,\n label: o.label,\n value: o.value,\n description: o.description,\n })) ?? [],\n multiSelect: event.content.question.multiSelect,\n } : undefined,\n };\n\n const context: NotificationContext = eventType === 'permission:request'\n ? {\n eventType: 'permission:request',\n sessionId: event.sessionId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction,\n }\n : {\n eventType: 'question:request',\n sessionId: event.sessionId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction,\n };\n\n await this.publishContext(context);\n }\n\n private async handleToolFailure(event: ToolFailureEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:failure',\n sessionId: event.sessionId,\n toolName: event.toolName,\n toolInput: event.toolInput,\n error: event.error,\n });\n }\n\n /**\n * [Streaming Extension] Currently emits one event per turn (complete thinking).\n * For streaming: called multiple times per turn with incremental chunks.\n * publishContext and Feishu formatter handle both cases identically — no changes needed here.\n */\n private async handleTurnThinking(event: TurnThinkingEvent): Promise<void> {\n await this.publishContext({\n eventType: 'turn:thinking',\n sessionId: event.sessionId,\n thinking: event.thinking,\n });\n }\n\n private async handleTurnFinished(event: TurnFinishedEvent): Promise<void> {\n this.logger.debug({ sessionId: event.sessionId, cwd: event.cwd }, '[NotificationHandler] handleTurnFinished');\n\n const sessionInfo = this.getSessionInfo?.(event.sessionId);\n\n const context: NotificationContext = {\n eventType: 'turn:finished',\n sessionId: event.sessionId,\n agentType: event.agentType,\n userId: event.userId,\n chatId: event.chatId,\n cwd: event.cwd,\n reason: event.reason,\n lastAssistantMessage: event.lastAssistantMessage,\n thinking: event.thinking,\n durationMs: event.durationMs,\n usage: event.usage,\n model: sessionInfo?.model,\n summary: event.usage || event.durationMs\n ? {\n durationMs: event.durationMs,\n inputTokens: event.usage?.inputTokens,\n outputTokens: event.usage?.outputTokens,\n }\n : undefined,\n };\n\n await this.publishContext(context);\n }\n\n private async handleToolPost(event: ToolPostEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:post',\n sessionId: event.sessionId,\n toolCallId: event.toolCallId || '',\n toolName: event.toolName,\n toolInput: event.toolInput,\n });\n }\n\n private async handleToolExecuted(event: ToolExecutedEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:executed',\n sessionId: event.sessionId,\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n summary: event.summary,\n toolInput: event.toolInput as Record<string, unknown> | undefined,\n output: event.output,\n isTimeout: event.isTimeout,\n });\n }\n\n private async publishContext(context: NotificationContext): Promise<void> {\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId: context.sessionId,\n chatId: context.chatId,\n },\n 'Publishing notification'\n );\n\n const sessionId = context.sessionId;\n\n // If sessionId is missing, fall back to broadcast (backward compat)\n if (!sessionId) {\n await this.publishBroadcast(context);\n return;\n }\n\n const agentType = this.sessionAgentMap.get(sessionId)\n ?? this.getAgentTypeFromSession(sessionId)\n ?? this.getSessionAgentType?.(sessionId);\n\n if (!agentType) {\n // Fall back to broadcast if we can't determine agent\n this.logger.warn({ sessionId }, '[NotificationHandler] No agent type for session, broadcasting');\n await this.publishBroadcast(context);\n return;\n }\n\n const channelInstanceId = this.bindingService!.getBoundChannel(agentType);\n\n if (!channelInstanceId) {\n this.logger.debug({ agentType, sessionId }, '[NotificationHandler] No binding for agent, dropping event');\n return; // No channel bound to this agent — drop the event silently\n }\n\n // Parse \"telegram:abc123\" → channelType\n const channelType = channelInstanceId.split(':')[0];\n\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId,\n agentType,\n channelInstanceId,\n channelType,\n },\n '[NotificationHandler] Routing notification to bound channel'\n );\n\n await this.bus.publishOutbound({\n channel: channelType,\n chatId: sessionId,\n context,\n metadata: {\n eventType: context.eventType,\n channelInstanceId,\n sessionId,\n },\n });\n }\n\n private async publishBroadcast(context: NotificationContext): Promise<void> {\n await this.bus.publishOutbound({\n channel: 'broadcast',\n chatId: 'broadcast',\n context,\n metadata: { eventType: context.eventType },\n });\n }\n\n private getAgentTypeFromSession(sessionId: string): 'claude' | 'codex' | undefined {\n if (typeof sessionId !== 'string' || !sessionId) {\n return undefined;\n }\n // Session IDs for codex are prefixed \"codex-\"\n if (sessionId.startsWith('codex-')) {\n return 'codex';\n }\n if (sessionId.startsWith('claude-')) {\n return 'claude';\n }\n // For Claude sessions without prefix, check via sessionManager if available\n // Default to 'claude' for unknown sessions (backward compat)\n return undefined;\n }\n}\n","/**\n * Channel 适配器导出\n *\n * 导入此文件会自动注册所有 Channel 到 Registry。\n */\n\n// Telegram\nexport { TelegramChannel } from './telegram/index.js';\n\n// Logger\nexport { LoggerChannel } from './logger/index.js';\n\n// Feishu\nexport { FeishuChannel } from './feishu/index.js';\n\n// App\nexport { AppChannel } from './app/index.js';\n","import type { Logger } from 'pino';\nimport type { Context } from 'grammy';\nimport { BaseChannel, type ExtendedChannelConfig } from '../../../core/channel/base.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { OutboundMessage, InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { Button } from '../../../core/bus/types.js';\nimport type { NotificationContext } from '../../../gateway/notification-context.js';\nimport { TelegramBot } from './bot.js';\nimport { TelegramFormatter } from './formatter.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\n\nconst REQUEST_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Telegram Channel 配置\n */\nexport interface TelegramChannelConfig extends ExtendedChannelConfig {\n /** Telegram Bot Token */\n bot_token: string;\n /** 允许发送消息的用户ID列表 */\n allowed_users: string[];\n}\n\n/**\n * Telegram Channel 实现\n * 支持消息发送、按钮交互和权限申请处理\n */\n@Channel('telegram')\nexport class TelegramChannel extends BaseChannel {\n readonly name = 'telegram';\n readonly displayName = 'Telegram';\n readonly capabilities = {\n supportsButtons: true,\n supportsMarkdown: true,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private bot: TelegramBot;\n private telegramConfig: TelegramChannelConfig;\n private formatter: TelegramFormatter;\n private allowedUsers: Set<string>;\n private pendingRequests: Map<string, Map<string, number>> = new Map();\n private pendingOptions: Map<string, Array<{ id: string; label: string; value: unknown }>> = new Map();\n private pendingToolNames: Map<string, string> = new Map(); // requestId -> toolName for always_allow\n private waitingForCustomInput: Map<string, string> = new Map(); // userId -> requestId\n /** Tracks selected optionIds per user per requestId for multi-select questions */\n private pendingSelections: Map<string, Map<string, Set<string>>> = new Map();\n private unsubscribeInteractionResponse?: () => void;\n\n /**\n * 构造函数\n * @param config - Channel 配置\n * @param bus - 事件总线\n * @param logger - 日志记录器\n */\n constructor(config: TelegramChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n\n this.telegramConfig = config as TelegramChannelConfig;\n if (!this.telegramConfig.bot_token) {\n throw new Error('TelegramChannel requires bot_token in config');\n }\n\n this.bot = new TelegramBot(this.telegramConfig.bot_token, logger);\n this.formatter = new TelegramFormatter();\n this.allowedUsers = new Set(this.telegramConfig.allowed_users || []);\n }\n\n get channelInstanceId(): string {\n return getChannelInstanceId('telegram', this.telegramConfig.bot_token);\n }\n\n /**\n * 检查发送者是否有权限\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected isAllowed(senderId: string): boolean {\n // 如果没有配置允许的用户,拒绝所有\n if (this.allowedUsers.size === 0) {\n return false;\n }\n // 如果包含 \"*\",允许所有\n if (this.allowedUsers.has('*')) {\n return true;\n }\n // 检查 senderId 是否在允许列表中\n return this.allowedUsers.has(senderId);\n }\n\n /**\n * 格式化通知上下文为 Telegram HTML\n * 覆写 BaseChannel.format() 以支持 HTML 格式\n */\n format(context: NotificationContext): string {\n return this.formatter.format(context);\n }\n\n /**\n * 启动 Channel\n * 启动 Bot 并订阅权限申请事件\n */\n async start(): Promise<void> {\n await super.start();\n\n // 注册消息处理器\n this.registerMessageHandlers();\n this.logger.debug('Telegram message handlers registered');\n\n // 启动 Bot\n await this.bot.start();\n this.logger.info('Telegram bot start called');\n\n // 上报连接状态\n this.updateConnectionState('connected');\n\n // 订阅统一交互响应事件(用于清理按钮等)\n this.unsubscribeInteractionResponse = this.bus.onInteractionResponse(\n this.handleInteractionResponse.bind(this)\n );\n\n this.logger.info({ channel: this.name }, '[Channel] Started');\n }\n\n /**\n * 停止 Channel\n * 停止 Bot 并取消事件订阅\n */\n async stop(): Promise<void> {\n // 取消事件订阅\n this.unsubscribeInteractionResponse?.();\n\n // 停止 Bot\n await this.bot.stop();\n\n // 清理未决请求,避免内存泄漏\n this.pendingRequests.clear();\n this.pendingOptions.clear();\n this.pendingToolNames.clear();\n this.waitingForCustomInput.clear();\n this.pendingSelections.clear();\n\n // 上报连接状态\n this.updateConnectionState('disconnected');\n\n await super.stop();\n this.logger.info({ channel: this.name }, '[Channel] Stopped');\n }\n\n /**\n * 发送消息给所有允许的用户\n * @param message - 出站消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission/question requests - NotificationHandler routes to the bound channel via onOutbound\n if (\n (message.metadata?.eventType === 'permission:request' || message.metadata?.eventType === 'question:request') &&\n message.chatId === 'broadcast'\n ) {\n return;\n }\n\n // 优先使用 context 进行格式化,否则使用 text(向后兼容)\n let text: string;\n if (message.context) {\n text = this.format(message.context);\n this.logger.debug({ eventType: message.context.eventType }, 'Formatting Telegram message from context');\n } else if (message.text) {\n text = message.text;\n this.logger.debug({ textLength: message.text.length }, 'Using raw text for Telegram message');\n } else {\n this.logger.warn('No content to send in Telegram message');\n return;\n }\n\n // Build inline keyboard for interaction requests\n const eventType = message.metadata?.eventType;\n const ctx = message.context as Record<string, unknown> | undefined;\n const interaction = ctx?.interaction as import('../../../gateway/notification-context.js').InteractionContext | undefined;\n const requestId = ctx?.requestId as string | undefined;\n let replyMarkup: { inline_keyboard: Array<Array<{ text: string; callback_data: string }>> } | undefined;\n let isInteractionRequest = false;\n\n if ((eventType === 'permission:request' || eventType === 'question:request') && requestId && interaction) {\n isInteractionRequest = true;\n if (eventType === 'permission:request') {\n const toolName = (ctx?.toolName as string) || '';\n this.pendingToolNames.set(requestId, toolName);\n replyMarkup = {\n inline_keyboard: [\n [\n { text: '✅ Allow', callback_data: `allow:${requestId}` },\n { text: '❌ Deny', callback_data: `deny:${requestId}` },\n ],\n [{ text: '🔓 Always Allow', callback_data: `always_allow:${requestId}` }],\n ],\n };\n } else if (eventType === 'question:request' && interaction.question) {\n const question = interaction.question;\n this.pendingOptions.set(\n requestId,\n question.options.map((opt: { id: string; label: string; value: unknown }) => ({ id: opt.id, label: opt.label, value: opt.value }))\n );\n if (question.multiSelect) {\n this.pendingSelections.set(requestId, new Map());\n replyMarkup = { inline_keyboard: this.buildQuestionKeyboard(requestId, question.options, new Set()) };\n } else {\n replyMarkup = {\n inline_keyboard: question.options.map((opt: { id: string; label: string }) => [\n { text: opt.label, callback_data: `select:${requestId}:${opt.id}` },\n ]),\n };\n }\n }\n }\n\n const sentMessageIds = new Map<string, number>();\n\n for (const userId of this.allowedUsers) {\n if (userId === '*') continue;\n\n let messageId: number | undefined;\n try {\n const result = await this.bot.sendMessage(userId, text, {\n parseMode: 'HTML',\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup,\n });\n messageId = result.message_id;\n } catch (error) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n textLength: text.length,\n },\n 'Failed to send HTML message to user, falling back to plain text'\n );\n try {\n const result = await this.bot.sendMessage(userId, TelegramFormatter.stripHtml(text), {\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup,\n });\n messageId = result.message_id;\n } catch (fallbackError) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error: fallbackError,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Failed to send plain text message to user'\n );\n }\n }\n\n if (messageId !== undefined) {\n sentMessageIds.set(userId, messageId);\n this.logger.debug(\n {\n userId,\n telegramMessageId: messageId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId ?? userId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n replyToMessageId: message.replyToMessageId,\n },\n 'Telegram outbound delivered to recipient'\n );\n }\n }\n\n // Track pending requests for interaction responses\n if (isInteractionRequest && requestId) {\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Map());\n }\n for (const [uid, msgId] of sentMessageIds) {\n this.pendingRequests.get(requestId)!.set(uid, msgId);\n }\n }\n\n this.logger.info(\n {\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Telegram message sent'\n );\n }\n\n /**\n * 发送带按钮的消息\n * @param message - 出站消息\n * @param buttons - 按钮二维数组\n */\n async sendWithButtons(message: OutboundMessage, buttons: Button[][]): Promise<void> {\n // Skip broadcast question requests - NotificationHandler routes to the bound channel via onOutbound\n if (message.metadata?.eventType === 'question:request' && message.chatId === 'broadcast') {\n return;\n }\n\n // 优先使用 context 进行格式化,否则使用 text(向后兼容)\n let text: string;\n if (message.context) {\n text = this.format(message.context);\n } else if (message.text) {\n text = message.text;\n } else {\n this.logger.warn('No content to send in Telegram message with buttons');\n return;\n }\n\n // 构建内联键盘\n const inlineKeyboard = buttons.map((row) =>\n row.map((btn) => ({\n text: btn.text,\n callback_data: btn.data,\n }))\n );\n\n const isInteractionRequest = buttons.some((row) =>\n row.some((btn) => btn.data.startsWith('allow:') || btn.data.startsWith('deny:') || btn.data.startsWith('select:'))\n );\n const sentMessageIds = new Map<string, number>();\n\n // 发送给所有允许的用户\n for (const userId of this.allowedUsers) {\n if (userId === '*') continue;\n\n let messageId: number | undefined;\n try {\n const result = await this.bot.sendMessage(userId, text, {\n parseMode: 'HTML',\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup: { inline_keyboard: inlineKeyboard },\n });\n messageId = result.message_id;\n } catch (error) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n textLength: text.length,\n },\n 'Failed to send HTML message with buttons to user, falling back to plain text'\n );\n try {\n const result = await this.bot.sendMessage(userId, TelegramFormatter.stripHtml(text), {\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n replyMarkup: { inline_keyboard: inlineKeyboard },\n });\n messageId = result.message_id;\n } catch (fallbackError) {\n this.logger.warn(\n {\n userId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId,\n channelInstanceId: this.channelInstanceId,\n error: fallbackError,\n eventType: message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Failed to send plain text message with buttons to user'\n );\n }\n }\n\n if (messageId !== undefined) {\n sentMessageIds.set(userId, messageId);\n this.logger.debug(\n {\n userId,\n telegramMessageId: messageId,\n logicalChatId: message.chatId,\n resolvedChatId: message.metadata?.resolvedChatId ?? userId,\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType ?? message.metadata?.eventType,\n sessionId: message.metadata?.sessionId,\n },\n 'Telegram outbound with buttons delivered to recipient'\n );\n }\n }\n\n // 跟踪交互请求相关的消息 ID(用于后续移除按钮)\n if (isInteractionRequest) {\n for (const row of buttons) {\n for (const btn of row) {\n if (btn.data.startsWith('allow:') || btn.data.startsWith('deny:') || btn.data.startsWith('select:')) {\n const requestId = btn.data.split(':')[1];\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Map());\n }\n for (const [uid, msgId] of sentMessageIds) {\n this.pendingRequests.get(requestId)!.set(uid, msgId);\n }\n }\n }\n }\n }\n }\n\n /**\n * 处理统一交互响应事件(清理按钮等)\n * @param event - 交互响应事件\n */\n private async handleInteractionResponse(event: InteractionResponseEvent): Promise<void> {\n const userMessages = this.pendingRequests.get(event.requestId);\n if (userMessages) {\n for (const [userId, messageId] of userMessages) {\n try {\n await this.bot.api.editMessageReplyMarkup(userId, messageId, { reply_markup: { inline_keyboard: [] } });\n } catch (error) {\n this.logger.debug(\n { userId, messageId, error: error instanceof Error ? error.message : String(error) },\n 'Failed to remove buttons'\n );\n }\n }\n }\n // 清理已处理的请求记录\n this.pendingRequests.delete(event.requestId);\n this.pendingOptions.delete(event.requestId);\n this.pendingSelections.delete(event.requestId);\n }\n\n /**\n * 处理按钮回调\n * @param ctx - grammy Context\n */\n private async handleCallbackQuery(ctx: Context): Promise<void> {\n const data = ctx.update.callback_query?.data;\n const userId = ctx.from?.id.toString();\n\n if (!data || !userId) {\n this.logger.warn('Invalid callback query: missing data or userId');\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n\n this.logger.debug({ userId, data }, 'Received callback query');\n\n // 解析回调数据(仅在第一个冒号处分割,防止 requestId 含冒号被错误解析)\n const colonIndex = data.indexOf(':');\n if (colonIndex === -1) {\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n const action = data.slice(0, colonIndex);\n const rest = data.slice(colonIndex + 1);\n\n if (!action || !['allow', 'deny', 'always_allow', 'select', 'confirm'].includes(action)) {\n await ctx.answerCallbackQuery({ text: 'Invalid action' });\n return;\n }\n\n // 处理选择动作(question request)\n if (action === 'select') {\n const secondColonIndex = rest.indexOf(':');\n if (secondColonIndex === -1) {\n await ctx.answerCallbackQuery({ text: 'Invalid request format' });\n return;\n }\n const requestId = rest.slice(0, secondColonIndex);\n const optionId = rest.slice(secondColonIndex + 1);\n\n if (!optionId) {\n await ctx.answerCallbackQuery({ text: 'Invalid option ID' });\n return;\n }\n\n // 校验 requestId 格式\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 验证用户是否有权限响应此请求\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n // Check if this is a multi-select request\n const isMultiSelect = this.pendingSelections.has(requestId);\n\n if (isMultiSelect) {\n // Multi-select: toggle option, update buttons, do NOT submit yet\n let userSelections = this.pendingSelections.get(requestId)!.get(userId);\n if (!userSelections) {\n userSelections = new Set();\n this.pendingSelections.get(requestId)!.set(userId, userSelections);\n }\n\n // Toggle this option\n if (userSelections.has(optionId)) {\n userSelections.delete(optionId);\n } else {\n userSelections.add(optionId);\n }\n\n // 1. Acknowledge immediately — removes loading spinner right away\n const options = this.pendingOptions.get(requestId);\n const selectedLabels = Array.from(userSelections).map((id) => {\n const opt = options?.find((o) => o.id === id);\n return opt?.label ?? id;\n });\n await ctx.answerCallbackQuery({\n text: selectedLabels.length > 0 ? `Selected: ${selectedLabels.join(', ')}` : 'No selection',\n });\n\n // 2. Then update UI asynchronously (fire-and-forget)\n const updatedKeyboard = this.buildQuestionKeyboard(requestId, options ?? [], userSelections);\n const chatId = ctx.callbackQuery?.message?.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n this.bot.api.editMessageReplyMarkup(chatId, messageId, {\n reply_markup: { inline_keyboard: updatedKeyboard },\n }).catch((err) => {\n this.logger.warn({ err, requestId, optionId }, 'Failed to update multi-select keyboard');\n });\n }\n return;\n }\n\n // Single-select: submit immediately (existing behavior)\n // 查找选项值\n const options = this.pendingOptions.get(requestId);\n const selectedOption = options?.find(opt => opt.id === optionId);\n if (!selectedOption) {\n this.logger.warn({ userId, requestId, optionId }, 'Selected option not found');\n await ctx.answerCallbackQuery({ text: 'Invalid option selected' });\n return;\n }\n\n // 发布交互响应事件,返回选项值\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues: [selectedOption.value],\n },\n reason: `User selected option ${optionId} via Telegram`,\n });\n\n // 立即为当前用户移除按钮,提供即时视觉反馈\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch {\n // 忽略失败\n }\n\n // 回复用户\n await ctx.answerCallbackQuery({\n text: 'Selection confirmed',\n });\n\n this.logger.info({ requestId, userId, action: 'select', optionId }, '[Channel] User response received');\n return;\n }\n\n // 处理确认动作(multi-select Done 按钮)\n if (action === 'confirm') {\n const requestId = rest;\n\n if (!requestId) {\n await ctx.answerCallbackQuery({ text: 'Invalid request' });\n return;\n }\n\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to confirm request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n const userSelections = this.pendingSelections.get(requestId)?.get(userId);\n if (!userSelections || userSelections.size === 0) {\n await ctx.answerCallbackQuery({ text: 'No options selected' });\n return;\n }\n\n // Build selectedValues from all selected optionIds\n const options = this.pendingOptions.get(requestId);\n const selectedValues = Array.from(userSelections).map(id => {\n const opt = options?.find(o => o.id === id);\n return opt?.value;\n }).filter(v => v !== undefined);\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues,\n },\n reason: `User confirmed multi-select via Telegram: ${Array.from(userSelections).join(', ')}`,\n });\n\n // Cleanup\n const selectionMap = this.pendingSelections.get(requestId);\n if (selectionMap) {\n selectionMap.delete(userId);\n if (selectionMap.size === 0) {\n this.pendingSelections.delete(requestId);\n }\n }\n\n // Remove buttons\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch { /* ignore */ }\n\n await ctx.answerCallbackQuery({ text: `Confirmed: ${selectedValues.length} option(s)` });\n this.logger.info({ requestId, userId, selectedValues }, '[Channel] Multi-select confirmed');\n return;\n }\n\n // 处理权限决策动作\n const requestId = rest;\n\n if (!requestId) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 校验 requestId 格式,防止注入或畸形数据\n if (!REQUEST_ID_REGEX.test(requestId)) {\n await ctx.answerCallbackQuery({ text: 'Invalid request ID' });\n return;\n }\n\n // 验证用户是否有权限响应此请求\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n await ctx.answerCallbackQuery({ text: 'You cannot respond to this request' });\n return;\n }\n\n // Build response with permission updates for always_allow\n const isAlwaysAllow = action === 'always_allow';\n const permissionUpdates = isAlwaysAllow ? [{\n type: 'addRules' as const,\n rules: [{ toolName: this.pendingToolNames.get(requestId) ?? '*', ruleContent: '*' }],\n behavior: 'allow' as const,\n destination: 'localSettings' as const, // Project's settings.local.json\n }] : undefined;\n\n // 发布交互响应事件\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: isAlwaysAllow ? 'allow' : (action as 'allow' | 'deny'),\n ...(permissionUpdates && { permissionUpdates }),\n },\n reason: `User clicked ${action} button via Telegram`,\n });\n\n // Cleanup pending tool name for all permission responses\n this.pendingToolNames.delete(requestId);\n\n // 立即为当前用户移除按钮,提供即时视觉反馈\n try {\n const chatId = ctx.chat?.id;\n const messageId = ctx.callbackQuery?.message?.message_id;\n if (chatId && messageId) {\n await this.bot.api.editMessageReplyMarkup(chatId, messageId, { reply_markup: { inline_keyboard: [] } });\n }\n } catch {\n // 忽略失败,handlePermissionDecision 会负责其他用户及兜底\n }\n\n // 回复用户\n await ctx.answerCallbackQuery({\n text: `Permission ${action === 'allow' ? 'granted' : action === 'always_allow' ? 'always allowed' : 'denied'}`,\n });\n\n this.logger.info({ requestId, userId, action }, '[Channel] User response received');\n }\n\n /**\n * 处理文本消息\n * @param ctx - grammy Context\n */\n private async handleTextMessage(ctx: Context): Promise<void> {\n const userId = ctx.from?.id.toString();\n const username = ctx.from?.username;\n const text = ctx.message?.text;\n const chatId = ctx.chat?.id.toString();\n const messageId = ctx.message?.message_id.toString();\n\n if (!userId || !text || !chatId || !messageId) {\n this.logger.warn('Invalid message: missing required fields');\n return;\n }\n\n this.logger.info(\n {\n userId,\n username,\n chatId,\n messageId,\n channelInstanceId: this.channelInstanceId,\n textLength: text.length,\n textPreview: text.slice(0, 120),\n },\n 'Telegram text message received'\n );\n\n // 检查用户权限\n if (!this.isAllowed(userId)) {\n this.logger.warn({ userId }, 'Telegram message from unauthorized user ignored');\n await ctx.reply('⛔ You are not authorized to use this bot.');\n return;\n }\n\n // 检查是否正在等待自定义输入\n const requestId = this.waitingForCustomInput.get(userId);\n if (requestId && text) {\n // 用户发送了自定义输入,提交作为答案\n this.waitingForCustomInput.delete(userId);\n\n // 验证请求仍然有效\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest || !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'Request no longer valid for custom input');\n return;\n }\n\n // 发布交互响应,使用用户输入的文本\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'input',\n customInput: text, // 使用用户输入的文本作为自定义答案\n },\n reason: `User provided custom input via Telegram`,\n });\n\n this.logger.info({ requestId, userId, action: 'input', customInput: text }, '[Channel] User response received');\n return;\n }\n\n // 转发消息到 EventBus\n this.receiveMessage(chatId, messageId, text, {\n id: userId,\n username,\n firstName: ctx.from?.first_name,\n lastName: ctx.from?.last_name,\n });\n // Note: 不再发送固定确认消息,命令响应通过 CommandHandler 发送\n }\n\n /**\n * Build inline keyboard for multi-select question with selection state\n */\n private buildQuestionKeyboard(\n requestId: string,\n options: Array<{ id: string; label: string; value: unknown }>,\n selectedIds: Set<string>\n ): Array<Array<{ text: string; callback_data: string }>> {\n const optionRows = options.map((opt) => [\n {\n text: selectedIds.has(opt.id) ? `✅ ${opt.label}` : opt.label,\n callback_data: `select:${requestId}:${opt.id}`,\n },\n ]);\n const doneRow = [[{ text: '✅ Done', callback_data: `confirm:${requestId}` }]];\n return [...optionRows, ...doneRow];\n }\n\n /**\n * 注册消息处理器\n */\n private registerMessageHandlers(): void {\n // 注册回调查询处理器\n this.bot.onCallbackQuery(this.handleCallbackQuery.bind(this));\n\n // 注册文本消息处理器\n this.bot.onTextMessage(this.handleTextMessage.bind(this));\n }\n}\n\nexport { TelegramBot, TelegramFormatter };\n","import type { Logger } from 'pino';\nimport type { EventBus } from '../bus/index.js';\nimport type { Button } from '../bus/types.js';\nimport type { OutboundMessage } from '../bus/events.js';\nimport type { Channel, ChannelCapabilities, ChannelConfig, ConnectionHealth } from './types.js';\nimport type { NotificationContext } from '../../gateway/notification-context.js';\n\n/**\n * Channel 配置扩展接口\n */\nexport interface ExtendedChannelConfig extends ChannelConfig {\n // 权限控制由具体 Channel 实现自行管理\n}\n\n/**\n * Channel 抽象基类\n * 封装通用逻辑,具体 Channel 实现需要继承此类\n */\nexport abstract class BaseChannel implements Channel {\n /** Channel 唯一标识名 */\n abstract readonly name: string;\n\n /** Channel 显示名称 */\n abstract readonly displayName: string;\n\n /** Channel 能力声明 */\n abstract readonly capabilities: ChannelCapabilities;\n\n /** Channel 实例 ID,用于 1:1 绑定路由 */\n abstract readonly channelInstanceId: string;\n\n /**\n * 是否支持流式消息输出\n * 子类可覆盖此属性声明支持流式\n * 参考 nanobot BaseChannel.supports_streaming\n */\n readonly supportsStreaming: boolean = false;\n\n /** Channel 运行状态 */\n private _isRunning: boolean = false;\n\n /** Channel 配置 */\n protected config: ExtendedChannelConfig;\n\n /** 事件总线 */\n protected bus: EventBus;\n\n /** 日志记录器 */\n protected logger: Logger;\n\n /**\n * 连接健康状态\n * 子类需要维护自己的连接状态\n */\n protected connectionHealth: ConnectionHealth = {\n state: 'unknown',\n reconnectCount: 0,\n };\n\n /**\n * 获取连接健康状态\n */\n getConnectionHealth(): ConnectionHealth {\n return { ...this.connectionHealth };\n }\n\n /**\n * 更新连接状态(子类调用)\n * @param state - 新状态\n * @param errorMessage - 错误信息(可选)\n */\n protected updateConnectionState(\n state: ConnectionHealth['state'],\n errorMessage?: string\n ): void {\n this.connectionHealth.state = state;\n this.connectionHealth.lastPingTime = new Date();\n if (errorMessage) {\n this.connectionHealth.errorMessage = errorMessage;\n }\n if (state === 'connected') {\n this.connectionHealth.reconnectCount = 0;\n }\n this.logger.debug(\n { channel: this.name, state, errorMessage },\n 'Connection state updated'\n );\n }\n\n /**\n * 记录重连(子类调用)\n */\n protected recordReconnectAttempt(): void {\n this.connectionHealth.reconnectCount++;\n this.logger.debug(\n { channel: this.name, attempt: this.connectionHealth.reconnectCount },\n 'Reconnect attempt recorded'\n );\n }\n\n /**\n * 获取 Channel 运行状态\n */\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n /**\n * 流式消息发送\n * 用于打字机效果的逐字/逐句输出\n * 默认空实现,支持流式的子类应覆盖此方法\n * 参考 nanobot base.py send_delta\n *\n * @param chatId - 聊天ID\n * @param delta - 新增的文本片段\n * @param metadata - 可选元数据,包含 _streamId 和 _streamEnd\n */\n async sendDelta(\n chatId: string,\n delta: string,\n metadata?: {\n _streamId?: string;\n _streamEnd?: boolean;\n }\n ): Promise<void> {\n // 默认空实现,子类选择性覆盖\n }\n\n /**\n * 构造函数\n * @param config - Channel 配置\n * @param bus - 事件总线实例\n * @param logger - 日志记录器\n */\n constructor(config: ExtendedChannelConfig, bus: EventBus, logger: Logger) {\n this.config = config;\n this.bus = bus;\n this.logger = logger;\n }\n\n /**\n * 启动 Channel\n * 子类应该重写此方法并在 super.start() 后添加自定义逻辑\n */\n async start(): Promise<void> {\n this.logger.info({ channel: this.name }, 'Starting channel');\n this._isRunning = true;\n }\n\n /**\n * 停止 Channel\n * 子类应该重写此方法并在 super.stop() 后添加自定义逻辑\n */\n async stop(): Promise<void> {\n this.logger.info({ channel: this.name }, 'Stopping channel');\n this._isRunning = false;\n }\n\n /**\n * 发送消息\n * 子类必须实现此方法\n * @param message - 出站消息\n */\n abstract send(message: OutboundMessage): Promise<void>;\n\n /**\n * 发送带按钮的消息\n * 默认实现会忽略按钮,仅发送文本\n * 支持按钮的 Channel 应该重写此方法\n * @param message - 出站消息\n * @param buttons - 按钮二维数组\n */\n async sendWithButtons(message: OutboundMessage, buttons: Button[][]): Promise<void> {\n this.logger.debug(\n { channel: this.name, buttonRows: buttons.length },\n 'Buttons not supported, sending text only'\n );\n // 默认实现忽略按钮,只发送文本\n await this.send(message);\n }\n\n /**\n * 接收消息并转发到 EventBus\n * 子类在收到外部消息时应该调用此方法\n * @param chatId - 聊天ID\n * @param messageId - 消息ID\n * @param text - 消息文本\n * @param sender - 发送者信息\n */\n protected receiveMessage(\n chatId: string,\n messageId: string,\n text: string,\n sender: {\n id: string;\n username?: string;\n firstName?: string;\n lastName?: string;\n }\n ): void {\n // 检查发送者权限\n if (!this.isAllowed(sender.id)) {\n this.logger.warn(\n { channel: this.name, senderId: sender.id, chatId },\n 'Message from unauthorized sender ignored'\n );\n return;\n }\n\n this.logger.debug(\n {\n channel: this.name,\n channelInstanceId: this.channelInstanceId,\n chatId,\n messageId,\n senderId: sender.id,\n textPreview: text.slice(0, 120),\n },\n 'Receiving message and forwarding to bus'\n );\n\n // 转发到 EventBus\n this.bus.publishInbound({\n channel: this.name,\n channelInstanceId: this.channelInstanceId,\n chatId,\n messageId,\n text,\n sender,\n });\n }\n\n /**\n * 检查发送者是否有权限\n * 具体权限控制逻辑由子类实现\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected abstract isAllowed(senderId: string): boolean;\n\n /**\n * 检查是否应该处理某类通知\n * @param eventType - 事件类型 (session_start, session_end, permission_request, finished, error)\n * @returns 是否应该处理\n */\n shouldNotify(eventType: string): boolean {\n const notify_types = this.config.notify_types;\n\n // 未配置 notify_types 则不接收任何通知\n if (!notify_types || notify_types.length === 0) {\n return false;\n }\n\n // \"*\" 表示接收所有通知\n if (notify_types.includes('*')) {\n return true;\n }\n\n return notify_types.includes(eventType);\n }\n\n /**\n * 格式化通知上下文为 Channel 特定格式\n * 默认实现返回纯文本,子类可覆写以支持 HTML、Post 等格式\n * @param context - 通知上下文\n * @returns 格式化后的内容(字符串或特定类型)\n */\n format(context: NotificationContext): string | unknown {\n const lines: string[] = [];\n\n switch (context.eventType) {\n case 'permission:request':\n lines.push('🔐 Permission Request');\n lines.push(`Session: ${context.sessionId}`);\n if (context.toolName) {\n lines.push(`Tool: ${context.toolName}`);\n }\n if (context.toolInput && Object.keys(context.toolInput as Record<string, unknown> || {}).length > 0) {\n lines.push('');\n lines.push('Args:');\n lines.push(JSON.stringify(context.toolInput, null, 2));\n }\n break;\n\n case 'turn:finished':\n lines.push('✅ Task Completed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.durationMs !== undefined) {\n const seconds = (context.durationMs / 1000).toFixed(1);\n lines.push(`Duration: ${seconds}s`);\n }\n if (context.usage?.inputTokens !== undefined && context.usage?.outputTokens !== undefined) {\n lines.push(`Tokens: in ${context.usage.inputTokens} / out ${context.usage.outputTokens}`);\n }\n if (context.lastAssistantMessage) {\n lines.push('');\n lines.push('Result:');\n lines.push(context.lastAssistantMessage);\n }\n break;\n\n case 'session:start':\n lines.push('🟢 Session Started');\n lines.push(`Session: ${context.sessionId}`);\n if (context.userId) {\n lines.push(`User: ${context.userId.slice(0, 16)}`);\n }\n break;\n\n case 'session:end':\n lines.push('🔴 Session Ended');\n lines.push(`Session: ${context.sessionId}`);\n break;\n\n case 'tool:failure':\n lines.push('⚠️ Tool Failed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.toolName) {\n lines.push(`Tool: ${context.toolName}`);\n }\n if (context.error) {\n lines.push(`Error: ${context.error}`);\n }\n break;\n\n case 'question:request':\n lines.push('❓ Question');\n lines.push(`Session: ${context.sessionId}`);\n if (context.interaction?.question) {\n const q = context.interaction.question;\n if (q.header) {\n lines.push(`Header: ${q.header}`);\n }\n lines.push(`Question: ${q.question}`);\n if (q.options && q.options.length > 0) {\n lines.push('');\n lines.push('Options:');\n q.options.forEach((opt: { label: string; description?: string }, idx: number) => {\n lines.push(` ${idx + 1}. ${opt.label}${opt.description ? ` - ${opt.description}` : ''}`);\n });\n }\n }\n break;\n\n default:\n lines.push(`Event: ${(context as NotificationContext).eventType}`);\n lines.push(`Session: ${context.sessionId}`);\n }\n\n return lines.join('\\n');\n }\n}\n","import { Bot, type Context, type Api } from 'grammy';\nimport type { Logger } from 'pino';\n\n/**\n * 发送消息选项\n */\nexport interface SendMessageOptions {\n /** 解析模式 */\n parseMode?: 'Markdown' | 'MarkdownV2' | 'HTML';\n /** 回复消息ID */\n replyToMessageId?: number;\n /** 内联键盘 */\n replyMarkup?: {\n inline_keyboard: Array<\n Array<{\n text: string;\n callback_data: string;\n }>\n >;\n };\n}\n\n/**\n * Telegram Bot 包装类\n * 封装 grammy Bot 实例,提供重试机制和错误处理\n */\nexport class TelegramBot {\n /** grammy Bot 实例 */\n readonly bot: Bot;\n\n private logger: Logger;\n private isRunning: boolean = false;\n\n /**\n * 构造函数\n * @param token - Telegram Bot Token\n * @param logger - 日志记录器\n */\n constructor(token: string, logger: Logger) {\n this.bot = new Bot(token);\n this.logger = logger;\n\n // 设置错误处理\n this.bot.catch((err) => {\n this.logger.error({ error: err }, 'Telegram bot unhandled error');\n });\n }\n\n /**\n * 启动 Bot(带重试机制)\n * @param maxAttempts - 最大重试次数,默认 3\n * @param initialIntervalMs - 初始重试间隔(毫秒),默认 1000\n * @param startTimeoutMs - 启动超时时间(毫秒),默认 5000\n */\n async start(\n maxAttempts: number = 3,\n initialIntervalMs: number = 1000,\n startTimeoutMs: number = 5000\n ): Promise<void> {\n if (this.isRunning) {\n this.logger.warn('Bot is already running');\n return;\n }\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await this.startWithTimeout(startTimeoutMs);\n this.isRunning = true;\n this.logger.info('Telegram bot started successfully');\n return;\n } catch (error) {\n if (attempt === maxAttempts) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(\n { attempts: maxAttempts, error: errorMessage },\n 'Telegram bot failed to start after all attempts'\n );\n throw new Error(`Failed to start Telegram bot after ${maxAttempts} attempts: ${errorMessage}`);\n }\n const interval = initialIntervalMs * Math.pow(2, attempt - 1);\n this.logger.warn(\n { attempt, nextRetryIn: interval },\n `Telegram bot start attempt ${attempt} failed, retrying...`\n );\n await this.sleep(interval);\n }\n }\n }\n\n /**\n * 停止 Bot\n */\n async stop(): Promise<void> {\n if (!this.isRunning) {\n this.logger.warn('Bot is not running');\n return;\n }\n\n try {\n await this.bot.stop();\n this.isRunning = false;\n this.logger.info('Telegram bot stopped');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ error: errorMessage }, 'Error stopping Telegram bot');\n throw error;\n }\n }\n\n /**\n * 发送消息\n * @param chatId - 聊天 ID\n * @param text - 消息文本\n * @param options - 发送选项\n */\n async sendMessage(\n chatId: string | number,\n text: string,\n options?: SendMessageOptions\n ): Promise<{ message_id: number }> {\n try {\n const result = await this.bot.api.sendMessage(chatId, text, {\n parse_mode: options?.parseMode,\n reply_to_message_id: options?.replyToMessageId,\n reply_markup: options?.replyMarkup,\n });\n this.logger.debug({ chatId }, 'Message sent successfully');\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ chatId, error: errorMessage }, 'Failed to send message');\n throw error;\n }\n }\n\n /**\n * 获取 grammy Bot 实例\n * 用于注册事件处理器\n */\n get instance(): Bot {\n return this.bot;\n }\n\n /**\n * 获取 Bot API\n */\n get api(): Api {\n return this.bot.api;\n }\n\n /**\n * 获取 Bot 运行状态\n */\n get running(): boolean {\n return this.isRunning;\n }\n\n /**\n * 注册回调查询处理器\n * @param handler - 处理器函数\n */\n onCallbackQuery(handler: (ctx: Context) => Promise<void>): void {\n this.bot.on('callback_query:data', handler);\n }\n\n /**\n * 注册文本消息处理器\n * @param handler - 处理器函数\n */\n onTextMessage(handler: (ctx: Context) => Promise<void>): void {\n this.bot.on('message:text', handler);\n }\n\n /**\n * 带超时启动 Bot\n * @param timeoutMs - 超时时间(毫秒)\n */\n private async startWithTimeout(timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Bot start timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.bot\n .start()\n .then(() => {\n clearTimeout(timeout);\n resolve();\n })\n .catch((error) => {\n clearTimeout(timeout);\n reject(error);\n });\n });\n }\n\n /**\n * 睡眠指定时间\n * @param ms - 毫秒\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import type { NotificationContext } from '../../../gateway/notification-context.js';\nimport { getEventTitle } from '../../../gateway/notification-context.js';\nimport { formatDuration, formatTokenCount } from '../../../shared/format.js';\n\n/**\n * Telegram HTML 格式化工具类\n * 生成 Telegram 支持的 HTML parse_mode 内容\n * 只需转义基础 HTML 字符: & < >\n */\nexport class TelegramFormatter {\n /**\n * 转义 HTML 特殊字符\n * @param text - 原始文本\n * @returns 转义后的文本\n */\n escape(text: string): string {\n return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n /**\n * 格式化代码块\n * @param text - 代码内容\n * @param language - 可选的编程语言\n * @returns 格式化后的代码块\n */\n code(text: string, language?: string): string {\n const escaped = this.escape(text);\n if (language) {\n return `<pre><code class=\"language-${this.escape(language)}\">${escaped}</code></pre>`;\n }\n return `<pre><code>${escaped}</code></pre>`;\n }\n\n /**\n * 格式化内联代码\n * @param text - 代码内容\n * @returns 格式化后的内联代码\n */\n inlineCode(text: string): string {\n return `<code>${this.escape(text ?? '')}</code>`;\n }\n\n /**\n * 截断过长的文本\n * @param text - 原始文本\n * @param maxLength - 最大长度\n * @returns 截断后的文本\n */\n private truncate(text: string, maxLength = 3500): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength) + '...';\n }\n\n /**\n * 格式化权限申请消息\n */\n formatPermissionRequest(\n title: string,\n toolName: string,\n toolInput: Record<string, unknown> | undefined,\n cwd?: string\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n `<b>Tool:</b> ${this.escape(toolName)}`,\n ];\n if (cwd) {\n lines.push(`<b>Working Dir:</b> ${this.inlineCode(cwd)}`);\n }\n if (toolInput && Object.keys(toolInput).length > 0) {\n lines.push('', '<b>Args:</b>');\n lines.push(this.code(JSON.stringify(toolInput, null, 2), 'json'));\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化问题申请消息\n */\n formatQuestionRequest(\n title: string,\n header: string | undefined,\n question: string,\n options: Array<{ label: string; description?: string }>\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n ];\n if (header) {\n lines.push(`<b>${this.escape(header)}</b>`, '');\n }\n lines.push(this.escape(question));\n if (options.length > 0) {\n lines.push('', '<b>Options:</b>');\n options.forEach((opt, idx) => {\n const label = this.escape(opt.label);\n const desc = opt.description ? ` - ${this.escape(opt.description)}` : '';\n lines.push(`${idx + 1}. <code>${label}</code>${desc}`);\n });\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化通知上下文(统一入口)\n */\n format(context: NotificationContext): string {\n const title = getEventTitle(context.eventType);\n switch (context.eventType) {\n case 'permission:request':\n return this.formatPermissionRequest(\n title,\n context.toolName ?? 'Unknown',\n context.toolInput,\n undefined\n );\n\n case 'question:request':\n if (context.interaction?.question) {\n const q = context.interaction.question;\n return this.formatQuestionRequest(\n title,\n q.header,\n q.question,\n q.options\n );\n }\n return this.formatQuestionRequest(\n title,\n undefined,\n context.interaction?.description || '',\n []\n );\n\n case 'turn:finished':\n return this.formatFinished(\n title,\n context.model || context.agentType,\n context.durationMs,\n context.usage?.inputTokens,\n context.usage?.outputTokens,\n context.lastAssistantMessage\n );\n\n case 'session:start': {\n let startMsg = `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n if (context.cwd) {\n startMsg += `\\n<b>WorkDir:</b> ${this.escape(context.cwd)}`;\n }\n return startMsg;\n }\n\n case 'session:end':\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'tool:failure':\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName ?? 'Unknown')}`;\n\n case 'tool:executed':\n return this.formatToolExecuted(context);\n\n default:\n return `${this.escape(title)}\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n }\n }\n\n /**\n * 格式化结果通知消息\n */\n formatFinished(\n title: string,\n model: string | undefined,\n durationMs?: number,\n inputTokens?: number,\n outputTokens?: number,\n result?: string\n ): string {\n const lines = [\n `${this.escape(title)}`,\n '',\n ];\n if (model) {\n lines.push(`<b>Model:</b> ${this.escape(model)}`);\n }\n if (durationMs !== undefined) {\n lines.push(`<b>Duration:</b> ${this.escape(formatDuration(durationMs))}`);\n }\n if (inputTokens !== undefined && outputTokens !== undefined) {\n lines.push(`<b>Tokens:</b> ${formatTokenCount(inputTokens)}↑ / ${formatTokenCount(outputTokens)}↓`);\n }\n if (result) {\n lines.push('', '<b>Result:</b>');\n // Try to parse as JSON, if fails treat as plain text\n try {\n const parsed = JSON.parse(result);\n lines.push(this.code(JSON.stringify(parsed, null, 2), 'json'));\n } catch {\n lines.push(this.escape(result));\n }\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 移除 HTML 标签,用于纯文本 fallback\n * @param text - 含 HTML 标签的文本\n * @returns 纯文本\n */\n static stripHtml(text: string): string {\n return text.replace(/<[^>]*>/g, '');\n }\n\n /**\n * 根据上下文获取标题\n */\n getTitleForContext(context: NotificationContext): string {\n return getEventTitle(context.eventType);\n }\n\n /**\n * 格式化 turn:finished 事件\n */\n private formatTurnFinished(context: NotificationContext): string {\n const lines = [\n '✅ <b>Task Completed</b>',\n '',\n `<b>Session:</b> ${this.escape(context.sessionId)}`,\n ];\n const c = context as unknown as Record<string, unknown>;\n if (c.durationMs !== undefined) {\n const seconds = ((c.durationMs as number) / 1000).toFixed(1);\n lines.push(`<b>Duration:</b> ${this.escape(seconds)}s`);\n }\n if (c.lastAssistantMessage) {\n lines.push('', this.escape(c.lastAssistantMessage as string));\n }\n return this.truncate(lines.join('\\n'));\n }\n\n /**\n * 格式化 tool:executed 事件\n */\n private formatToolExecuted(context: NotificationContext): string {\n const title = getEventTitle(context.eventType);\n const c = context as unknown as Record<string, unknown>;\n const lines = [\n `${this.escape(title)}`,\n '',\n `<b>Session:</b> ${this.escape(context.sessionId)}`,\n `<b>Tool:</b> ${this.escape((c.toolName as string) || 'Unknown')}`,\n ];\n if (c.summary) {\n lines.push('', this.escape(c.summary as string));\n }\n return this.truncate(lines.join('\\n'));\n }\n}\n\n/**\n * 默认格式化器实例\n */\nexport const formatter = new TelegramFormatter();\n","import type { SessionSummary } from '../core/session-context.js';\nimport type { ToolInfo } from '../core/adapter/types.js';\nimport { t } from '../i18n/index.js';\n\n/**\n * Unified interaction context for permission/question events.\n * Flattened shape — no `.content` wrapper.\n */\nexport interface InteractionContext {\n type: 'permission' | 'question';\n requestId: string;\n toolName: string;\n title: string;\n description?: string;\n permission?: {\n riskLevel: 'low' | 'medium' | 'high';\n args: Record<string, unknown>;\n };\n question?: {\n question: string;\n header?: string;\n options: Array<{ id: string; label: string; value: unknown; description?: string }>;\n multiSelect: boolean;\n };\n}\n\n/**\n * Unified NotificationContext event types\n * All channel formatters should handle these consistently\n */\nexport type NotificationEventType =\n | 'session:start' | 'session:end'\n | 'turn:finished' | 'turn:thinking'\n | 'tool:post' | 'tool:executed' | 'tool:failure'\n | 'permission:request' | 'permission:response'\n | 'question:request' | 'question:response'\n | 'agent:message'\n | 'error';\n\n/**\n * 获取统一的事件标题(emoji + 多语言)\n * 所有 Channel Formatter 应使用此函数以保证标题一致性\n */\nexport function getEventTitle(eventType: NotificationEventType): string {\n switch (eventType) {\n case 'session:start':\n return t('eventTitles.sessionStart');\n case 'session:end':\n return t('eventTitles.sessionEnd');\n case 'turn:finished':\n return t('eventTitles.turnFinished');\n case 'turn:thinking':\n return t('eventTitles.turnThinking');\n case 'tool:post':\n return t('eventTitles.toolPost');\n case 'tool:executed':\n return t('eventTitles.toolExecuted');\n case 'tool:failure':\n return t('eventTitles.toolFailure');\n case 'permission:request':\n return t('eventTitles.permissionRequest');\n case 'permission:response':\n return t('eventTitles.permissionResponse');\n case 'question:request':\n return t('eventTitles.questionRequest');\n case 'question:response':\n return t('eventTitles.questionResponse');\n case 'agent:message':\n return t('eventTitles.agentMessage');\n case 'error':\n return t('eventTitles.error');\n default:\n return t('eventTitles.fallback');\n }\n}\n\n// ==========================================\n// Base type — common fields for all events\n// ==========================================\ninterface NotificationContextBase {\n eventType: NotificationEventType;\n sessionId: string;\n agentType?: 'claude' | 'codex';\n userId?: string;\n chatId?: string;\n cwd?: string;\n timestamp?: string;\n}\n\n// ==========================================\n// Event-specific context types\n// ==========================================\n\nexport interface SessionStartContext extends NotificationContextBase {\n eventType: 'session:start';\n}\n\nexport interface SessionEndContext extends NotificationContextBase {\n eventType: 'session:end';\n reason?: string;\n}\n\nexport interface TurnFinishedContext extends NotificationContextBase {\n eventType: 'turn:finished';\n lastAssistantMessage?: string;\n thinking?: string;\n durationMs?: number;\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadInputTokens?: number;\n cacheCreationInputTokens?: number;\n };\n summary?: SessionSummary;\n tools?: ToolInfo[];\n reason?: string;\n model?: string;\n}\n\nexport interface TurnThinkingContext extends NotificationContextBase {\n eventType: 'turn:thinking';\n thinking: string;\n}\n\nexport interface ToolPostContext extends NotificationContextBase {\n eventType: 'tool:post';\n toolCallId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n}\n\nexport interface ToolExecutedContext extends NotificationContextBase {\n eventType: 'tool:executed';\n toolCallId: string;\n toolName: string;\n summary: string;\n toolInput?: Record<string, unknown>;\n output?: string;\n isTimeout: boolean;\n}\n\nexport interface ToolFailureContext extends NotificationContextBase {\n eventType: 'tool:failure';\n toolCallId?: string;\n toolName: string;\n summary?: string;\n toolInput?: Record<string, unknown>;\n error?: string;\n}\n\nexport interface PermissionRequestContext extends NotificationContextBase {\n eventType: 'permission:request';\n requestId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface QuestionRequestContext extends NotificationContextBase {\n eventType: 'question:request';\n requestId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface AgentMessageContext extends NotificationContextBase {\n eventType: 'agent:message';\n messageContent?: string;\n}\n\nexport interface ErrorContext extends NotificationContextBase {\n eventType: 'error';\n error?: string;\n}\n\n// ==========================================\n// Union type — no index signature\n// ==========================================\nexport type NotificationContext =\n | SessionStartContext\n | SessionEndContext\n | TurnFinishedContext\n | TurnThinkingContext\n | ToolPostContext\n | ToolExecutedContext\n | ToolFailureContext\n | PermissionRequestContext\n | QuestionRequestContext\n | AgentMessageContext\n | ErrorContext;\n","// src/i18n/index.ts\nimport './types.js';\nimport i18next from 'i18next';\nimport en from './locales/en.js';\n\nconst lng = process.env.HANDSOFF_LANG ?? 'en';\n\ni18next.init({\n initImmediate: false,\n lng,\n fallbackLng: 'en',\n resources: { en: { translation: en } },\n interpolation: { escapeValue: false },\n});\n\nexport const t = i18next.t.bind(i18next);\n","// src/i18n/types.ts\nimport type en from './locales/en.js';\n\ndeclare module 'i18next' {\n interface CustomTypeOptions {\n defaultNS: 'translation';\n resources: { translation: typeof en };\n }\n}\n","// src/i18n/locales/en.ts\nexport default {\n wizard: {\n section: {\n cli: '[ CLI Configuration ]',\n channel: '[ Channel Configuration ]',\n complete: '[ Setup Complete ]',\n },\n cli: {\n runAgain: 'Run init again when Claude Code is installed.',\n detected: 'Claude Code detected.',\n hooksInstalled: 'Hooks already installed.',\n hooksNotInstalled: 'Hooks not installed.',\n hooksTokenMismatch: 'Hooks have outdated token - reconfiguration required.',\n actionQuestion: 'Select action:',\n injectAction: 'Inject hooks configuration',\n updateAction: 'Update hooks configuration',\n backAction: 'Back',\n hookCheckbox: 'Select hooks:',\n noHooksSelected: 'No hooks selected, skipping injection.',\n injecting: 'Injecting hooks...',\n injected: 'Hooks injected',\n failed: 'Failed: {{error}}',\n remoteModeSkipHooks: 'Remote mode does not require hooks; skipping injection.',\n cleaningHooks: 'Cleaning up hooks from previous mode...',\n hooksCleaned: 'Hooks cleaned',\n cleanupWarning: 'Hook cleanup warning: {{error}}',\n },\n channel: {\n configuring: 'Configuring {{channel}}',\n telegram: {\n botToken: 'Telegram bot token:',\n allowedUsers: 'Allowed Telegram user IDs (comma-separated):',\n testing: 'Testing Telegram connection...',\n connected: 'Connected to Telegram',\n sendingTest: 'Sending test message...',\n testSent: 'Test message sent',\n testContent: 'Handsoff test message',\n testWarning: 'Could not send test message (user may not have messaged bot yet)',\n apiError: 'API error: {{status}}',\n connFailed: 'Connection failed: {{error}}',\n },\n feishu: {\n appId: 'Feishu App ID:',\n appSecret: 'Feishu App Secret:',\n allowedUsers: 'Allowed User IDs (comma-separated, e.g., ou_xxx,oc_xxx):',\n required: 'app_id and app_secret are required. Skipping.',\n },\n },\n codex: {\n enable: 'Enable Codex agent integration?',\n command: 'Codex app-server command:',\n workDir: 'Default Codex working directory (optional):',\n model: 'Default Codex model (optional):',\n approvalPolicy: 'Default Codex approval policy (optional):',\n detected: 'Codex CLI detected.',\n notDetected: 'Codex CLI not found in PATH.',\n enabled: 'Codex integration enabled.',\n disabled: 'Codex integration disabled.',\n },\n notify: {\n title: 'Notification types for {{channel}}',\n checkbox: 'Notification types:',\n saved: 'Notification types saved for {{channel}}',\n },\n menu: {\n select: 'Select:',\n next: '--- Next ---',\n testFailed: 'Test failed. Action:',\n retry: 'Retry',\n reenter: 'Re-enter',\n backToMenu: 'Back to menu',\n restartQuestion: 'Restart Gateway now?',\n },\n final: {\n noItems: 'No items configured.',\n itemOk: '{{item}}: OK',\n running: 'Gateway is running',\n runningChanges: 'Gateway is running with pending changes',\n configModified: 'Configuration was modified. Restart required to apply changes.',\n runningReady: 'Gateway is already running and ready.',\n notRunning: 'Gateway is not running',\n configModifiedStart: 'Configuration was modified. Starting Gateway with new configuration.',\n restarting: 'Restarting...',\n restarted: 'Gateway restarted with new configuration',\n starting: 'Starting...',\n started: 'Gateway started',\n startFailed: 'Failed: {{error}}',\n restartTip: 'Run `handsoff gateway start` to restart.',\n startTip: 'Run `handsoff gateway start` to start.',\n done: 'Done.',\n },\n },\n\n gateway: {\n stopping: 'Stopping daemon...',\n startedOnPort: 'Gateway started on port {{port}}',\n stopped: 'Daemon stopped',\n notRunning: 'Daemon is not running',\n restartedOnPort: 'Gateway restarted on port {{port}}',\n startFailed: 'Failed to start Gateway',\n stopFailed: 'Failed to stop Gateway',\n restartFailed: 'Failed to restart Gateway',\n error: ' Error: {{error}}',\n checkLogs: 'Check logs at: {{path}}',\n status: {\n title: 'Gateway Status:',\n running: 'Running: {{value}}',\n sessions: 'Sessions: {{count}}',\n clients: 'Connected clients: {{count}}',\n activeSessions: 'Active sessions:',\n notResponding: 'Gateway is not responding',\n notRunning: 'Gateway is not running',\n },\n },\n\n daemon: {\n alreadyRunning: 'Daemon is already running',\n startedOnPort: 'Daemon started on port {{port}}',\n startFailed: 'Daemon failed to start. Check logs for details.',\n checkLogs: 'Check logs at: {{path}}',\n portInUse: 'Warning: Port {{port}} still in use after {{ms}}ms',\n startError: 'Failed to start daemon: {{error}}',\n lackingToken: 'Daemon is running but PID file lacks token, restarting...',\n scriptNotFound: 'Daemon script not found: {{path}}',\n },\n\n status: {\n title: '=== Handsoff Status ===',\n daemon: {\n running: 'Daemon: ✓ Running',\n notRunning: 'Daemon: ✗ Not running',\n },\n port: 'Port: {{port}}',\n logLevel: 'Log Level: {{level}}',\n channels: 'Channels:',\n telegram: {\n enabled: 'Telegram: ✓ Enabled',\n disabled: 'Telegram: ✗ Disabled',\n },\n feishu: {\n enabled: 'Feishu: ✓ Enabled',\n disabled: 'Feishu: ✗ Disabled',\n },\n settingsBackup: 'Settings: ✓ Backup exists',\n settingsNoBackup: 'Settings: ✗ No backup',\n paths: 'Paths:',\n pathConfig: 'Config: {{path}}',\n pathLogs: 'Logs: {{path}}',\n pathBackup: 'Backup: {{path}}',\n },\n\n cli: {\n init: {\n configExists: 'Configuration exists. Continue?',\n cancelled: 'Cancelled.',\n },\n stop: {\n notRunning: 'Handsoff daemon is not running',\n stopping: 'Stopping handsoff daemon...',\n stopped: 'Daemon stopped successfully',\n failed: 'Failed to stop daemon cleanly',\n },\n attach: {\n checking: 'Checking Gateway status...',\n running: 'Gateway is running',\n notRunning: 'Gateway is not running. Start it with: handsoff gateway start',\n tokenNotFound: 'Hook token not found. Please run \"handsoff init\" first.',\n attached: 'Successfully attached {{agent}} to Gateway',\n start: 'Start \"claude\" to begin a session.',\n usingToken: 'Using hook token: {{token}}',\n settingsBacked: 'Claude settings backed up to: {{path}}',\n configuringHooks: 'Configuring hooks in Claude settings...',\n connected: 'Your Claude Code is now connected to handsoff Gateway.',\n forwarding: 'Events will be forwarded to connected clients.',\n tipStatus: 'Use \"handsoff gateway status\" to check status',\n tipDetach: 'Use \"handsoff detach\" to remove hooks and restore settings',\n },\n agent: {\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n tokenNotFound: 'Failed to get token from daemon',\n hooksConfigured: 'Claude hooks configured',\n startingIn: 'Starting Claude Code in {{dir}}...',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n configuring: 'Configuring Claude Code...',\n settingsBacked: 'Claude settings backed up',\n exited: '\\nClaude Code exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n tipStop: 'Use \"handsoff stop\" to stop the daemon and restore settings',\n detaching: '\\nDetaching from Claude...',\n },\n codex: {\n notInstalled: 'Codex CLI is not installed',\n installMethods: 'Please install Codex CLI using one of these methods:',\n option1npm: 'Option 1 - npm (recommended): npm install -g @openai/codex',\n option2brew: 'Option 2 - Homebrew (macOS): brew install --cask codex',\n alternative: 'Alternatively, use Claude Code: handsoff claude',\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n notEnabled: 'Codex adapter is not enabled in handsoff config.',\n enableHint: 'Enable it with \"handsoff init\" or by setting agent.codex.enabled = true in ~/.handsoff/config.toml, then restart the daemon.',\n startingIn: 'Starting Codex CLI {{version}} in {{dir}}',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n exited: '\\nCodex CLI exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n detaching: '\\nDetaching from Codex...',\n },\n debug: {\n starting: 'Starting hook debug server on port {{port}}',\n capturing: 'This will capture all incoming webhook requests...',\n pressCtrlC: 'Press Ctrl+C to stop.',\n stopping: '\\nStopping debug server...',\n },\n },\n\n notifications: {\n permission: {\n title: '🔐 Permission Request',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n args: 'Args: {{args}}',\n requestId: 'Request ID: {{requestId}}',\n allow: '✅ Allow',\n deny: '❌ Deny',\n },\n finished: {\n titleTelegram: '✅ Task Completed',\n titleLogger: '🏁 Task Completed',\n session: 'Session: {{sessionId}}',\n message: 'Message: {{message}}',\n eventType: 'Type: {{eventType}}',\n },\n sessionStart: {\n title: '🟢 Session Started',\n session: 'Session: {{sessionId}}',\n },\n error: {\n title: '❌ Error',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n message: 'Message: {{message}}',\n },\n unauthorized: 'You are not authorized to use this bot.',\n received: 'Message received.',\n processingError: 'Error processing message.',\n },\n\n eventTitles: {\n sessionStart: '🚀 Session Started',\n sessionEnd: '👋 Session Ended',\n turnFinished: '✅ Task Completed',\n turnThinking: '💭 Thinking...',\n toolPost: '🔧 Tool Call',\n toolExecuted: '✅ Tool Executed',\n toolFailure: '❌ Tool Failed',\n permissionRequest: '🔐 Permission Request',\n permissionResponse: '📋 Permission Response',\n questionRequest: '❓ Question',\n questionResponse: '📋 Question Response',\n agentMessage: '🤖 Agent Message',\n error: '⚠️ Error',\n fallback: '📋 Notification',\n },\n};\n","/**\n * Format a duration in milliseconds to a compact human-readable string.\n *\n * < 1s → \"900ms\"\n * < 1m → \"15s\"\n * < 1h → \"15m\"\n * >= 1h → \"1h15m\" (hours + minutes, omit minutes if 0)\n */\nexport function formatDuration(ms: number | undefined): string {\n if (ms === undefined || ms < 0) return '-';\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60_000) return `${Math.round(ms / 1000)}s`;\n if (ms < 3_600_000) return `${Math.round(ms / 60_000)}m`;\n\n const hours = Math.floor(ms / 3_600_000);\n const minutes = Math.round((ms % 3_600_000) / 60_000);\n if (minutes === 0) return `${hours}h`;\n return `${hours}h${minutes}m`;\n}\n\n/**\n * Format a token count to a compact human-readable string.\n *\n * < 1_000 → \"500\"\n * < 1_000_000 → \"1.5k\" (one decimal, trailing .0 stripped)\n * >= 1_000_000 → \"2.0M\"\n */\nexport function formatTokenCount(n: number | undefined): string {\n if (n === undefined || n < 0) return '-';\n if (n < 1_000) return `${n}`;\n if (n < 1_000_000) {\n const val = n / 1_000;\n return `${stripZeroDecimal(val)}k`;\n }\n const val = n / 1_000_000;\n return `${stripZeroDecimal(val)}M`;\n}\n\nfunction stripZeroDecimal(val: number): string {\n const fixed = val.toFixed(1);\n return fixed.endsWith('.0') ? fixed.slice(0, -2) : fixed;\n}\n","import { createHash } from 'crypto';\n\n/**\n * Generate a channel instance ID from channel type and its credential.\n * Format: \"channelType:hash\" e.g. \"telegram:abc123def\"\n */\nexport function getChannelInstanceId(channelType: string, credential: string): string {\n const hash = createHash('sha256').update(credential).digest('hex').slice(0, 12);\n return `${channelType}:${hash}`;\n}\n\n/**\n * Parse a channel instance ID back into its components.\n */\nexport function parseChannelInstanceId(instanceId: string): { channelType: string; hash: string } | null {\n const parts = instanceId.split(':');\n if (parts.length !== 2) return null;\n return { channelType: parts[0], hash: parts[1] };\n}\n\n/**\n * Get display label for a channel instance ID.\n * Uses short hash for display purposes.\n */\nexport function getChannelInstanceLabel(channelType: string, hash: string, displayName?: string): string {\n return displayName ?? `${channelType} (${hash})`;\n}","import type { Logger } from 'pino';\nimport { BaseChannel } from '../../../core/channel/base.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { ChannelConfig, ChannelCapabilities } from '../../../core/channel/types.js';\nimport type { OutboundMessage } from '../../../core/bus/events.js';\nimport { Channel } from '../../../core/channel/registry.js';\n\n/**\n * Logger Channel 实现\n *\n * 仅用于调试,将所有消息输出到日志。\n */\n@Channel('logger')\nexport class LoggerChannel extends BaseChannel {\n readonly name = 'logger';\n readonly displayName = 'Logger';\n readonly channelInstanceId = 'logger:default';\n readonly capabilities: ChannelCapabilities = {\n supportsButtons: false,\n supportsMarkdown: false,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private messageLogger: Logger;\n\n constructor(config: ChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n this.messageLogger = logger;\n }\n\n /**\n * Logger Channel 不接收消息,拒绝所有发送者\n */\n protected isAllowed(_senderId: string): boolean {\n return false;\n }\n\n async start(): Promise<void> {\n await super.start();\n this.logger.info('Logger channel started');\n }\n\n async stop(): Promise<void> {\n await super.stop();\n this.logger.info('Logger channel stopped');\n }\n\n async send(message: OutboundMessage): Promise<void> {\n this.messageLogger.info({\n chatId: message.chatId,\n text: message.text,\n }, '[Logger] Message');\n }\n}\n","import type { Logger } from 'pino';\nimport { BaseChannel } from '../../../core/channel/base.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { ChannelConfig, ChannelCapabilities } from '../../../core/channel/types.js';\nimport type { OutboundMessage, InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { NotificationContext, TurnFinishedContext } from '../../../gateway/notification-context.js';\nimport { getEventTitle } from '../../../gateway/notification-context.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport { FeishuClient, type CardActionData } from './client.js';\nimport { FeishuFormatter, type PostContent } from './formatter.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\nimport { formatDuration, formatTokenCount } from '../../../shared/format.js';\n\nconst REQUEST_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nexport interface FeishuChannelConfig extends ChannelConfig {\n /** 飞书应用 ID */\n app_id: string;\n /** 飞书应用密钥 */\n app_secret: string;\n /** 消息加密密钥(可选) */\n encrypt_key?: string;\n /** 验证 Token(可选) */\n verification_token?: string;\n /** 允许访问的用户列表,[\"*\"] 表示允许所有 */\n allowed_users?: string[];\n}\n\n/**\n * 飞书卡片结构(预留 V3 使用)\n * 参考:https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/send-feishu-cards\n */\nexport interface FeishuCard {\n config?: { wide_screen_mode?: boolean };\n header?: {\n title: { tag: 'plain_text'; content: string };\n };\n elements: unknown[];\n}\n\n/**\n * Feishu Channel 实现\n *\n * V2:实现完整消息收发\n * V3+:交互卡片、流式输出\n */\n@Channel('feishu')\nexport class FeishuChannel extends BaseChannel {\n readonly name = 'feishu';\n readonly displayName = 'Feishu';\n\n readonly capabilities: ChannelCapabilities = {\n supportsButtons: true, // V3:交互卡片\n supportsMarkdown: true, // V2:支持 Markdown\n supportsImages: false, // V3:图片消息\n supportsStreaming: false, // V3:流式输出\n };\n\n private feishuConfig: FeishuChannelConfig;\n private allowedUsers: Set<string>;\n private client: FeishuClient | null = null;\n private pendingRequests: Map<string, Set<string>> = new Map();\n private pendingOptions: Map<string, Array<{ id: string; value: unknown }>> = new Map();\n private pendingToolNames: Map<string, string> = new Map(); // requestId -> toolName for always_allow\n private pendingSelections: Map<string, Set<string>> = new Map();\n private unsubscribeInteractionResponse?: () => void;\n private formatter = new FeishuFormatter();\n\n constructor(config: ChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n\n this.feishuConfig = config as FeishuChannelConfig;\n this.allowedUsers = new Set(this.feishuConfig.allowed_users || []);\n\n if (!this.feishuConfig.app_id || !this.feishuConfig.app_secret) {\n throw new Error('FeishuChannel requires app_id and app_secret in config');\n }\n\n this.logger.debug(\n { appId: this.feishuConfig.app_id },\n 'FeishuChannel initialized'\n );\n }\n\n get channelInstanceId(): string {\n return getChannelInstanceId('feishu', this.feishuConfig.app_id);\n }\n\n /**\n * 获取默认配置\n * 参考 nanobot default_config 类方法\n */\n static defaultConfig(): Partial<FeishuChannelConfig> {\n return {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [], // 默认拒绝所有,需要显式配置\n };\n }\n\n /**\n * 启动 Channel\n * V2:启动 WebSocket 连接\n */\n async start(): Promise<void> {\n await super.start();\n\n this.client = new FeishuClient(this.feishuConfig, {\n logger: this.logger,\n onStateChange: (state, error) => {\n this.updateConnectionState(state, error?.message);\n },\n onReconnect: (attempt) => {\n this.recordReconnectAttempt();\n this.logger.warn({ attempt }, 'Feishu WebSocket reconnecting');\n },\n });\n\n this.client.startWebSocket(\n this.handleMessage.bind(this),\n this.handleCardAction.bind(this)\n );\n\n this.unsubscribeInteractionResponse = this.bus.onInteractionResponse(\n this.handleInteractionResponse.bind(this)\n );\n\n this.logger.info({ channel: this.name }, '[Channel] Started');\n }\n\n /**\n * 停止 Channel\n */\n async stop(): Promise<void> {\n this.unsubscribeInteractionResponse?.();\n this.pendingRequests.clear();\n this.pendingOptions.clear();\n this.pendingToolNames.clear();\n this.pendingSelections.clear();\n this.client?.stopWebSocket();\n await super.stop();\n this.logger.info({ channel: this.name }, '[Channel] Stopped');\n }\n\n /**\n * 格式化通知上下文为飞书 PostContent\n * 覆写 BaseChannel.format() 以支持富文本格式\n */\n format(context: NotificationContext): PostContent {\n // Use the channel's inline formatter for NotificationContext\n const markdown = this.formatContextToMarkdown(context);\n return this.formatter.markdownToPost(markdown);\n }\n\n /**\n * 发送消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission/question requests - NotificationHandler routes to the bound channel via onOutbound\n if (\n (message.metadata?.eventType === 'permission:request' ||\n message.metadata?.eventType === 'question:request') &&\n message.channel === 'broadcast'\n ) {\n return;\n }\n\n if (!this.client) {\n throw new Error('Feishu client not initialized');\n }\n\n const eventType = message.metadata?.eventType;\n const ctx = message.context as Record<string, unknown> | undefined;\n const interaction = ctx?.interaction as import('../../../gateway/notification-context.js').InteractionContext | undefined;\n const requestId = ctx?.requestId as string | undefined;\n\n // Route to appropriate card builder\n if (eventType === 'permission:request') {\n const toolName = (ctx?.toolName as string) || '';\n if (requestId) {\n this.pendingToolNames.set(requestId, toolName);\n }\n const content = this.formatContextToMarkdown(message.context!);\n const buttons: import('./types.js').PermissionButtonDef[] = [\n { text: '✅ Allow', type: 'primary_filled', value: 'agree' },\n { text: '❌ Deny', type: 'danger_filled', value: 'reject', confirm: { title: '确认拒绝', text: '确认拒绝该工具调用?' } },\n { text: '🔓 Always Allow', type: 'default', value: 'always_allow', confirm: { title: '确认总是允许', text: '总是允许将放行该工具的所有调用,请确认。' } },\n ];\n const cardContent = this.formatter.formatPermissionCard({ title: this.getTitleForContext(message.context), content, buttons });\n await this.sendCardRaw(cardContent, message);\n } else if (eventType === 'question:request') {\n const question = interaction?.question;\n const content = this.formatContextToMarkdown(message.context!);\n const mode = question?.multiSelect ? 'multiple' : 'single';\n const items = (question?.options || []).map((opt: { id: string; label: string }) => ({ id: opt.id, label: opt.label }));\n if (requestId && question) {\n this.pendingOptions.set(\n requestId,\n question.options.map((opt: { id: string; value: unknown }) => ({ id: opt.id, value: opt.value }))\n );\n }\n const cardContent = this.formatter.formatQuestionCard({ title: this.getTitleForContext(message.context), content, mode, items, requestId });\n await this.sendCardRaw(cardContent, message);\n } else {\n // Default: message card\n const content = message.context ? this.formatContextToMarkdown(message.context) : (message.text || '');\n let meta = '';\n if (message.context?.eventType === 'turn:finished') {\n const finishedCtx = message.context as TurnFinishedContext;\n const model = finishedCtx.model || finishedCtx.agentType || '-';\n const duration = formatDuration(finishedCtx.durationMs);\n const outTokens = finishedCtx.usage?.outputTokens;\n const inTokens = finishedCtx.usage?.inputTokens;\n const tokens = (outTokens !== undefined && inTokens !== undefined)\n ? `${formatTokenCount(inTokens)}↑ ${formatTokenCount(outTokens)}↓`\n : '-';\n meta = `${model} · ${duration} · ${tokens}`;\n }\n const cardContent = this.formatter.formatMessageCard({ title: this.getTitleForContext(message.context), content, meta });\n await this.sendCardRaw(cardContent, message);\n }\n\n // Track pending requests so card actions can be validated\n if ((eventType === 'permission:request' || eventType === 'question:request') && requestId) {\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, new Set());\n }\n const targetUsers = this.feishuConfig.allowed_users || [];\n for (const userId of targetUsers) {\n if (userId !== '*') {\n this.pendingRequests.get(requestId)!.add(userId);\n }\n }\n }\n\n this.logger.info({ chatId: message.chatId, eventType: message.context?.eventType }, 'Feishu message sent');\n }\n\n /**\n * 处理接收到的消息\n */\n private async handleMessage(data: unknown): Promise<void> {\n const message = this.parseMessage(data);\n if (!message) return;\n\n if (!this.isAllowed(message.senderId)) {\n this.logger.warn({ senderId: message.senderId }, 'Unauthorized message');\n return;\n }\n\n this.receiveMessage(\n message.chatId,\n message.messageId,\n message.content,\n {\n id: message.senderId,\n username: message.senderName,\n }\n );\n this.logger.info({ senderId: message.senderId, chatId: message.chatId, contentPreview: message.content.slice(0, 60) }, 'Feishu message received');\n }\n\n /**\n * 解析飞书消息\n * TODO: 实现完整的消息解析\n */\n private parseMessage(data: unknown): FeishuMessage | null {\n // 基础实现,需要根据实际情况完善\n try {\n const event = data as Record<string, unknown>;\n const message = event.message as Record<string, unknown>;\n const sender = event.sender as Record<string, unknown>;\n\n if (!message || !sender) {\n this.logger.warn({ hasMessage: !!message, hasSender: !!sender }, 'Feishu parseMessage: missing message or sender');\n return null;\n }\n\n const content = this.extractContent(message);\n if (!content) {\n this.logger.warn({ msgType: message.message_type || message.msg_type, rawContent: message.content }, 'Feishu parseMessage: no content extracted');\n return null;\n }\n\n const senderIdObj = sender.sender_id as Record<string, unknown> | undefined;\n\n return {\n messageId: String(message.message_id || ''),\n chatId: String(message.chat_id || ''),\n senderId: String(senderIdObj?.open_id || ''),\n senderName: String(senderIdObj?.union_id || 'unknown'),\n content,\n };\n } catch (error) {\n this.logger.error({ error }, 'Failed to parse Feishu message');\n return null;\n }\n }\n\n /**\n * 提取消息内容\n */\n private extractContent(message: Record<string, unknown>): string | null {\n const msgType = String(message.message_type || message.msg_type || '');\n const contentStr = String(message.content || '{}');\n\n try {\n const content = JSON.parse(contentStr);\n\n if (msgType === 'text') {\n return content.text || '';\n }\n\n // TODO: 支持其他消息类型\n return `[${msgType}]`;\n } catch {\n return contentStr;\n }\n }\n\n /**\n * 权限检查\n * 安全默认:空列表 = 拒绝所有\n *\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected isAllowed(senderId: string): boolean {\n // 安全默认:空列表 = 拒绝所有\n if (this.allowedUsers.size === 0) {\n this.logger.warn(\n { senderId },\n 'Feishu: allowed_users is empty — all access denied'\n );\n return false;\n }\n\n // \"*\" = 允许所有\n if (this.allowedUsers.has('*')) {\n return true;\n }\n\n return this.allowedUsers.has(senderId);\n }\n\n /**\n * 处理统一交互响应事件\n */\n private async handleInteractionResponse(event: InteractionResponseEvent): Promise<void> {\n const userMessages = this.pendingRequests.get(event.requestId);\n if (userMessages) {\n const action = event.response.action;\n const decisionText = action === 'allow' ? '✅ Approved' : action === 'deny' ? '❌ Denied' : `✓ ${action}`;\n this.logger.info(\n { requestId: event.requestId, action },\n `Interaction ${decisionText}`\n );\n }\n this.pendingRequests.delete(event.requestId);\n this.pendingOptions.delete(event.requestId);\n }\n\n /**\n * Handle card button / checker callbacks\n */\n private async handleCardAction(data: CardActionData): Promise<void> {\n const { action, requestId, userId, optionId } = data;\n\n if (!requestId || !userId) {\n this.logger.warn({ data }, 'Invalid card action: missing requestId or userId');\n return;\n }\n\n if (!REQUEST_ID_REGEX.test(requestId)) {\n this.logger.warn({ requestId }, 'Invalid request ID format');\n return;\n }\n\n if (!this.isAllowed(userId)) {\n this.logger.warn({ userId, requestId }, 'Unauthorized user tried to respond to request');\n return;\n }\n\n const allowedUsersForRequest = this.pendingRequests.get(requestId);\n if (!allowedUsersForRequest) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to unknown request');\n return;\n }\n // Empty set means \"*\" (all users allowed); otherwise check specific user\n if (allowedUsersForRequest.size > 0 && !allowedUsersForRequest.has(userId)) {\n this.logger.warn({ userId, requestId }, 'User tried to respond to request they did not receive');\n return;\n }\n\n // Handle checker toggle (multi-select)\n if (action === 'check') {\n if (!optionId) {\n this.logger.warn({ requestId, userId }, '[Channel] Check missing optionId');\n return;\n }\n if (!this.pendingSelections.has(requestId)) {\n this.pendingSelections.set(requestId, new Set());\n }\n const selected = this.pendingSelections.get(requestId)!;\n if (data.checked) {\n selected.add(optionId);\n } else {\n selected.delete(optionId);\n }\n this.logger.info({ requestId, userId, optionId, checked: data.checked, selectedCount: selected.size }, '[Channel] Checker changed');\n return;\n }\n\n // Handle submit (multi-select)\n if (action === 'submit') {\n const selected = this.pendingSelections.get(requestId);\n const optionIds = selected ? Array.from(selected) : [];\n if (optionIds.length === 0) {\n this.logger.warn({ requestId, userId }, '[Channel] Submit with no selections');\n return;\n }\n const options = this.pendingOptions.get(requestId);\n const selectedValues = optionIds\n .map((id) => options?.find((opt) => opt.id === id)?.value)\n .filter((v): v is unknown => v !== undefined);\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues,\n },\n reason: `User submitted multi-select via Feishu`,\n });\n\n this.logger.info({ requestId, userId, selectedCount: optionIds.length }, '[Channel] Multi-select submitted');\n this.pendingSelections.delete(requestId);\n this.pendingRequests.delete(requestId);\n this.pendingOptions.delete(requestId);\n return;\n }\n\n // Handle permission actions (agree / reject / always_allow)\n if (action === 'agree' || action === 'reject' || action === 'always_allow') {\n const decision = action === 'reject' ? 'deny' : 'allow';\n const isAlwaysAllow = action === 'always_allow';\n\n const permissionUpdates = isAlwaysAllow ? [{\n type: 'addRules' as const,\n rules: [{ toolName: this.pendingToolNames.get(requestId) ?? '*', ruleContent: '*' }],\n behavior: 'allow' as const,\n destination: 'localSettings' as const,\n }] : undefined;\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: decision,\n ...(permissionUpdates && { permissionUpdates }),\n },\n reason: `User clicked ${action} button via Feishu`,\n });\n\n this.pendingToolNames.delete(requestId);\n this.pendingRequests.delete(requestId);\n this.pendingOptions.delete(requestId);\n\n this.logger.info({ requestId, userId, action: decision }, '[Channel] User response received');\n return;\n }\n\n // Handle single-select\n if (action === 'select') {\n if (!optionId) {\n this.logger.warn({ requestId, userId }, '[Channel] Select missing optionId');\n return;\n }\n\n const options = this.pendingOptions.get(requestId);\n const selectedOption = options?.find((opt) => opt.id === optionId);\n if (!selectedOption) {\n this.logger.warn({ requestId, userId, optionId }, 'Selected option not found');\n return;\n }\n\n this.bus.publishInteractionResponse({\n requestId,\n response: {\n requestId,\n action: 'select',\n selectedValues: [selectedOption.value],\n },\n reason: `User selected option ${optionId} via Feishu`,\n });\n\n this.logger.info({ requestId, userId, action: 'select', optionId }, '[Channel] User response received');\n this.pendingRequests.delete(requestId);\n this.pendingOptions.delete(requestId);\n return;\n }\n\n this.logger.warn({ action, requestId }, 'Unknown card action');\n }\n\n /**\n * Send a pre-built card JSON string\n */\n async sendCardRaw(cardContent: string, message: OutboundMessage): Promise<void> {\n if (!this.client) {\n this.logger.error('Feishu client not initialized');\n throw new Error('Feishu client not initialized');\n }\n\n const targetUsers = this.feishuConfig.allowed_users || [];\n\n for (const userId of targetUsers) {\n if (userId === '*') continue;\n\n const receiveIdType = userId.startsWith('oc_') ? 'chat_id' : 'open_id';\n\n try {\n await this.client.sendCard(userId, receiveIdType, cardContent);\n } catch (error) {\n this.logger.error(\n { userId, error: error instanceof Error ? error.message : String(error) },\n 'Failed to send Feishu card message'\n );\n }\n }\n }\n\n /**\n * 将 NotificationContext 转换为 Markdown 字符串\n */\n private formatContextToMarkdown(context: NotificationContext): string {\n let md = '';\n switch (context.eventType) {\n case 'session:start':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**User:** ${context.userId || 'Unknown'}\\n`;\n md += `**Status:** Session started`;\n if (context.cwd) {\n md += `\\n**WorkDir:** ${context.cwd}`;\n }\n break;\n case 'session:end':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Status:** Session ended`;\n if (context.reason) {\n md += `\\n**Reason:** ${context.reason}`;\n }\n break;\n case 'agent:message':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Agent Message:**\\n${context.messageContent || ''}`;\n break;\n case 'turn:thinking':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Status:** Thinking...`;\n if (context.thinking) {\n md += `\\n\\n${context.thinking}`;\n }\n break;\n case 'turn:finished':\n md = `**Session:** ${context.sessionId}\\n`;\n if (context.cwd) {\n md += `**WorkDir:** ${context.cwd}\\n`;\n }\n // Duration, model, and tokens are rendered in the card meta footer — omit from content to avoid duplication\n if (context.lastAssistantMessage) {\n md += `${context.lastAssistantMessage}`;\n }\n break;\n case 'tool:post':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Starting`;\n if (context.toolInput) {\n md += `\\n**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n }\n break;\n case 'tool:executed':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Completed`;\n if (context.summary) {\n md += `\\n\\n${context.summary}`;\n }\n if (context.isTimeout) {\n md += `\\n\\n⚠️ **Timeout**`;\n }\n break;\n case 'tool:failure':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Status:** Failed`;\n if (context.error) {\n md += `\\n**Error:** ${context.error}`;\n }\n break;\n case 'permission:request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**${getEventTitle('permission:request')}**\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n if (context.cwd) {\n md += `**Working Dir:** ${context.cwd}\\n`;\n }\n if (context.toolInput) {\n md += `\\n**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n }\n break;\n case 'question:request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**${getEventTitle('question:request')}**\\n`;\n if (context.interaction?.question) {\n md += `\\n${context.interaction.question.question}`;\n }\n break;\n case 'error':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Error**\\n`;\n if (context.error) {\n md += context.error;\n }\n break;\n default:\n md = `**Event:** ${(context as any).eventType}\\n**Session:** ${(context as any).sessionId}`;\n }\n return md;\n }\n\n /**\n * 根据上下文获取标题\n */\n private getTitleForContext(context?: NotificationContext): string {\n if (!context) return getEventTitle('error');\n return getEventTitle(context.eventType);\n }\n}\n\n// 消息类型定义\ninterface FeishuMessage {\n messageId: string;\n chatId: string;\n senderId: string;\n senderName: string;\n content: string;\n}\n","/**\n * Feishu SDK 客户端封装\n * 支持 WebSocket 连接和自动重连\n */\n\nimport {\n Client,\n WSClient,\n EventDispatcher,\n AppType,\n LoggerLevel,\n} from '@larksuiteoapi/node-sdk';\nimport type { PostContent } from './formatter.js';\nimport type { FeishuChannelConfig } from './index.js';\nimport type { CardActionData } from './types.js';\n\nexport type ConnectionState = 'connected' | 'disconnected' | 'error';\n\nexport { type CardActionData } from './types.js';\n\nexport interface FeishuClientOptions {\n /** 状态变化回调 */\n onStateChange?: (state: ConnectionState, error?: Error) => void;\n /** 重连回调 */\n onReconnect?: (attempt: number) => void;\n /** 日志记录器 */\n logger?: import('pino').Logger;\n}\n\nexport type MessageHandler = (data: unknown) => void | Promise<void>;\nexport type CardActionHandler = (data: CardActionData) => void | Promise<void>;\n\nexport class FeishuClient {\n private client: Client;\n private wsClient: WSClient | null = null;\n private eventDispatcher: EventDispatcher | null = null;\n private config: FeishuChannelConfig;\n private options: FeishuClientOptions;\n private reconnectCount = 0;\n private isRunning = false;\n private messageHandler: MessageHandler | null = null;\n private cardActionHandler: CardActionHandler | null = null;\n /** 重连定时器 */\n private reconnectTimer: NodeJS.Timeout | null = null;\n\n constructor(config: FeishuChannelConfig, options: FeishuClientOptions = {}) {\n this.config = config;\n this.options = options;\n this.client = new Client({\n appId: config.app_id,\n appSecret: config.app_secret,\n appType: AppType.SelfBuild,\n });\n options.logger?.debug('FeishuClient created');\n }\n\n /**\n * 发送 post 消息(富文本)\n */\n async sendPost(\n receiveId: string,\n receiveIdType: 'open_id' | 'chat_id',\n postContent: PostContent\n ): Promise<string | null> {\n const response = await this.client.im.message.create({\n params: { receive_id_type: receiveIdType },\n data: {\n receive_id: receiveId,\n msg_type: 'post',\n content: JSON.stringify(postContent),\n },\n });\n\n if (response.code !== 0) {\n throw new Error(`Feishu API error: ${response.msg}`);\n }\n return response.data?.message_id || null;\n }\n\n /**\n * 发送卡片消息(交互式)\n */\n async sendCard(\n receiveId: string,\n receiveIdType: 'open_id' | 'chat_id',\n cardContent: string\n ): Promise<string | null> {\n const response = await this.client.im.message.create({\n params: { receive_id_type: receiveIdType },\n data: {\n receive_id: receiveId,\n msg_type: 'interactive',\n content: cardContent,\n },\n });\n\n if (response.code !== 0) {\n throw new Error(`Feishu API error: ${response.msg}`);\n }\n return response.data?.message_id || null;\n }\n\n /**\n * 启动 WebSocket 连接(带自动重连)\n */\n startWebSocket(messageHandler: MessageHandler, cardActionHandler?: CardActionHandler): void {\n if (this.isRunning) {\n this.options.logger?.warn('startWebSocket called but already running');\n return;\n }\n\n this.isRunning = true;\n this.messageHandler = messageHandler;\n this.cardActionHandler = cardActionHandler || null;\n this.options.logger?.debug('FeishuClient starting WebSocket...');\n this.connectWebSocket();\n }\n\n /**\n * 连接 WebSocket\n */\n private connectWebSocket(): void {\n try {\n this.eventDispatcher = new EventDispatcher({\n encryptKey: this.config.encrypt_key || '',\n verificationToken: this.config.verification_token || '',\n });\n\n // 注册消息处理器\n this.eventDispatcher.register({\n 'im.message.receive_v1': async (data: unknown) => {\n this.options.logger?.info('Feishu WS received im.message.receive_v1');\n this.options.logger?.debug({ data }, 'Feishu WS im.message.receive_v1 payload');\n await this.messageHandler?.(data);\n },\n // Catch-all: log any other event to aid debugging\n '*': async (eventType: string, data: unknown) => {\n this.options.logger?.info({ eventType }, 'Feishu WS received other event');\n this.options.logger?.debug({ eventType, data }, 'Feishu WS other event payload');\n },\n 'card.action.trigger': async (data: unknown) => {\n // 必须返回响应(toast/card),否则飞书会在3秒后超时\n await this.handleCardAction(data);\n // 返回 toast 响应表示成功处理\n return {\n toast: {\n type: 'success',\n content: '已处理',\n },\n };\n },\n });\n\n this.wsClient = new WSClient({\n appId: this.config.app_id,\n appSecret: this.config.app_secret,\n loggerLevel: LoggerLevel.debug,\n autoReconnect: true,\n });\n\n // 启动连接\n this.wsClient\n .start({ eventDispatcher: this.eventDispatcher })\n .then(() => {\n // 检查是否仍在运行,防止 stop 后的状态更新\n if (!this.isRunning) {\n this.wsClient?.close({ force: true });\n return;\n }\n this.reconnectCount = 0;\n this.options.logger?.info('Feishu WebSocket connected');\n this.options.onStateChange?.('connected');\n })\n .catch((error: Error) => {\n this.options.logger?.error({ error: error.message }, 'Feishu WebSocket connection failed');\n this.options.onStateChange?.('error', error);\n this.handleDisconnect();\n });\n\n // 注意:WSClient 内部有自动重连机制,但我们无法直接监听 connect/disconnect 事件\n // 我们通过定期检查和重连回调来跟踪状态\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.options.onStateChange?.('error', err);\n this.handleDisconnect();\n }\n }\n\n /**\n * 处理卡片按钮回调\n */\n private async handleCardAction(data: unknown): Promise<void> {\n if (!this.cardActionHandler) {\n return;\n }\n\n try {\n const eventData = data as Record<string, unknown>;\n\n // 回调结构:\n // {\n // operator: { open_id: \"ou_xxx\" },\n // action: { tag: \"checker\", checked: true, value: { action: \"check\", requestId: \"xxx\" } },\n // context: { open_message_id: \"om_xxx\", open_chat_id: \"oc_xxx\" }\n // }\n const operator = eventData.operator as Record<string, unknown> | undefined;\n const actionObj = eventData.action as Record<string, unknown> | undefined;\n const value = actionObj?.value as Record<string, unknown> | undefined;\n const context = eventData.context as Record<string, unknown> | undefined;\n\n const cardAction: CardActionData = {\n action: String(value?.action || ''),\n requestId: value?.requestId as string | undefined,\n userId: operator?.open_id as string | undefined,\n messageId: context?.open_message_id as string | undefined,\n chatId: context?.open_chat_id as string | undefined,\n optionId: value?.optionId as string | undefined,\n checked: actionObj?.checked as boolean | undefined,\n };\n\n await this.cardActionHandler(cardAction);\n } catch (error) {\n this.options.logger?.error({ error }, 'Feishu handleCardAction error');\n }\n }\n /**\n * 处理连接断开(自动重连)\n */\n private handleDisconnect(): void {\n if (!this.isRunning) {\n return;\n }\n\n this.reconnectCount++;\n this.options.onReconnect?.(this.reconnectCount);\n this.options.onStateChange?.('disconnected');\n\n // 指数退避:1s, 2s, 4s, 8s, 最大30s\n const delay = Math.min(1000 * Math.pow(2, this.reconnectCount - 1), 30000);\n\n this.reconnectTimer = setTimeout(() => {\n if (this.isRunning) {\n this.connectWebSocket();\n }\n }, delay);\n }\n\n /**\n * 停止 WebSocket 连接\n */\n stopWebSocket(): void {\n this.isRunning = false;\n\n // 清理重连定时器\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.wsClient) {\n this.wsClient.close({ force: false });\n this.wsClient = null;\n }\n this.eventDispatcher = null;\n }\n\n /**\n * 获取重连次数\n */\n getReconnectCount(): number {\n return this.reconnectCount;\n }\n}\n","import type { InteractionRequestEvent } from '../../../core/bus/events.js';\nimport type { CardButton, CardContent } from './types.js';\n\n/**\n * Feishu 消息格式转换器\n * Markdown/HTML → Post 格式\n * 参考 nanobot _markdown_to_post 实现\n */\n\nexport interface PostContent {\n zh_cn: {\n title?: string;\n content: PostElement[][];\n };\n}\n\nexport type PostElement =\n | { tag: 'text'; text: string; style?: ('bold' | 'italic' | 'underline' | 'line_through')[] }\n | { tag: 'a'; text: string; href: string }\n | { tag: 'at'; user_id: string; user_name?: string };\n\ninterface Segment {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n type?: 'text' | 'link';\n href?: string;\n}\n\nexport class FeishuFormatter {\n /**\n * 将内容转换为飞书 post 格式\n * 支持 Markdown 和简单的 HTML 标签\n */\n markdownToPost(content: string): PostContent {\n // 先处理 HTML 标签,转换为飞书支持的格式\n const normalized = this.normalizeHtml(content);\n const lines = normalized.trim().split('\\n');\n const paragraphs: PostElement[][] = [];\n\n for (const line of lines) {\n const elements = this.parseLine(line);\n if (elements.length > 0) {\n paragraphs.push(elements);\n }\n }\n\n return {\n zh_cn: {\n content: paragraphs,\n },\n };\n }\n\n /**\n * 格式化统一交互请求事件为卡片内容\n */\n formatInteractionRequest(event: InteractionRequestEvent): string {\n const { content, interactionType } = event;\n\n let markdown = '';\n\n if (interactionType === 'permission' && content.permission) {\n const toolName = content.title?.replace(/^Permission Required: /, '') ?? '';\n markdown += `**🔐 ${content.title}**\\n\\n`;\n markdown += `**Tool:** \\`${toolName}\\`\\n`;\n if (content.description) {\n markdown += `\\n${content.description}\\n`;\n }\n if (content.permission.args && Object.keys(content.permission.args).length > 0) {\n markdown += `\\n**Args:**\\n`;\n markdown += `\\`\\`\\`json\\n${JSON.stringify(content.permission.args, null, 2)}\\n\\`\\`\\`\\n`;\n }\n } else if (interactionType === 'question' && content.question) {\n const q = content.question;\n markdown += `**❓ ${content.title}**\\n\\n`;\n if (q.header) {\n markdown += `**${q.header}**\\n\\n`;\n }\n markdown += `${q.text}\\n\\n`;\n if (q.options.length > 0) {\n markdown += `**Options:**\\n`;\n q.options.forEach((opt, idx) => {\n markdown += `${idx + 1}. \\`${opt.label}\\``;\n if (opt.description) {\n markdown += ` - ${opt.description}`;\n }\n markdown += '\\n';\n });\n }\n } else {\n markdown += `**${content.title}**\\n\\n`;\n if (content.description) {\n markdown += `${content.description}`;\n }\n }\n\n return markdown;\n }\n\n /**\n * 将 HTML 标签规范化,提取纯文本和格式信息\n * 飞书 post 格式不支持 HTML,需要转换\n */\n private normalizeHtml(content: string): string {\n return content\n // 代码块: <pre><code>...</code></pre> -> ```...```\n .replace(/<pre><code[^>]*>([\\s\\S]*?)<\\/code><\\/pre>/g, '```\\n$1\\n```')\n // 行内代码: <code>...</code> -> `...`\n .replace(/<code>(.*?)<\\/code>/g, '`$1`')\n // 粗体: <b>...</b> 或 <strong>...</strong> -> **...**\n .replace(/<(b|strong)>(.*?)<\\/(b|strong)>/g, '**$2**')\n // 斜体: <i>...</i> 或 <em>...</em> -> *...*\n .replace(/<(i|em)>(.*?)<\\/(i|em)>/g, '*$2*')\n // 下划线: <u>...</u> -> __...__\n .replace(/<u>(.*?)<\\/u>/g, '__$1__')\n // 删除线: <s>...</s> 或 <del>...</del> -> ~~...~~\n .replace(/<(s|del)>(.*?)<\\/(s|del)>/g, '~~$2~~')\n // 换行标签\n .replace(/<br\\s*\\/?>/g, '\\n')\n // 段落标签\n .replace(/<p>(.*?)<\\/p>/g, '$1\\n')\n // 移除其他 HTML 标签但保留内容\n .replace(/<[^>]+>/g, '');\n }\n\n /**\n * 解析单行 Markdown(支持粗体、斜体、行内代码、链接)\n */\n private parseLine(line: string): PostElement[] {\n const elements: PostElement[] = [];\n\n // 处理代码块开始/结束标记\n if (line.trim() === '```') {\n return [];\n }\n\n // 处理行内格式:粗体、斜体、行内代码、链接\n const segments = this.parseInlineFormats(line);\n\n for (const seg of segments) {\n if (seg.type === 'link') {\n elements.push({ tag: 'a', text: seg.text, href: seg.href! });\n } else {\n const style: ('bold' | 'italic' | 'underline' | 'line_through')[] = [];\n if (seg.bold) style.push('bold');\n if (seg.italic) style.push('italic');\n if (seg.underline) style.push('underline');\n if (seg.strikethrough) style.push('line_through');\n\n elements.push({\n tag: 'text',\n text: seg.text,\n ...(style.length > 0 ? { style } : {}),\n });\n }\n }\n\n // 空行处理\n if (elements.length === 0 && line.trim() === '') {\n elements.push({ tag: 'text', text: '' });\n }\n\n return elements;\n }\n\n /**\n * 解析行内格式(粗体、斜体、行内代码、链接)\n */\n private parseInlineFormats(line: string): Segment[] {\n const segments: Segment[] = [];\n let remaining = line;\n\n // 匹配优先级:链接 > 行内代码 > 粗体 > 斜体\n const patterns = [\n { regex: /\\[([^\\]]+)\\]\\((https?:\\/\\/[^)]+)\\)/, type: 'link' as const },\n { regex: /`([^`]+)`/, type: 'code' as const },\n { regex: /\\*\\*([^*]+)\\*\\*/, type: 'bold' as const },\n { regex: /\\*([^*]+)\\*/, type: 'italic' as const },\n { regex: /__([^_]+)__/, type: 'underline' as const },\n { regex: /~~([^~]+)~~/, type: 'strikethrough' as const },\n ];\n\n while (remaining.length > 0) {\n let matched = false;\n\n for (const pattern of patterns) {\n const match = remaining.match(pattern.regex);\n if (match && match.index !== undefined) {\n // 匹配前的文本\n if (match.index > 0) {\n const before = remaining.slice(0, match.index);\n if (before) {\n segments.push({ text: before });\n }\n }\n\n // 处理匹配内容\n if (pattern.type === 'link') {\n segments.push({\n text: match[1],\n type: 'link',\n href: match[2],\n });\n } else {\n const segment: Segment = { text: match[1] };\n if (pattern.type === 'bold') segment.bold = true;\n if (pattern.type === 'italic') segment.italic = true;\n if (pattern.type === 'underline') segment.underline = true;\n if (pattern.type === 'strikethrough') segment.strikethrough = true;\n // 代码特殊处理:保留反引号\n if (pattern.type === 'code') {\n segment.text = match[0]; // 保留完整的 `code`\n }\n segments.push(segment);\n }\n\n remaining = remaining.slice(match.index + match[0].length);\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n // 没有匹配到任何模式,剩余部分作为纯文本\n segments.push({ text: remaining });\n break;\n }\n }\n\n return segments.length > 0 ? segments : [{ text: line }];\n }\n\n /**\n * 生成卡片 JSON\n * 根据按钮数量动态生成元素,无按钮时隐藏 hr 和 column_set\n */\n formatCard(card: CardContent): string {\n const elements: unknown[] = [\n {\n tag: 'markdown',\n content: card.content,\n text_size: 'normal',\n margin: '0px',\n },\n ];\n\n // 有按钮时添加分割线和按钮组\n if (card.buttons && card.buttons.length > 0) {\n elements.push({ tag: 'hr', margin: '0px' });\n\n const columns = card.buttons.map((btn: CardButton, index: number) => ({\n tag: 'column' as const,\n horizontal_align: 'left' as const,\n vertical_align: 'top' as const,\n vertical_spacing: '8px',\n width: 'auto' as const,\n elements: [\n {\n tag: 'button' as const,\n text: {\n content: btn.text,\n tag: 'plain_text' as const,\n },\n type: btn.type,\n size: 'small' as const,\n margin: '4px 0px 4px 0px',\n width: 'default' as const,\n element_id: `btn_${index}_${Date.now()}`,\n behaviors: [\n {\n type: 'callback' as const,\n value: btn.callbackValue,\n },\n ],\n },\n ],\n }));\n\n elements.push({\n tag: 'column_set' as const,\n flex_mode: 'stretch' as const,\n horizontal_align: 'left' as const,\n horizontal_spacing: '8px',\n margin: '0px',\n columns,\n });\n }\n\n const cardJson = {\n schema: '2.0',\n config: {\n update_multi: true,\n },\n header: {\n title: {\n content: card.title,\n tag: 'plain_text' as const,\n },\n template: 'blue',\n padding: '12px 8px 12px 8px',\n subtitle: {\n content: '',\n tag: 'plain_text' as const,\n },\n },\n body: {\n direction: 'vertical',\n elements,\n },\n };\n\n return JSON.stringify(cardJson);\n }\n\n /**\n * Format a message notification card\n */\n formatMessageCard(params: { title: string; content: string; meta?: string }): string {\n const { buildMessageCard } = require('./templates/message.js');\n return buildMessageCard(params);\n }\n\n /**\n * Format a permission request card\n */\n formatPermissionCard(params: { title: string; content: string; buttons: import('./types.js').PermissionButtonDef[] }): string {\n const { buildPermissionCard } = require('./templates/permission.js');\n return buildPermissionCard(params);\n }\n\n /**\n * Format a question request card\n */\n formatQuestionCard(params: { title: string; content: string; mode: import('./types.js').QuestionMode; items: import('./types.js').QuestionItem[]; requestId?: string }): string {\n const { buildQuestionCard } = require('./templates/question.js');\n return buildQuestionCard(params);\n }\n}\n","import type { Logger } from 'pino';\nimport { BaseChannel, type ExtendedChannelConfig } from '../../../core/channel/base.js';\nimport { Channel } from '../../../core/channel/registry.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { OutboundMessage } from '../../../core/bus/events.js';\nimport {\n mapOutboundMessageToAppEvent,\n type AppMappedOutboundEvent,\n} from './mapper.js';\n\nexport interface AppChannelTransport {\n sendEvent(channelId: string, event: AppMappedOutboundEvent): Promise<void> | void;\n}\n\nexport interface AppChannelConfig extends ExtendedChannelConfig {\n channel_id: string;\n transport?: AppChannelTransport;\n}\n\n@Channel('app')\nexport class AppChannel extends BaseChannel {\n readonly name = 'app';\n readonly displayName = 'App';\n readonly capabilities = {\n supportsButtons: false,\n supportsMarkdown: false,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n private readonly appConfig: AppChannelConfig;\n\n constructor(config: AppChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n this.appConfig = config;\n\n if (!this.appConfig.channel_id) {\n throw new Error('AppChannel requires channel_id in config');\n }\n }\n\n get channelInstanceId(): string {\n return this.appConfig.channel_id;\n }\n\n async start(): Promise<void> {\n await super.start();\n this.updateConnectionState('connected');\n }\n\n async stop(): Promise<void> {\n this.updateConnectionState('disconnected');\n await super.stop();\n }\n\n async send(message: OutboundMessage): Promise<void> {\n const targetChannelInstanceId = readChannelInstanceId(message);\n if (targetChannelInstanceId && targetChannelInstanceId !== this.channelInstanceId) {\n this.logger.debug(\n {\n channelInstanceId: this.channelInstanceId,\n targetChannelInstanceId,\n sessionId: message.context?.sessionId,\n },\n '[AppChannel] Skipping outbound message for another channel instance',\n );\n return;\n }\n\n const event = mapOutboundMessageToAppEvent(message);\n if (!event) {\n this.logger.debug(\n {\n channelInstanceId: this.channelInstanceId,\n eventType: message.context?.eventType,\n sessionId: message.context?.sessionId,\n },\n '[AppChannel] No outbound app event mapping for message',\n );\n return;\n }\n\n if (!this.appConfig.transport) {\n this.logger.warn(\n { channelInstanceId: this.channelInstanceId, eventName: event.name },\n '[AppChannel] Transport unavailable, dropping outbound event',\n );\n return;\n }\n\n await this.appConfig.transport.sendEvent(this.channelInstanceId, event);\n }\n\n protected isAllowed(_senderId: string): boolean {\n return false;\n }\n}\n\nfunction readChannelInstanceId(message: OutboundMessage): string | undefined {\n const channelInstanceId = message.metadata?.channelInstanceId;\n return typeof channelInstanceId === 'string' && channelInstanceId.length > 0\n ? channelInstanceId\n : undefined;\n}\n","import type { OutboundMessage } from '../../../core/bus/events.js';\nimport type { NotificationContext, PermissionRequestContext, QuestionRequestContext } from '../../../gateway/notification-context.js';\nimport type { AppProtocolEventFrame } from './types.js';\n\nexport interface AppChannelMapperOptions {\n createEventId?: () => string;\n createMessageId?: () => string;\n}\n\nexport type AppMappedOutboundEvent =\n | AppProtocolEventFrame<'message.created'>\n | AppProtocolEventFrame<'interaction.requested'>\n | AppProtocolEventFrame<'agent.finished'>;\n\nexport function mapOutboundMessageToAppEvent(\n message: OutboundMessage,\n options: AppChannelMapperOptions = {},\n): AppMappedOutboundEvent | null {\n const context = message.context;\n if (!context) {\n return null;\n }\n\n const timestamp = message.timestamp.toISOString();\n const eventId = options.createEventId?.() ?? createId('evt');\n\n switch (context.eventType) {\n case 'agent:message':\n return {\n type: 'event',\n eventId,\n name: 'message.created' as const,\n timestamp,\n payload: {\n sessionId: context.sessionId,\n message: {\n id: options.createMessageId?.() ?? createId('msg'),\n sessionId: context.sessionId,\n role: 'assistant' as const,\n type: 'text' as const,\n text: context.messageContent ?? '',\n createdAt: timestamp,\n status: 'completed' as const,\n metadata: {},\n },\n },\n };\n\n case 'turn:finished':\n return {\n type: 'event',\n eventId,\n name: 'agent.finished' as const,\n timestamp,\n payload: {\n sessionId: context.sessionId,\n reason: context.reason,\n lastAssistantMessage: context.lastAssistantMessage,\n summary: context.summary,\n },\n };\n\n case 'permission:request':\n case 'question:request':\n return mapInteractionRequested(context, eventId, timestamp);\n\n default:\n return null;\n }\n}\n\nfunction mapInteractionRequested(\n context: PermissionRequestContext | QuestionRequestContext,\n eventId: string,\n timestamp: string,\n): AppProtocolEventFrame<'interaction.requested'> | null {\n const interaction = context.interaction;\n const requestId = context.requestId ?? interaction?.requestId;\n const interactionType = interaction?.type;\n\n if (!interaction || !requestId || !interactionType) {\n return null;\n }\n\n return {\n type: 'event',\n eventId,\n name: 'interaction.requested',\n timestamp,\n payload: {\n interaction: {\n id: requestId,\n sessionId: context.sessionId,\n type: interactionType,\n title: interaction.title,\n description: interaction.description,\n status: 'pending',\n createdAt: timestamp,\n toolName: context.toolName,\n toolInput: context.toolInput,\n riskLevel: interaction.permission?.riskLevel,\n cwd: context.cwd,\n },\n },\n };\n}\n\nfunction createId(prefix: string): string {\n return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;\n}\n","import { WebSocketServer as NodeWebSocketServer, WebSocket } from 'ws';\nimport type { IncomingMessage } from 'http';\nimport { getLogger } from '../../../shared/logger.js';\nimport type { HttpServer } from '../../../server/http.js';\nimport type { AgentType } from '../../../core/adapter/types.js';\nimport type { AppProtocolErrorResponseFrame, AppProtocolEventFrame } from './types.js';\nimport type {\n AppChannelBusinessCommandFrame,\n AppChannelBusinessResponseFrame,\n AppChannelCommandHandler,\n AppChannelProtocolHandler,\n} from './protocol.js';\n\nconst logger = getLogger();\nconst DEFAULT_PATH = '/ws/channels/app';\nconst DEFAULT_PROTOCOL_VERSION = '1';\n\nexport interface AppChannelGateway {\n listRegisteredAgents(): Array<{ token: string; agentType: string }>;\n}\n\nexport interface AppChannelConnection {\n clientId: string;\n connectionId: string;\n channel: 'app';\n channelId: string;\n token: string;\n agentId: AgentType;\n protocolVersion: string;\n clientInfo?: Record<string, unknown>;\n authenticatedAt: string;\n}\n\ninterface AppChannelTransportCommandFrame {\n type: 'cmd';\n id: string;\n name: string;\n payload?: Record<string, unknown>;\n}\n\nexport interface AppChannelCommandContext {\n frame: AppChannelBusinessCommandFrame;\n connection: AppChannelConnection;\n request: IncomingMessage;\n}\n\nexport interface AppChannelWebSocketServerOptions {\n path?: string;\n protocolVersion?: string;\n commandHandler?: AppChannelCommandHandler;\n protocolHandler?: AppChannelProtocolHandler;\n}\n\ninterface ConnectedClient {\n clientId: string;\n ws: WebSocket;\n request: IncomingMessage;\n}\n\ninterface AuthPayload {\n channel?: unknown;\n channelId?: unknown;\n token?: unknown;\n protocolVersion?: unknown;\n clientInfo?: unknown;\n}\n\ninterface PingPayload {\n ts?: unknown;\n}\n\nexport class AppChannelWebSocketServer {\n private readonly path: string;\n private readonly protocolVersion: string;\n private readonly clients = new Map<string, ConnectedClient>();\n private readonly connections = new Map<string, AppChannelConnection>();\n private wss: NodeWebSocketServer | null = null;\n private unregisterUpgradeHandler: (() => void) | null = null;\n private clientIdCounter = 0;\n private connectionIdCounter = 0;\n\n constructor(\n private readonly httpServer: HttpServer,\n private readonly gateway: AppChannelGateway,\n private readonly options: AppChannelWebSocketServerOptions = {},\n ) {\n this.path = options.path ?? DEFAULT_PATH;\n this.protocolVersion = options.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;\n }\n\n async start(): Promise<void> {\n const server = this.httpServer.getServer();\n if (!server) {\n throw new Error('HTTP server must be started before app channel WebSocket server');\n }\n\n this.wss = new NodeWebSocketServer({ noServer: true });\n this.wss.on('connection', (ws, request) => {\n this.addClient(ws, request);\n });\n\n this.unregisterUpgradeHandler = this.httpServer.onUpgrade(this.path, (request, socket, head) => {\n this.wss?.handleUpgrade(request, socket, head, (ws) => {\n this.wss?.emit('connection', ws, request);\n });\n });\n\n logger.info({ path: this.path }, '[AppChannel] WebSocket server registered');\n }\n\n async stop(): Promise<void> {\n this.unregisterUpgradeHandler?.();\n this.unregisterUpgradeHandler = null;\n\n for (const client of this.clients.values()) {\n client.ws.close();\n }\n\n this.clients.clear();\n this.connections.clear();\n\n if (!this.wss) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n this.wss?.close(() => resolve());\n });\n\n this.wss = null;\n }\n\n listConnections(): AppChannelConnection[] {\n return Array.from(this.connections.values());\n }\n\n broadcastToChannel(channelId: string, event: AppProtocolEventFrame): void {\n for (const [clientId, connection] of this.connections) {\n if (connection.channelId === channelId) {\n this.send(clientId, event);\n }\n }\n }\n\n connectClientForTest(ws: WebSocket, request: IncomingMessage): void {\n this.addClient(ws, request);\n }\n\n private addClient(ws: WebSocket, request: IncomingMessage): void {\n const clientId = `app-client-${++this.clientIdCounter}`;\n this.clients.set(clientId, { clientId, ws, request });\n\n ws.on('message', (raw) => {\n void this.handleRawMessage(clientId, raw.toString());\n });\n\n ws.on('close', () => {\n this.removeClient(clientId);\n });\n\n ws.on('error', (error) => {\n logger.warn({ clientId, error }, '[AppChannel] WebSocket client error');\n this.removeClient(clientId);\n });\n }\n\n private removeClient(clientId: string): void {\n this.clients.delete(clientId);\n this.connections.delete(clientId);\n }\n\n private async handleRawMessage(clientId: string, raw: string): Promise<void> {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n this.sendError(clientId, 'invalid_json', 'INVALID_JSON', 'Invalid JSON frame');\n return;\n }\n\n if (!isCommandFrame(frame)) {\n const id = readFrameId(frame);\n this.sendError(clientId, id, 'INVALID_FRAME', 'Expected a command frame');\n return;\n }\n\n await this.handleCommand(clientId, frame);\n }\n\n private async handleCommand(clientId: string, frame: AppChannelTransportCommandFrame): Promise<void> {\n if (frame.name === 'auth') {\n this.handleAuth(clientId, frame);\n return;\n }\n\n if (frame.name === 'ping') {\n this.handlePing(clientId, frame);\n return;\n }\n\n const connection = this.connections.get(clientId);\n if (!connection) {\n this.sendError(\n clientId,\n frame.id,\n 'UNAUTHORIZED',\n `Authenticate with auth before sending ${frame.name}`,\n );\n return;\n }\n\n const client = this.clients.get(clientId);\n if (!client) {\n return;\n }\n\n const commandHandler = this.options.commandHandler ?? this.options.protocolHandler?.handleCommand;\n if (!commandHandler) {\n this.sendError(clientId, frame.id, 'NOT_IMPLEMENTED', `Unhandled command: ${frame.name}`);\n return;\n }\n\n try {\n const response = await commandHandler({\n frame: frame as AppChannelBusinessCommandFrame,\n connection,\n request: client.request,\n });\n\n if (response) {\n this.send(clientId, response);\n }\n } catch (error) {\n logger.error({ clientId, frameName: frame.name, error }, '[AppChannel] Command handler failed');\n this.sendError(clientId, frame.id, 'INTERNAL_ERROR', 'Failed to process command');\n }\n }\n\n private handleAuth(clientId: string, frame: AppChannelTransportCommandFrame): void {\n const payload = (frame.payload ?? {}) as AuthPayload;\n\n if (payload.channel !== 'app') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.channel must be app');\n return;\n }\n\n if (typeof payload.channelId !== 'string' || payload.channelId.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.channelId is required');\n return;\n }\n\n if (typeof payload.token !== 'string' || payload.token.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'auth payload.token is required');\n return;\n }\n\n if (payload.protocolVersion !== this.protocolVersion) {\n this.sendError(\n clientId,\n frame.id,\n 'UNSUPPORTED_PROTOCOL_VERSION',\n `Unsupported protocol version: ${String(payload.protocolVersion ?? '')}`,\n );\n return;\n }\n\n const registration = this.gateway\n .listRegisteredAgents()\n .find((candidate) => candidate.token === payload.token);\n\n if (!registration) {\n this.sendError(clientId, frame.id, 'AUTH_INVALID', 'Invalid app channel token');\n return;\n }\n\n const connectionId = `conn_${String(++this.connectionIdCounter).padStart(3, '0')}`;\n const connection: AppChannelConnection = {\n clientId,\n connectionId,\n channel: 'app',\n channelId: payload.channelId,\n token: payload.token,\n agentId: registration.agentType as AgentType,\n protocolVersion: this.protocolVersion,\n clientInfo: isRecord(payload.clientInfo) ? payload.clientInfo : undefined,\n authenticatedAt: new Date().toISOString(),\n };\n\n this.connections.set(clientId, connection);\n\n this.send(clientId, {\n type: 'res',\n id: frame.id,\n ok: true,\n result: {\n channel: 'app',\n channelId: connection.channelId,\n connectionId: connection.connectionId,\n protocolVersion: connection.protocolVersion,\n serverTime: new Date().toISOString(),\n defaultAgentId: connection.agentId,\n },\n });\n }\n\n private handlePing(clientId: string, frame: AppChannelTransportCommandFrame): void {\n const payload = (frame.payload ?? {}) as PingPayload;\n\n if (typeof payload.ts !== 'string' || payload.ts.trim() === '') {\n this.sendError(clientId, frame.id, 'INVALID_PAYLOAD', 'ping payload.ts is required');\n return;\n }\n\n this.send(clientId, {\n type: 'res',\n id: frame.id,\n ok: true,\n result: {\n ts: payload.ts,\n serverTime: new Date().toISOString(),\n },\n });\n }\n\n private send(clientId: string, frame: AppChannelBusinessResponseFrame | AuthSuccessResponseFrame | PingSuccessResponseFrame | AppProtocolEventFrame): void {\n const client = this.clients.get(clientId);\n if (!client || client.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n\n client.ws.send(JSON.stringify(frame));\n }\n\n private sendError(clientId: string, id: string, code: string, message: string): void {\n this.send(clientId, {\n type: 'res',\n id,\n ok: false,\n error: { code, message },\n } satisfies AppProtocolErrorResponseFrame);\n }\n}\n\nfunction isCommandFrame(value: unknown): value is AppChannelTransportCommandFrame {\n return (\n isRecord(value) &&\n value.type === 'cmd' &&\n typeof value.id === 'string' &&\n value.id.length > 0 &&\n typeof value.name === 'string' &&\n value.name.length > 0 &&\n (value.payload === undefined || isRecord(value.payload))\n );\n}\n\ninterface AuthSuccessResponseFrame {\n type: 'res';\n id: string;\n ok: true;\n result: {\n channel: 'app';\n channelId: string;\n connectionId: string;\n protocolVersion: string;\n serverTime: string;\n defaultAgentId: string;\n };\n}\n\ninterface PingSuccessResponseFrame {\n type: 'res';\n id: string;\n ok: true;\n result: {\n ts: string;\n serverTime: string;\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readFrameId(frame: unknown): string {\n if (isRecord(frame) && typeof frame.id === 'string' && frame.id.length > 0) {\n return frame.id;\n }\n\n return 'unknown';\n}\n","import { randomUUID } from 'crypto';\nimport type { InteractionResponseEvent } from '../../../core/bus/events.js';\nimport type { AgentType, CreateSessionOptions } from '../../../core/adapter/types.js';\nimport type { InteractionResponse } from '../../../core/interaction/types.js';\nimport { AppQueryService, type AppQueryGateway, type AppQueryPendingInteraction } from './query-service.js';\nimport type {\n AppProtocolCommandFrame,\n AppProtocolErrorResponseFrame,\n AppProtocolSuccessResponseFrame,\n} from './types.js';\nimport type { AppChannelConnection, AppChannelCommandContext } from './server.js';\n\nexport interface AppProtocolGateway extends AppQueryGateway {\n createSession(\n token: string,\n sessionId: string,\n options?: CreateSessionOptions,\n ): Promise<AppSession>;\n}\n\nexport interface AppProtocolBus {\n publishInteractionResponse(\n response: Omit<InteractionResponseEvent, 'type' | 'timestamp'>,\n ): void;\n}\n\nexport interface AppChannelCommandHandlerOptions {\n gateway: AppProtocolGateway;\n queryService?: AppQueryService;\n bus?: AppProtocolBus;\n createSessionId?: () => string;\n createMessageId?: () => string;\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[];\n}\n\nexport type AppChannelBusinessCommandFrame =\n | AppProtocolCommandFrame<'session.create'>\n | AppAgentListCommandFrame\n | AppSessionListCommandFrame\n | AppMessageSendCommandFrame\n | AppInteractionRespondCommandFrame;\n\nexport type AppChannelBusinessResponseFrame =\n | AppProtocolSuccessResponseFrame\n | AppProtocolErrorResponseFrame;\n\nexport type AppChannelCommandHandler =\n (context: AppChannelCommandContext) => Promise<AppChannelBusinessResponseFrame | void> | AppChannelBusinessResponseFrame | void;\n\nexport interface AppChannelProtocolHandler {\n handleCommand: AppChannelCommandHandler;\n}\n\nconst MAX_SUCCESSFUL_MESSAGE_SEND_RESULTS = 32;\n\nexport function createAppChannelProtocolHandler(\n options: AppChannelCommandHandlerOptions,\n): AppChannelProtocolHandler {\n return {\n handleCommand: createAppChannelCommandHandler(options),\n };\n}\n\nexport function createAppChannelCommandHandler(\n options: AppChannelCommandHandlerOptions,\n): AppChannelCommandHandler {\n const queryService =\n options.queryService ??\n new AppQueryService(options.gateway, {\n listPendingInteractions: options.listPendingInteractions,\n });\n const sentMessageResults = new Map<string, AppMessageSendRecord>();\n const inFlightMessageResults = new Map<string, AppMessageSendInFlight>();\n\n return async ({ frame, connection }) => {\n switch (frame.name) {\n case 'agent.list':\n return ok(frame.id, {\n items: queryService.listAgents(),\n });\n\n case 'session.list':\n return handleSessionList(frame, connection, options.gateway, queryService);\n\n case 'session.create':\n return handleSessionCreate(frame, connection, options.gateway, queryService, options.createSessionId);\n\n case 'message.send':\n return handleMessageSend(\n frame,\n connection,\n options.gateway,\n sentMessageResults,\n inFlightMessageResults,\n options.createMessageId,\n );\n\n case 'interaction.respond':\n return handleInteractionRespond(frame, connection, options);\n\n default: {\n const fallback = frame as { id: string; name?: string };\n return error(fallback.id, 'NOT_IMPLEMENTED', `Unhandled command: ${String(fallback.name)}`);\n }\n }\n };\n}\n\nasync function handleSessionList(\n frame: AppSessionListCommandFrame,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n queryService: AppQueryService,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (!isAgentId(payload.agentId)) {\n return error(frame.id, 'INVALID_PAYLOAD', 'session.list payload.agentId is required');\n }\n\n const sessions = queryService\n .listSessions(payload.agentId)\n .filter((session) => isOwnedSession(gateway.getSession(session.id), connection));\n const limit = typeof payload.limit === 'number' && payload.limit > 0 ? payload.limit : sessions.length;\n\n return ok(frame.id, {\n items: sessions.slice(0, limit),\n pageInfo: {\n nextCursor: null,\n hasMore: false,\n },\n });\n}\n\nasync function handleSessionCreate(\n frame: AppProtocolCommandFrame<'session.create'>,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n queryService: AppQueryService,\n createSessionId?: () => string,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n\n if (!isAgentId(payload.agentId)) {\n return error(frame.id, 'INVALID_PAYLOAD', 'session.create payload.agentId is required');\n }\n\n if (payload.agentId !== connection.agentId) {\n return error(\n frame.id,\n 'INVALID_PAYLOAD',\n 'session.create payload.agentId must match the authenticated agent',\n );\n }\n\n const sessionId = createSessionId?.() ?? randomUUID();\n const metadata: Record<string, unknown> = {\n channel: connection.channel,\n channelId: connection.channelId,\n channelInstanceId: connection.channelId,\n };\n\n if (typeof payload.title === 'string' && payload.title.trim() !== '') {\n metadata.title = payload.title;\n }\n\n await gateway.createSession(connection.token, sessionId, { metadata, cwd: payload.cwd });\n const session = queryService.getSessionSummary(sessionId);\n if (!session) {\n return error(frame.id, 'INTERNAL_ERROR', `Created session could not be loaded: ${sessionId}`);\n }\n\n return ok(frame.id, { session });\n}\n\nasync function handleMessageSend(\n frame: AppMessageSendCommandFrame,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n sentMessageResults: Map<string, AppMessageSendRecord>,\n inFlightMessageResults: Map<string, AppMessageSendInFlight>,\n createMessageId?: () => string,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (typeof payload.sessionId !== 'string' || payload.sessionId.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'message.send payload.sessionId is required');\n }\n\n if (payload.message?.type !== 'text' || typeof payload.message.text !== 'string' || payload.message.text.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'message.send payload.message.text is required');\n }\n\n const session = gateway.getSession(payload.sessionId);\n if (!session || !isOwnedSession(session, connection)) {\n return error(frame.id, 'NOT_FOUND', `Unknown session: ${payload.sessionId}`);\n }\n\n const providedMessageId =\n typeof payload.message.id === 'string' && payload.message.id.trim() !== ''\n ? payload.message.id\n : undefined;\n const messageText = payload.message.text;\n const dedupeKey = providedMessageId ? `${payload.sessionId}:${providedMessageId}` : null;\n if (dedupeKey) {\n const existing = sentMessageResults.get(dedupeKey);\n if (existing) {\n if (existing.messageText !== messageText) {\n return error(\n frame.id,\n 'CONFLICT',\n 'message.send payload.message.text must match the original text for this message.id',\n );\n }\n\n return ok(frame.id, existing.outcome);\n }\n\n const inFlight = inFlightMessageResults.get(dedupeKey);\n if (inFlight) {\n if (inFlight.messageText !== messageText) {\n return error(\n frame.id,\n 'CONFLICT',\n 'message.send payload.message.text must match the original text for this message.id',\n );\n }\n\n const outcome = await inFlight.promise;\n return ok(frame.id, outcome);\n }\n }\n\n const messageId = providedMessageId ?? createMessageId?.() ?? randomUUID();\n const resultPromise = (async (): Promise<AppMessageSendOutcome> => {\n await session.sendCommand({\n type: 'user:message',\n content: messageText,\n });\n\n return {\n accepted: true,\n sessionId: payload.sessionId,\n messageId,\n };\n })();\n\n if (dedupeKey) {\n inFlightMessageResults.set(dedupeKey, {\n messageText,\n promise: resultPromise,\n });\n }\n\n try {\n const outcome = await resultPromise;\n if (dedupeKey) {\n inFlightMessageResults.delete(dedupeKey);\n sentMessageResults.set(dedupeKey, {\n messageText,\n outcome,\n });\n if (sentMessageResults.size > MAX_SUCCESSFUL_MESSAGE_SEND_RESULTS) {\n const oldestKey = sentMessageResults.keys().next().value as string | undefined;\n if (oldestKey) {\n sentMessageResults.delete(oldestKey);\n }\n }\n }\n\n return ok(frame.id, outcome);\n } catch (error) {\n if (dedupeKey) {\n inFlightMessageResults.delete(dedupeKey);\n }\n\n throw error;\n }\n}\n\nasync function handleInteractionRespond(\n frame: AppInteractionRespondCommandFrame,\n connection: AppChannelConnection,\n options: AppChannelCommandHandlerOptions,\n): Promise<AppChannelBusinessResponseFrame> {\n const payload = frame.payload;\n if (typeof payload.interactionId !== 'string' || payload.interactionId.trim() === '') {\n return error(frame.id, 'INVALID_PAYLOAD', 'interaction.respond payload.interactionId is required');\n }\n\n const response = toInteractionResponse(payload.interactionId, payload.response);\n if (!response) {\n return error(frame.id, 'INVALID_PAYLOAD', 'interaction.respond payload.response is invalid');\n }\n\n const pendingSessionId = findPendingInteractionSessionId(\n payload.interactionId,\n connection,\n options.gateway,\n options.listPendingInteractions,\n );\n if (!pendingSessionId) {\n return error(frame.id, 'NOT_FOUND', `Unknown interaction: ${payload.interactionId}`);\n }\n\n if (options.bus) {\n options.bus.publishInteractionResponse({\n requestId: payload.interactionId,\n response,\n reason: response.message,\n });\n } else {\n return error(frame.id, 'NOT_IMPLEMENTED', 'Interaction response transport is unavailable');\n }\n\n return ok(frame.id, {\n accepted: true,\n interactionId: payload.interactionId,\n });\n}\n\nfunction findPendingInteractionSessionId(\n interactionId: string,\n connection: AppChannelConnection,\n gateway: AppProtocolGateway,\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[],\n): string | null {\n if (!listPendingInteractions) {\n return null;\n }\n\n const sessions = gateway.listSessions({ agentType: connection.agentId, includeEnded: true });\n for (const sessionInfo of sessions) {\n const session = gateway.getSession(sessionInfo.id);\n if (!session || !isOwnedSession(session, connection)) {\n continue;\n }\n\n const pendingInteractions = listPendingInteractions(sessionInfo.id);\n if (pendingInteractions.some((interaction) => interaction.id === interactionId)) {\n return sessionInfo.id;\n }\n }\n\n return null;\n}\n\nfunction toInteractionResponse(\n interactionId: string,\n payload: AppInteractionRespondCommandFrame['payload']['response'],\n): InteractionResponse | null {\n if (!isInteractionAction(payload.action)) {\n return null;\n }\n\n return {\n requestId: interactionId,\n action: payload.action,\n message: typeof payload.message === 'string' ? payload.message : undefined,\n selectedValues: Array.isArray(payload.selectedValues) ? payload.selectedValues : undefined,\n customInput: typeof payload.customInput === 'string' ? payload.customInput : undefined,\n updatedInput: isRecord(payload.updatedInput) ? payload.updatedInput : undefined,\n permissionUpdates: Array.isArray(payload.permissionUpdates) ? payload.permissionUpdates : undefined,\n permanent: typeof payload.permanent === 'boolean' ? payload.permanent : undefined,\n };\n}\n\nfunction isOwnedSession(\n session: AppSession | undefined,\n connection: AppChannelConnection,\n): boolean {\n if (!session) {\n return false;\n }\n\n if (session.token && session.token !== connection.token) {\n return false;\n }\n\n const metadata = session.metadata ?? {};\n const channelId = readString(metadata.channelId) ?? readString(metadata.channelInstanceId);\n return channelId ? channelId === connection.channelId : true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction readString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\nfunction isAgentId(value: unknown): value is AgentType {\n return value === 'claude' || value === 'codex';\n}\n\nfunction isInteractionAction(value: unknown): value is InteractionResponse['action'] {\n return value === 'allow' || value === 'deny' || value === 'select' || value === 'input';\n}\n\nfunction ok<Result>(id: string, result: Result): AppProtocolSuccessResponseFrame {\n return {\n type: 'res',\n id,\n ok: true,\n result: result as unknown,\n } as AppProtocolSuccessResponseFrame;\n}\n\nfunction error(id: string, code: string, message: string): AppProtocolErrorResponseFrame {\n return {\n type: 'res',\n id,\n ok: false,\n error: { code, message },\n };\n}\n\ntype AppSession = NonNullable<ReturnType<AppQueryGateway['getSession']>>;\n\nexport type AppAgentListCommandFrame = AppProtocolCommandFrame<'agent.list'>;\nexport type AppSessionListCommandFrame = AppProtocolCommandFrame<'session.list'>;\nexport type AppMessageSendCommandFrame = AppProtocolCommandFrame<'message.send'>;\n\ntype AppMessageSendOutcome = {\n accepted: true;\n sessionId: string;\n messageId: string;\n};\ntype AppMessageSendRecord = {\n messageText: string;\n outcome: AppMessageSendOutcome;\n};\ntype AppMessageSendInFlight = {\n messageText: string;\n promise: Promise<AppMessageSendOutcome>;\n};\nexport type AppInteractionRespondCommandFrame = AppProtocolCommandFrame<'interaction.respond'>;\n\nexport type AppProtocolSessionCreateResponseFrame = AppProtocolSuccessResponseFrame<'session.create'>;\nexport type AppAgentListResponseFrame = AppProtocolSuccessResponseFrame<'agent.list'>;\nexport type AppSessionListResponseFrame = AppProtocolSuccessResponseFrame<'session.list'>;\nexport type AppMessageSendResponseFrame = AppProtocolSuccessResponseFrame<'message.send'>;\nexport type AppInteractionRespondResponseFrame = AppProtocolSuccessResponseFrame<'interaction.respond'>;\n","import type { AgentType } from '../../../core/adapter/types.js';\nimport type { Session } from '../../../core/session/Session.js';\nimport type { SessionInfo } from '../../../core/session/types.js';\n\nexport interface AppQueryAgent {\n id: AgentType;\n type: AgentType;\n title: string;\n enabled: boolean;\n available: boolean;\n default: boolean;\n capabilities: {\n chat: boolean;\n multiTurn: boolean;\n permission: boolean;\n question: boolean;\n streaming: boolean;\n };\n}\n\nexport interface AppQueryPendingInteraction {\n id: string;\n kind: string;\n title: string | null;\n}\n\nexport interface AppQueryMessage {\n id: string;\n role: string;\n content: string | null;\n createdAt: string | null;\n}\n\nexport interface AppQuerySessionSummary {\n id: string;\n agentId: AgentType;\n title: string | null;\n status: SessionInfo['status'];\n createdAt: string;\n updatedAt: string;\n lastMessageAt: string | null;\n messageCount: number | null;\n summary: string | null;\n pendingInteractionCount: number | null;\n metadata: {\n workspacePath: string | null;\n };\n}\n\nexport interface AppQuerySessionDetail {\n session: AppQuerySessionSummary;\n messages: AppQueryMessage[];\n pendingInteractions: AppQueryPendingInteraction[];\n}\n\nexport interface AppQueryGateway {\n listRegisteredAgents(): Array<{ token: string; agentType: AgentType }>;\n listSessions(filter?: { agentType?: AgentType; includeEnded?: boolean }): SessionInfo[];\n getSession(sessionId: string): Session | undefined;\n}\n\nexport interface AppQueryServiceDependencies {\n defaultAgentId?: AgentType;\n listMessages?: (sessionId: string) => AppQueryMessage[];\n listPendingInteractions?: (sessionId: string) => AppQueryPendingInteraction[];\n}\n\nconst DEFAULT_CAPABILITIES = {\n chat: true,\n multiTurn: true,\n permission: true,\n question: true,\n streaming: false,\n} as const;\n\nexport class AppQueryService {\n constructor(\n private readonly gateway: AppQueryGateway,\n private readonly dependencies: AppQueryServiceDependencies = {},\n ) {}\n\n listAgents(): AppQueryAgent[] {\n const registrations = this.gateway.listRegisteredAgents();\n const agentTypes = [...new Set(registrations.map((registration) => registration.agentType))].sort() as AgentType[];\n const defaultAgentId = this.resolveDefaultAgentId(agentTypes);\n\n return agentTypes.map((agentType) => ({\n id: agentType,\n type: agentType,\n title: toAgentTitle(agentType),\n enabled: true,\n available: true,\n default: agentType === defaultAgentId,\n capabilities: { ...DEFAULT_CAPABILITIES },\n }));\n }\n\n listSessions(agentId: AgentType): AppQuerySessionSummary[] {\n return this.gateway\n .listSessions({ agentType: agentId, includeEnded: true })\n .slice()\n .sort((left, right) => right.updatedAt - left.updatedAt)\n .map((sessionInfo) => this.toSessionSummary(sessionInfo, this.gateway.getSession(sessionInfo.id)));\n }\n\n getSessionSummary(sessionId: string): AppQuerySessionSummary | null {\n return this.getSessionDetail(sessionId)?.session ?? null;\n }\n\n getSessionDetail(sessionId: string): AppQuerySessionDetail | null {\n const session = this.gateway.getSession(sessionId);\n const sessionInfo =\n (session ? session.toInfo() : undefined) ??\n this.gateway.listSessions({ includeEnded: true }).find((candidate) => candidate.id === sessionId);\n\n if (!sessionInfo) {\n return null;\n }\n\n const pendingInteractions = this.dependencies.listPendingInteractions?.(sessionId) ?? [];\n\n return {\n session: this.toSessionSummary(sessionInfo, session, pendingInteractions),\n messages: this.dependencies.listMessages?.(sessionId) ?? [],\n pendingInteractions,\n };\n }\n\n private toSessionSummary(\n sessionInfo: SessionInfo,\n session?: Session,\n pendingInteractions: AppQueryPendingInteraction[] = this.dependencies.listPendingInteractions?.(sessionInfo.id) ?? [],\n ): AppQuerySessionSummary {\n const metadata = session?.metadata ?? {};\n\n return {\n id: sessionInfo.id,\n agentId: sessionInfo.agentType,\n title: readString(metadata.title),\n status: session?.getStatus() ?? sessionInfo.status,\n createdAt: toIsoString(sessionInfo.createdAt),\n updatedAt: toIsoString(sessionInfo.updatedAt),\n lastMessageAt: null,\n messageCount: null,\n summary: readString(metadata.summary),\n pendingInteractionCount: this.dependencies.listPendingInteractions ? pendingInteractions.length : null,\n metadata: {\n workspacePath: readString(sessionInfo.cwd),\n },\n };\n }\n\n private resolveDefaultAgentId(agentTypes: AgentType[]): AgentType | undefined {\n if (this.dependencies.defaultAgentId && agentTypes.includes(this.dependencies.defaultAgentId)) {\n return this.dependencies.defaultAgentId;\n }\n\n if (agentTypes.length === 1) {\n return agentTypes[0];\n }\n\n return undefined;\n }\n}\n\nfunction readString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction toIsoString(value: number): string {\n return new Date(value).toISOString();\n}\n\nfunction toAgentTitle(agentType: AgentType): string {\n return agentType\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join(' ');\n}\n","import { readdirSync, readFileSync } from 'fs';\nimport { join, extname, basename } from 'path';\nimport type { Logger } from 'pino';\nimport { getLogger } from '../../shared/logger.js';\nimport type { Gateway } from '../../gateway/index.js';\n\ninterface ClaudeSessionFile {\n pid: number;\n sessionId: string;\n cwd: string;\n startedAt: number;\n kind: string;\n entrypoint: string;\n}\n\nexport class SessionRecoveryService {\n private logger: Logger;\n private sessionsDir: string;\n\n constructor(sessionsDir: string = join(process.env.HOME || '', '.claude', 'sessions'), logger?: Logger) {\n this.sessionsDir = sessionsDir;\n this.logger = logger ?? getLogger();\n }\n\n /**\n * Scan Claude sessions directory and restore active sessions.\n * Only sessions with a live process (verified via kill -0) are restored.\n * Skip publish to avoid duplicate session:start notifications.\n */\n async recover(gateway: Gateway): Promise<void> {\n const files = this.listSessionFiles();\n if (files.length === 0) {\n this.logger.debug('No Claude session files found, nothing to recover');\n return;\n }\n\n this.logger.info({ count: files.length }, 'Scanning Claude sessions for recovery');\n let recovered = 0;\n let skippedDead = 0;\n\n for (const file of files) {\n const sessionData = this.parseSessionFile(file);\n if (!sessionData) {\n this.logger.warn({ file }, 'Failed to parse session file, skipping');\n continue;\n }\n\n if (!this.isProcessAlive(sessionData.pid)) {\n this.logger.debug({ sessionId: sessionData.sessionId, pid: sessionData.pid }, 'Claude process dead, skipping session recovery');\n skippedDead++;\n continue;\n }\n\n const existing = gateway.getSession(sessionData.sessionId);\n if (existing) {\n this.logger.debug({ sessionId: sessionData.sessionId }, 'Session already exists, skipping recovery');\n continue;\n }\n\n try {\n const agentRegistry = gateway.getAgentRegistry();\n const agents = agentRegistry.listRegisteredAgents();\n const claudeAgent = agents.find((a) => a.agentType === 'claude');\n if (!claudeAgent) {\n this.logger.warn('No claude agent registered, cannot recover sessions');\n continue;\n }\n\n await gateway.createSession(\n claudeAgent.token,\n sessionData.sessionId,\n {\n metadata: { kind: sessionData.kind, entrypoint: sessionData.entrypoint },\n cwd: sessionData.cwd,\n createdAt: sessionData.startedAt,\n },\n true // skipPublishSessionStart — don't duplicate start notification\n );\n\n recovered++;\n this.logger.info(\n { sessionId: sessionData.sessionId, cwd: sessionData.cwd, pid: sessionData.pid },\n 'Session recovered from Claude sessions directory'\n );\n } catch (err) {\n this.logger.warn(\n { sessionId: sessionData.sessionId, error: err instanceof Error ? err.message : String(err) },\n 'Failed to recover session'\n );\n }\n }\n\n this.logger.info(\n { recovered, skippedDead, total: files.length },\n 'Session recovery complete'\n );\n }\n\n private listSessionFiles(): string[] {\n try {\n return readdirSync(this.sessionsDir)\n .filter((f) => extname(f) === '.json')\n .map((f) => join(this.sessionsDir, f));\n } catch (err) {\n this.logger.debug(\n { dir: this.sessionsDir, error: err instanceof Error ? err.message : String(err) },\n 'Could not read Claude sessions directory'\n );\n return [];\n }\n }\n\n private parseSessionFile(path: string): ClaudeSessionFile | null {\n try {\n const raw = readFileSync(path, 'utf-8');\n const data = JSON.parse(raw) as ClaudeSessionFile;\n if (!data.sessionId || typeof data.pid !== 'number') {\n return null;\n }\n return data;\n } catch (err) {\n this.logger.warn(\n { file: path, error: err instanceof Error ? err.message : String(err) },\n 'Failed to parse session file'\n );\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n if (pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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","names":["mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","homedir","logger","readFileSync","existsSync","i","acc","ext","start","final","ext","path","qmark","star","regExpEscape","i","match","existsSync","readFileSync","error","path","logger","logger","filter","match","t","error","error","resolve","randomUUID","logger","readFile","join","resolve","existsSync","resolve","error","error","resolve","existsSync","resolve","randomUUID","randomUUID","spawn","createInterface","path","error","filter","defaults","resolve","match","randomUUID","readdir","readFile","join","existsSync","match","logger","path","resolve","error","match","URL","VERSION","logger","path","resolve","URL","error","filter","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","join","path","existsSync","readFileSync","error","randomUUID","randomUUID","resolve","error","readFileSync","existsSync","join","homedir","error","logger","error","resolve","writeFileSync","join","homedir","TOML","logger","logger","logger","error","logger","logger","oldChannelId","bindingService","bindingService","process","formatDuration","logger","logger","logger","logger","bindingService","logger","logger","error","resolve","formatDuration","val","formatDuration","_a","logger","error","requestId","allowedUsersForRequest","options","_init","_a","logger","error","match","buildMessageCard","buildPermissionCard","buildQuestionCard","REQUEST_ID_REGEX","_init","_a","logger","error","formatDuration","_init","_a","logger","WebSocket","logger","resolve","error","WebSocket","randomUUID","randomUUID","error","isRecord","readString","readdirSync","readFileSync","join","join","logger","readdirSync","path","readFileSync","VERSION","homedir","logger","bindingService","error"]}