handsoff 0.1.1 → 0.1.2-beta.0

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/config.ts","../../src/gateway/interaction-service.ts","../../src/gateway/index.ts","../../src/gateway/publisher.ts","../../src/adapters/agent/claude/ClaudeAdapter.ts","../../src/core/session-scanner/registry.ts","../../src/adapters/agent/claude/hook/HookServer.ts","../../src/core/event/types.ts","../../src/core/adapter/protocol/claude/ClaudeEventMapper.ts","../../src/adapters/agent/claude/scanner.ts","../../src/core/adapter/protocol/claude/ClaudeProtocolHandler.ts","../../src/core/adapter/protocol/permissionUtils.ts","../../src/adapters/agent/codex/CodexAppServerAdapter.ts","../../src/adapters/agent/codex/CodexProtocolHandler.ts","../../src/adapters/agent/codex/codexAppServerClient.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/core/event/ack.ts","../../src/shared/credentials.ts","../../src/adapters/interaction/queue.ts","../../src/core/bus/index.ts","../../src/core/event/schema.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/adapters/agent/claude/session-context.ts","../../src/core/channel/base.ts","../../src/adapters/channels/telegram/bot.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/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.onAgentMessage((e) => this.write(e.sessionId, 'agent:message', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolStart((e) => this.write(e.sessionId, 'tool:start', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolEnd((e) => this.write(e.sessionId, 'tool:end', '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.onFinished((e) => this.write(e.sessionId, '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 handle = await adapter.createSession({\n ...options,\n });\n\n const session = new Session({\n id: sessionId,\n agentType,\n adapter,\n protocolHandler: adapter.protocolHandler,\n handle,\n token: options?.token,\n metadata: options?.metadata,\n });\n\n this.sessions.set(sessionId, session);\n this.logger.info({ sessionId, agentType, 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 } from '../adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../adapter/protocol/ProtocolHandler.js';\nimport type { AgentCommand, SessionHandle, 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 protocolHandler: ProtocolHandler;\n readonly createdAt: number;\n\n private status: 'active' | 'closed' | 'archived' = 'active';\n private handle: SessionHandle;\n\n constructor(options: {\n id: string;\n agentType: 'claude' | 'codex';\n adapter: AgentAdapter;\n protocolHandler: ProtocolHandler;\n handle: SessionHandle;\n token?: string;\n metadata?: Record<string, unknown>;\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.protocolHandler = options.protocolHandler;\n this.handle = options.handle;\n this.createdAt = 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.handle.sendCommand(command);\n }\n\n async close(): Promise<void> {\n if (this.status !== 'active') {\n return;\n }\n // Abort any pending protocol requests to prevent memory leaks\n this.protocolHandler.abort();\n await this.handle.close();\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 };\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 if (!rule.pattern) {\n return true;\n }\n\n // For Bash tools, match against the command\n if (toolName === 'Bash' && 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, rule.pattern) || matchesPattern(firstWord, rule.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, rule.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'].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\nconst DEFAULT_LOW_RISK_TOOLS = ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'] as const;\n\n/**\n * Check if a tool is low-risk (Claude Code won't prompt for permission)\n * @param toolName The name of the tool to check\n * @param lowRiskTools Optional custom list of low-risk tools\n */\nexport function isLowRiskTool(toolName: string, lowRiskTools: readonly string[] = DEFAULT_LOW_RISK_TOOLS): boolean {\n return lowRiskTools.includes(toolName);\n}\n\n/**\n * Check only deny rules for low-risk tools\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 { 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 default_agent: string;\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: string;\n binary: string;\n work_dir: string;\n model: string;\n permission_mode: string;\n}\n\nexport interface AgentPermissionConfig {\n lowRiskTools: string[];\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n sandbox_mode: 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}\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 ChannelsConfig {\n app?: AppChannelConfig;\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig & { permission?: AgentPermissionConfig };\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 channels?: ChannelsConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n default_agent: 'claude',\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 },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n permission: {\n lowRiskTools: ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'],\n },\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n sandbox_mode: '',\n },\n },\n channels: {},\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 },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n permission: {\n ...DEFAULT_CONFIG.agent.claude!.permission,\n ...(raw.agent?.claude?.permission || {}),\n },\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 sandbox_mode: raw.agent?.codex?.sandbox_mode || DEFAULT_CONFIG.agent.codex!.sandbox_mode,\n },\n },\n channels: {\n ...DEFAULT_CONFIG.channels,\n ...(raw.channels || {}),\n app: raw.channels?.app\n ? {\n enabled: raw.channels.app.enabled === true,\n channel_id: String(raw.channels.app.channel_id || ''),\n auth_token: String(raw.channels.app.auth_token || ''),\n heartbeat_interval_ms: raw.channels.app.heartbeat_interval_ms\n ? parseInt(String(raw.channels.app.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channels.app.notify_types)\n ? raw.channels.app.notify_types.map(String)\n : undefined,\n }\n : DEFAULT_CONFIG.channels?.app,\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 { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadPermissionsConfig, checkPermission, checkDenyOnly, isLowRiskTool } from '../shared/permissions.js';\nimport { loadConfig } from '../config.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 (agentType === 'codex') {\n // Codex approvals should be resolved by the bound channel, not Claude's low-risk rules.\n return { immediate: false };\n }\n\n if (permissionMode === 'bypassPermissions') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'permissionMode is bypassPermissions' },\n };\n }\n\n const config = loadConfig();\n const projectConfig = cwd ? loadPermissionsConfig(cwd) : null;\n\n if (isLowRiskTool(toolName, config.agent?.claude?.permission?.lowRiskTools)) {\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: 'Low-risk tool, no deny match' },\n };\n }\n\n if (permissionMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit'].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.metadata.sessionId || envelope.sessionId);\n const toolName = String(payload.toolName);\n const toolInput = payload.toolInput || {};\n const permissionMode = (envelope.metadata.permission_mode as string) || 'auto';\n const cwd = (envelope.metadata.cwd as string) || '';\n const agentType = String(envelope.metadata.agentType || 'claude');\n\n logger.info({ sessionId, toolName, type: envelope.type }, '[Interaction] Request received');\n\n // Determine interaction type\n const interactionType = envelope.type === 'question:request' ? 'question' : 'permission';\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 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 } from '../core/adapter/types.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport type { 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';\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 */\nexport class Gateway {\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 */\n async createSession(\n token: string,\n sessionId: string,\n metadata?: Record<string, unknown>\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 { sessionId, metadata, token }\n );\n\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 payload: metadata ?? {},\n metadata: { agentType: session.agentType, transportType: session.adapter.transportType },\n },\n session\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 endSession(sessionId: string): void {\n // For now, closeSession is async but endSession is sync in old API\n // We need to handle this - for HTTP context, we'll await it\n this.sessionManager.closeSession(sessionId).catch((err) => {\n console.error(`Failed to end session ${sessionId}:`, err);\n });\n }\n\n /**\n * Handle an incoming event from an agent\n */\n async handleEvent(\n token: string,\n envelope: AgentEventEnvelope\n ): Promise<InteractionResponse | undefined> {\n const sessionId = envelope.sessionId;\n if (!sessionId) {\n return;\n }\n\n // Validate token\n if (!this.agentRegistry.isTokenRegistered(token)) {\n return;\n }\n\n let session = this.sessionManager.getSession(sessionId);\n if (!session) {\n try {\n session = await this.createSession(\n token,\n sessionId,\n envelope.payload as Record<string, unknown>\n );\n } catch {\n return;\n }\n }\n\n if (envelope.type === 'session:end') {\n this.sessionManager.closeSession(sessionId).catch((err) => {\n console.error(`Failed to close session ${sessionId}:`, err);\n });\n }\n\n // Handle interaction requests (permission, question, etc.)\n if (envelope.type === 'permission:request' || envelope.type === 'question:request') {\n this.eventPublisher.publish(envelope, session);\n return await this.interactionService.evaluate(envelope);\n }\n\n this.eventPublisher.publish(envelope, session);\n return undefined;\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\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 this.bus.publishSessionStart({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n agentType: session.agentType,\n });\n break;\n case 'session:end':\n this.bus.publishSessionEnd({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n });\n break;\n case 'finished':\n this.bus.publishFinished({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n lastAssistantMessage: envelope.payload.lastAssistantMessage as string | undefined,\n transcriptPath: envelope.payload.transcriptPath as string | undefined,\n });\n break;\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:post':\n this.bus.publishToolPost({\n sessionId: session.id,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n output: envelope.payload.output as string | 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 }\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/ClaudeAdapter.ts\n// Unified Claude Adapter using AgentEvent as internal format\n\nimport { randomUUID } from 'crypto';\nimport type { Logger } from 'pino';\nimport type {\n AgentAdapter,\n AgentEventEnvelope,\n CreateSessionOptions,\n SessionHandle,\n SessionInfo,\n PermissionResponseCommand,\n} from '../../../core/adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport type { Gateway } from '../../../gateway/index.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\nimport { HookServer } from './hook/HookServer.js';\nimport type { AgentEvent } from '../../../core/event/types.js';\nimport { ClaudeSessionScanner } from './scanner.js';\nimport { ClaudeProtocolHandler } from '../../../core/adapter/protocol/claude/ClaudeProtocolHandler.js';\nimport {\n mapClaudeToAgentEvent,\n mapClaudeToAgentEventEnvelope,\n isClaudeHookEventType,\n} from './ClaudeEventMapper.js';\n\n/**\n * Claude Adapter\n *\n * Uses AgentEvent as the internal event format.\n * Supports both legacy and unified hook URL formats.\n *\n * Event flow:\n * Claude Code → HookServer → AgentEvent → (Optional: AgentEventEnvelope) → Gateway\n *\n * Benefits:\n * - Single event pipeline\n * - Standardized AgentEvent format for all internal processing\n * - Backward compatible with existing Gateway interface\n */\nexport class ClaudeAdapter implements AgentAdapter {\n readonly agentType = 'claude';\n readonly transportType = 'hook';\n readonly version = '2.0.0';\n readonly protocolHandler: ProtocolHandler = new ClaudeProtocolHandler();\n\n private hookServer: HookServer | null = null;\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private agentEventHandler: ((event: AgentEvent) => void) | null = null;\n private sessions: Map<string, SessionInfo> = new Map();\n private pendingPermissionHandlers: Map<string, (decision: PermissionResponseCommand) => void> = new Map();\n private port: number = 0;\n private token: string = '';\n private _initializing: Promise<void> | null = null;\n private static scanner: ClaudeSessionScanner | null = null;\n private logger: Logger | undefined;\n private bus?: EventBus;\n private gateway?: Gateway;\n private inboundUnsubscribe: (() => void) | null = null;\n\n constructor(options?: { logger?: Logger; bus?: EventBus; gateway?: Gateway; token?: string }) {\n this.logger = options?.logger;\n this.bus = options?.bus;\n this.gateway = options?.gateway;\n this.token = options?.token ?? '';\n }\n\n async initialize(): Promise<void> {\n // Register Claude SessionScanner\n if (!ClaudeAdapter.scanner) {\n ClaudeAdapter.scanner = new ClaudeSessionScanner();\n SessionScannerRegistry.getInstance().register(ClaudeAdapter.scanner);\n this.logger?.info('Claude session scanner registered');\n }\n\n // Register with AgentAdapterRegistry for discovery\n AgentAdapterRegistry.getInstance().register(this);\n this.logger?.info('Claude adapter initialized');\n\n if (this.bus && !this.inboundUnsubscribe) {\n this.inboundUnsubscribe = this.bus.onInbound((message) => this.handleInboundMessage(message));\n this.logger?.debug('Subscribed Claude adapter to inbound messages');\n }\n }\n\n async shutdown(): Promise<void> {\n this.logger?.info('Claude adapter shutting down');\n await this.hookServer?.stop();\n this.sessions.clear();\n this.pendingPermissionHandlers.clear();\n this.inboundUnsubscribe?.();\n this.inboundUnsubscribe = null;\n }\n\n async createSession(opts: CreateSessionOptions): Promise<SessionHandle> {\n if (!this.hookServer) {\n if (this._initializing) {\n await this._initializing;\n } else {\n this._initializing = (async () => {\n this.token = (opts.agentOptions?.token as string) || this.generateToken();\n this.port = opts.hookPort || 0;\n\n this.hookServer = new HookServer({\n port: this.port,\n token: this.token,\n logger: this.logger,\n // AgentEvent handler (new style)\n onAgentEvent: (agentEvent) => {\n this.logger?.debug({ agentEventType: agentEvent.type, sessionId: agentEvent.session_id }, 'Forwarding AgentEvent to handler');\n if (this.agentEventHandler) {\n this.agentEventHandler(agentEvent);\n } else {\n this.logger?.warn({ agentEventType: agentEvent.type }, 'No agentEventHandler registered');\n }\n },\n // Legacy event handler (backward compatible)\n onEvent: (envelope) => {\n this.logger?.debug({ eventType: envelope.type, sessionId: envelope.sessionId }, 'Forwarding legacy envelope to handler');\n if (this.eventHandler) {\n this.eventHandler(envelope);\n } else {\n this.logger?.warn({ eventType: envelope.type }, 'No eventHandler registered');\n }\n },\n // Permission request handler\n onPermissionRequest: (envelope, respond) => {\n const requestId = envelope.metadata.permissionRequestId || envelope.sessionId;\n this.logger?.info({ eventType: envelope.type, sessionId: envelope.sessionId, requestId }, 'Permission request received from hook');\n this.pendingPermissionHandlers.set(requestId, respond);\n\n // Emit to both handlers\n if (this.agentEventHandler) {\n // Convert envelope back to AgentEvent for the handler\n const agentEvent = this.convertEnvelopeToAgentEvent(envelope);\n if (agentEvent) {\n this.logger?.debug({ requestId, agentEventType: agentEvent.type }, 'Forwarding permission as AgentEvent');\n this.agentEventHandler(agentEvent);\n }\n }\n if (this.eventHandler) {\n this.logger?.debug({ requestId, envelopeType: envelope.type }, 'Forwarding permission as legacy envelope');\n this.eventHandler(envelope);\n }\n },\n });\n\n this.port = await this.hookServer.start(this.port);\n })();\n await this._initializing;\n this._initializing = null;\n }\n }\n\n const sessionId = this.generateSessionId();\n const handle: SessionHandle = {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n createdAt: new Date(),\n sendCommand: async (command) => {\n if (command.type === 'permission:response') {\n const responder = this.pendingPermissionHandlers.get(command.requestId);\n if (responder) {\n responder(command);\n this.pendingPermissionHandlers.delete(command.requestId);\n }\n }\n },\n close: async () => {\n this.sessions.delete(sessionId);\n },\n };\n\n this.sessions.set(sessionId, {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: new Date(),\n cwd: opts.cwd,\n });\n\n this.logger?.info({ sessionId, port: this.port }, 'Claude session created');\n return handle;\n }\n\n async closeSession(handle: SessionHandle): Promise<void> {\n await handle.close();\n this.sessions.delete(handle.id);\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return Array.from(this.sessions.values());\n }\n\n async getSession(sessionId: string): Promise<SessionInfo | undefined> {\n return this.sessions.get(sessionId);\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n this.logger?.debug('Legacy event handler registered');\n }\n\n /**\n * Set handler for AgentEvents (new style)\n */\n setAgentEventHandler(handler: (event: AgentEvent) => void): void {\n this.agentEventHandler = handler;\n this.logger?.debug('AgentEvent handler registered');\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return {\n healthy: this.hookServer !== null,\n message: this.hookServer ? `Hook server running on port ${this.port}` : 'Not initialized',\n };\n }\n\n getPort(): number {\n return this.port;\n }\n\n getToken(): string {\n return this.token;\n }\n\n /**\n * Get the unified hook URL (recommended)\n * All events are sent to this single URL with event_type in the body\n */\n getHookUrl(): string {\n if (!this.hookServer) {\n return '';\n }\n return this.hookServer.getHookUrl(this.port);\n }\n\n /**\n * Get legacy hook URL for a specific event type\n * @deprecated Use getHookUrl() for unified endpoint\n */\n getLegacyHookUrl(eventType: string): string {\n if (!this.hookServer) {\n return '';\n }\n return this.hookServer.getLegacyHookUrl(this.port, eventType);\n }\n\n /**\n * Get the settings.json hooks configuration (unified format)\n */\n getSettingsConfig(): Record<string, unknown> {\n const hookUrl = this.getHookUrl();\n if (!hookUrl) {\n throw new Error('Hook server not initialized. Call createSession first.');\n }\n\n return {\n hooks: {\n SessionStart: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n SessionEnd: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n Stop: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PreToolUse: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PermissionRequest: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PostToolUse: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PostToolUseFailure: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n },\n };\n }\n\n /**\n * Convert AgentEventEnvelope to AgentEvent (simplified)\n * This is used when we need to emit AgentEvent from legacy envelope\n */\n private convertEnvelopeToAgentEvent(envelope: AgentEventEnvelope): AgentEvent | null {\n // Map back from raw event type\n const rawEventType = envelope.metadata.rawEventType;\n if (!rawEventType) return null;\n\n // Build payload from envelope\n const payload: Record<string, unknown> = {\n session_id: envelope.sessionId,\n ...envelope.payload,\n };\n\n if (envelope.metadata.cwd) {\n payload.cwd = envelope.metadata.cwd;\n }\n\n return mapClaudeToAgentEvent(rawEventType as any, payload, 'claude');\n }\n\n /**\n * Check if this adapter can handle the given raw event type\n * @deprecated Use the isClaudeHookEventType function instead\n */\n canHandle(rawEventType: string): boolean {\n return isClaudeHookEventType(rawEventType);\n }\n\n /**\n * @deprecated Still used by setupRoutes in src/server/http.ts\n * This provides backward compatibility for the HTTP route handler\n */\n translate(rawEventType: string, payload: unknown): AgentEventEnvelope | null {\n this.logger?.debug({ rawEventType }, 'translate called');\n if (!payload || typeof payload !== 'object') {\n this.logger?.warn({ rawEventType }, 'translate failed: invalid payload');\n return null;\n }\n\n if (!['SessionStart', 'SessionEnd', 'PreToolUse', 'PermissionRequest',\n 'PostToolUse', 'PostToolUseFailure', 'Stop'].includes(rawEventType)) {\n this.logger?.warn({ rawEventType }, 'translate failed: unsupported event type');\n return null;\n }\n\n const envelope = mapClaudeToAgentEventEnvelope(\n rawEventType as any,\n payload as Record<string, unknown>,\n 'claude'\n );\n if (envelope) {\n this.logger?.info({ rawEventType, envelopeType: envelope.type, sessionId: envelope.sessionId }, 'Event translated');\n } else {\n this.logger?.warn({ rawEventType }, 'translate failed: mapping returned null');\n }\n return envelope;\n }\n\n private generateToken(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n }\n\n private generateSessionId(): string {\n return `claude-${randomUUID().slice(0, 8)}`;\n }\n\n private handleInboundMessage(message: InboundMessage): void {\n if (!this.bus) {\n return;\n }\n\n this.logger?.debug(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n targetAgent: message.targetAgent,\n agentCommand: message.agentCommand,\n textPreview: message.text.slice(0, 80),\n },\n 'Claude inbound message received'\n );\n\n if (message.systemCommand || message.targetAgent !== 'claude') {\n return;\n }\n\n const normalized = this.normalizeInboundText(message);\n if (normalized === null) {\n return;\n }\n\n const [keyword, ...rest] = normalized.split(/\\s+/);\n const lowered = keyword.toLowerCase();\n const commandOnly = rest.length === 0;\n\n if (!normalized || (lowered === 'help' && commandOnly)) {\n this.reply(message, this.getHelpText());\n return;\n }\n\n if (lowered === 'status' && commandOnly) {\n this.reply(message, this.getStatusText());\n return;\n }\n\n if ((lowered === 'reset' || lowered === 'stop') && commandOnly) {\n this.reply(\n message,\n 'Claude chat sessions are not owned by Handsoff. Stop or restart the local Claude Code session in your workspace, then continue here for approvals and notifications.'\n );\n return;\n }\n\n this.reply(message, this.getPromptingNotSupportedText());\n }\n\n private normalizeInboundText(message: InboundMessage): string | null {\n const text = message.text.trim();\n const explicitCommand = text.match(/^\\/claude(?:@[^\\s]+)?(?:\\s+(.*))?$/s);\n if (explicitCommand) {\n return explicitCommand[1]?.trim() ?? '';\n }\n\n return message.agentCommand ? null : text;\n }\n\n private getHelpText(): string {\n return [\n 'Claude commands:',\n '/claude help - show this help message',\n '/claude status - show Claude hook status',\n '/claude stop - explain how to stop the local Claude session',\n '/claude reset - explain how to reset the local Claude session',\n '',\n 'Current Claude integration is hook-based.',\n 'Send prompts in your local Claude Code workspace, and use Handsoff channels for approvals, notifications, and status.',\n ].join('\\n');\n }\n\n private getStatusText(): string {\n const activeSessions = Array.from(this.sessions.values()).filter((session) => session.status === 'active');\n const hookStatus = this.hookServer ? `running on port ${this.port}` : 'not initialized';\n\n return [\n '**Claude Status**',\n '',\n `Hook server: ${hookStatus}`,\n `Tracked Claude sessions: ${activeSessions.length}`,\n this.token ? `Registered token: ${this.token.slice(0, 8)}...` : 'Registered token: unavailable',\n '',\n 'Claude sessions are started from the local Claude Code client, not from the chat channel.',\n ].join('\\n');\n }\n\n private getPromptingNotSupportedText(): string {\n return [\n 'This channel is bound to Claude, but the current Claude integration is hook-based.',\n 'Start or continue the task from your local Claude Code session, and use this channel for approvals, notifications, and `/claude status`.',\n ].join('\\n');\n }\n\n private reply(message: InboundMessage, text: string): void {\n this.bus?.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text,\n replyToMessageId: message.messageId,\n });\n }\n}\n\n// Re-export for backward compatibility\nexport { ClaudeAdapter as ClaudeHookAdapter };\nexport { HookServer } from './hook/HookServer.js';\nexport {\n mapClaudeToAgentEvent,\n mapAgentEventToAgentEventEnvelope,\n mapClaudeToAgentEventEnvelope,\n calculateRiskLevel,\n createPermissionDecisionEvent,\n isClaudeHookEventType,\n type ClaudeHookEventType,\n} from './ClaudeEventMapper.js';\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/hook/HookServer.ts\n// Unified Hook Server - supports both legacy and unified URL formats\n\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport type { Logger } from 'pino';\nimport type {\n AgentEventEnvelope,\n PermissionResponseCommand,\n} from '../../../../core/adapter/types.js';\nimport type { AgentEvent } from '../../../../core/event/types.js';\nimport {\n isClaudeHookEventType,\n mapClaudeToAgentEvent,\n mapAgentEventToAgentEventEnvelope,\n} from '../ClaudeEventMapper.js';\n\nexport interface HookServerOptions {\n port: number;\n token: string;\n logger?: Logger;\n /** Legacy event handler (for backward compatibility) */\n onEvent?: (envelope: AgentEventEnvelope) => void;\n /** AgentEvent handler (new style) */\n onAgentEvent?: (event: AgentEvent) => void;\n /** Permission request handler with response callback */\n onPermissionRequest?: (\n envelope: AgentEventEnvelope,\n respond: (decision: PermissionResponseCommand) => void\n ) => void;\n}\n\ninterface PendingRequest {\n response: ServerResponse;\n timeout: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Unified Hook Server\n *\n * Supports two URL formats:\n * 1. Legacy: /hook/{token}/{eventType} (event type in URL path)\n * 2. Unified: /hook/{token}/event (event type in body.hook_event_name)\n *\n * Events are always converted to:\n * - AgentEvent format (for new consumers)\n * - AgentEventEnvelope format (for backward compatibility)\n */\nexport class HookServer {\n private server: ReturnType<typeof createServer> | null = null;\n private pendingRequests: Map<string, PendingRequest> = new Map();\n private token: string;\n private onEvent: HookServerOptions['onEvent'];\n private onAgentEvent: HookServerOptions['onAgentEvent'];\n private onPermissionRequest: HookServerOptions['onPermissionRequest'];\n private logger: Logger | undefined;\n\n constructor(options: HookServerOptions) {\n this.token = options.token;\n this.onEvent = options.onEvent;\n this.onAgentEvent = options.onAgentEvent;\n this.onPermissionRequest = options.onPermissionRequest;\n this.logger = options.logger;\n }\n\n async start(port: number): Promise<number> {\n return new Promise((resolve, reject) => {\n this.server = createServer(this.handleRequest.bind(this));\n this.server.on('error', reject);\n this.server.listen(port, () => {\n const address = this.server?.address();\n const actualPort =\n typeof address === 'object' && address ? address.port : port;\n this.logger?.info({ port: actualPort }, 'Claude hook server listening');\n resolve(actualPort);\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.logger?.info('Claude hook server stopping');\n // Clear all pending requests\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timeout);\n pending.response.writeHead(503, { 'Content-Type': 'application/json' });\n pending.response.end(\n JSON.stringify({ accepted: false, error: 'Server shutting down' })\n );\n }\n this.pendingRequests.clear();\n this.server?.close(() => {\n this.logger?.info('Claude hook server stopped');\n resolve();\n });\n });\n }\n\n resolvePermission(requestId: string, decision: PermissionResponseCommand): void {\n const pending = this.pendingRequests.get(requestId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRequests.delete(requestId);\n\n const behavior =\n decision.decision === 'allow'\n ? 'allow'\n : decision.decision === 'always_allow'\n ? 'always_allow'\n : 'deny';\n\n pending.response.writeHead(200, { 'Content-Type': 'application/json' });\n pending.response.end(\n JSON.stringify({\n hookSpecificOutput: {\n decision: { behavior, message: '' },\n },\n })\n );\n }\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url || '/', 'http://localhost');\n const pathname = url.pathname;\n\n this.logger?.debug({ method: req.method, url: pathname }, 'Hook request received');\n\n // Token validation\n const tokenMatch = pathname.match(/^\\/hook\\/([^/]+)\\/(.+)$/);\n if (!tokenMatch || tokenMatch[1] !== this.token) {\n this.logger?.warn({ pathname }, 'Hook request unauthorized');\n res.writeHead(401);\n res.end('Unauthorized');\n return;\n }\n\n const pathPart = tokenMatch[2];\n\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n try {\n const payload = body ? JSON.parse(body) : {};\n\n // Determine event type based on URL format\n // Legacy: /hook/{token}/Stop\n // Unified: /hook/{token}/event with body.hook_event_name\n let eventType: string;\n if (pathPart === 'event' && payload.hook_event_name) {\n eventType = String(payload.hook_event_name);\n } else {\n eventType = pathPart;\n }\n\n if (!isClaudeHookEventType(eventType)) {\n this.logger?.info({ eventType }, 'Hook event ignored: unknown event type');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'Unknown event type' }));\n return;\n }\n\n this.processEvent(eventType, payload, res);\n } catch (err) {\n this.logger?.error({ error: err instanceof Error ? err.message : String(err) }, 'Hook request JSON parse error');\n res.writeHead(400);\n res.end('Invalid JSON');\n }\n });\n }\n\n private processEvent(\n eventType: string,\n payload: Record<string, unknown>,\n res: ServerResponse\n ): void {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : undefined;\n const requestId = typeof payload.request_id === 'string' ? payload.request_id : sessionId;\n this.logger?.info({ eventType, sessionId, toolName, requestId }, 'Processing Claude hook event');\n\n // Convert to AgentEvent format first\n const agentEvent = mapClaudeToAgentEvent(eventType as any, payload, 'claude');\n if (!agentEvent) {\n this.logger?.warn({ eventType, sessionId }, 'Event mapping returned null');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'Event not mapped' }));\n return;\n }\n\n // Emit AgentEvent (new consumers)\n if (this.onAgentEvent) {\n this.logger?.debug({ eventType, agentEventType: agentEvent.type, sessionId }, 'Emitting AgentEvent');\n this.onAgentEvent(agentEvent);\n }\n\n // Convert to legacy format for backward compatibility\n const envelope = mapAgentEventToAgentEventEnvelope(agentEvent, 'claude');\n if (!envelope) {\n this.logger?.warn({ eventType, agentEventType: agentEvent.type, sessionId }, 'AgentEvent to legacy envelope conversion failed');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'AgentEvent to legacy conversion failed' }));\n return;\n }\n\n // Check if this is a permission request\n const isPermissionHook =\n eventType === 'PreToolUse' || eventType === 'PermissionRequest';\n\n if (isPermissionHook && this.onPermissionRequest) {\n const permissionRequestId =\n envelope.metadata.permissionRequestId || envelope.sessionId;\n\n this.logger?.info({ eventType, sessionId, requestId: permissionRequestId, toolName }, 'Permission request queued for response');\n\n // Permission request - wait for response\n const timeout = setTimeout(() => {\n if (this.pendingRequests.has(permissionRequestId)) {\n this.logger?.warn({ requestId: permissionRequestId }, 'Permission request timeout');\n this.pendingRequests.delete(permissionRequestId);\n res.writeHead(200);\n res.end(\n JSON.stringify({\n hookSpecificOutput: {\n decision: { behavior: 'deny', message: 'Timeout' },\n },\n })\n );\n }\n }, 60000);\n\n this.pendingRequests.set(permissionRequestId, { response: res, timeout });\n\n try {\n this.onPermissionRequest(envelope, (decision) => {\n this.logger?.info({ requestId: permissionRequestId, decision: decision.decision }, 'Permission resolved');\n this.resolvePermission(permissionRequestId, decision);\n });\n } catch (error) {\n this.logger?.error({ requestId: permissionRequestId, error: error instanceof Error ? error.message : String(error) }, 'Error in permission request callback');\n clearTimeout(timeout);\n this.pendingRequests.delete(permissionRequestId);\n res.writeHead(500);\n res.end(JSON.stringify({ error: 'Internal error' }));\n }\n } else {\n // Non-permission event - don't block\n this.logger?.info({ eventType, sessionId, envelopeType: envelope.type }, 'Non-permission event handled');\n if (this.onEvent) {\n this.logger?.debug({ eventType, sessionId, envelopeType: envelope.type }, 'Emitting legacy envelope');\n this.onEvent(envelope);\n }\n res.writeHead(202);\n res.end(\n JSON.stringify({\n accepted: true,\n event_type: agentEvent.type,\n agent_event_id: agentEvent.id,\n })\n );\n }\n }\n\n /**\n * Get the hook URL for this server\n * Returns unified format by default\n */\n getHookUrl(port: number): string {\n return `http://localhost:${port}/hook/${this.token}/event`;\n }\n\n /**\n * Get legacy hook URL pattern\n */\n getLegacyHookUrl(port: number, eventType: string): string {\n return `http://localhost:${port}/hook/${this.token}/${eventType}`;\n }\n}\n","/**\n * Agent Event Protocol v1.0.0\n * Standardized event format for Agent ↔ App communication\n */\n\nexport type AgentEventDirection = 'agent' | 'user' | 'system';\n\n// Note: 'input' and 'confirm' are reserved for future use\nexport type InteractionType = 'permission' | 'question';\n\nexport interface AgentEventButton {\n text: string;\n action: string;\n value?: unknown;\n metadata?: Record<string, unknown>;\n}\n\nexport interface InteractionContext {\n type: InteractionType;\n requestId: string;\n toolName: string;\n permission?: {\n riskLevel: string;\n args: Record<string, unknown>;\n };\n question?: {\n question: string;\n header?: string;\n options: Array<{\n label: string;\n value: unknown;\n description?: string;\n }>;\n multiSelect: boolean;\n };\n}\n\n// Response action: 'allow'/'deny' for permission, 'select' for question, 'input' for text input\nexport interface InteractionResponse {\n requestId: string;\n action: 'allow' | 'deny' | 'select' | 'input';\n data?: unknown;\n}\n\nexport interface AgentEventPayload {\n title?: string;\n description?: string;\n text?: string;\n buttons?: AgentEventButton[];\n data: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface AgentEvent {\n id: string;\n ts: number;\n version: string;\n type: string;\n direction: AgentEventDirection;\n session_id: string;\n agent: string;\n device_id: string;\n ack_id?: string;\n app?: string;\n payload: AgentEventPayload;\n}\n\n// Event type constants\nexport const AGENT_EVENTS = [\n 'agent:session:start',\n 'agent:session:end',\n 'agent:permission:request',\n 'agent:question:request',\n 'agent:tool:start',\n 'agent:tool:end',\n 'agent:turn:finished',\n 'agent:message:text',\n 'agent:message:file',\n] as const;\n\nexport const USER_EVENTS = [\n 'user:message:text',\n 'user:permission:decision',\n 'user:command:exec',\n 'user:command:session',\n 'user:command:pause',\n 'user:command:resume',\n 'user:command:stop',\n 'user:command:status',\n 'user:interaction:response',\n] as const;\n\nexport const SYSTEM_EVENTS = [\n 'system:ack',\n 'system:error',\n 'system:heartbeat',\n] as const;\n\nexport type AgentEventType = typeof AGENT_EVENTS[number];\nexport type UserEventType = typeof USER_EVENTS[number];\nexport type SystemEventType = typeof SYSTEM_EVENTS[number];\nexport type AllEventType = AgentEventType | UserEventType | SystemEventType;\n\n// Factory functions\nexport function createAgentEvent(\n type: AllEventType,\n direction: AgentEventDirection,\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Omit<AgentEventPayload, 'data'> & { data: Record<string, unknown> }\n): AgentEvent {\n return {\n id: generateEventId(sessionId),\n ts: Date.now(),\n version: '1.0.0',\n type,\n direction,\n session_id: sessionId,\n agent,\n device_id: deviceId,\n payload: {\n title: payload.title,\n description: payload.description,\n text: payload.text,\n buttons: payload.buttons,\n data: payload.data,\n extensions: payload.extensions,\n interaction: payload.interaction,\n },\n };\n}\n\nfunction generateEventId(sessionId: string): string {\n return `${sessionId}:${Date.now()}`;\n}\n","/**\n * Claude Event Mapper\n *\n * Maps Claude Code hook events to standardized formats:\n * 1. Claude Event → AgentEvent\n * 2. AgentEvent → AgentEventEnvelope (backward compatible)\n *\n * This is the single source of truth for all Claude event transformations.\n */\n\nimport type { AgentEvent, InteractionContext, AgentEventButton } from '../../../../core/event/types.js';\nimport { createAgentEvent, AGENT_EVENTS, USER_EVENTS, SYSTEM_EVENTS } from '../../../../core/event/types.js';\nimport type { AgentEventEnvelope, AgentEventType } from '../../../../core/adapter/types.js';\nimport { hostname } from 'os';\n\nconst DEVICE_ID = hostname();\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\n/**\n * Calculate risk level for permission requests\n */\nexport function calculateRiskLevel(\n toolName: string,\n args: Record<string, unknown>\n): 'low' | 'medium' | 'high' {\n const highRiskTools = ['Bash', 'Write', 'Edit'];\n\n if (highRiskTools.includes(toolName)) {\n const command = String(args.command || args.file_path || '');\n // High risk commands that can cause data loss or system damage\n if (command.match(/\\brm\\b/) || command.includes('sudo') || command.includes('>')) {\n return 'high';\n }\n return 'medium';\n }\n\n return 'low';\n}\n\n/**\n * Question option from AskUserQuestion tool input\n */\ninterface QuestionOption {\n label: string;\n value?: unknown;\n description?: string;\n}\n\n/**\n * Question data from AskUserQuestion tool input\n */\ninterface QuestionData {\n question: string;\n header?: string;\n options: QuestionOption[];\n multiSelect?: boolean;\n}\n\n/**\n * Build interaction context for AskUserQuestion\n */\nfunction buildQuestionInteraction(\n requestId: string,\n toolName: string,\n questions: QuestionData[]\n): InteractionContext {\n const question = questions[0]; // Use first question for now\n return {\n type: 'question',\n requestId,\n toolName,\n question: {\n question: question.question,\n header: question.header,\n options: question.options.map(opt => ({\n label: opt.label,\n value: opt.value ?? opt.label,\n description: opt.description,\n })),\n multiSelect: question.multiSelect ?? false,\n },\n };\n}\n\n/**\n * Build interaction context for permission request\n */\nfunction buildPermissionInteraction(\n requestId: string,\n toolName: string,\n args: Record<string, unknown>,\n riskLevel: 'low' | 'medium' | 'high'\n): InteractionContext {\n return {\n type: 'permission',\n requestId,\n toolName,\n permission: {\n riskLevel,\n args,\n },\n };\n}\n\n/**\n * Build buttons for question interaction\n */\nfunction buildQuestionButtons(options: QuestionOption[]): AgentEventButton[] {\n return options.map((option, index) => ({\n text: option.label,\n action: 'select',\n value: option.value ?? option.label,\n metadata: {\n index,\n description: option.description,\n },\n }));\n}\n\n/**\n * Build buttons for permission interaction\n */\nfunction buildPermissionButtons(): AgentEventButton[] {\n return [\n { text: 'Allow', action: 'allow' },\n { text: 'Deny', action: 'deny' },\n { text: 'Always Allow', action: 'always_allow' },\n ];\n}\n\n/**\n * Map Claude hook event to AgentEvent\n */\nexport function mapClaudeToAgentEvent(\n eventType: ClaudeHookEventType,\n payload: Record<string, unknown>,\n agent: string = 'claude'\n): AgentEvent | null {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : 'unknown';\n\n switch (eventType) {\n case 'SessionStart':\n return createAgentEvent(\n 'agent:session:start',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Session Started',\n description: `Working directory: ${payload.cwd || 'unknown'}`,\n data: {\n session_id: sessionId,\n work_dir: payload.cwd || '',\n permission_mode: payload.permission_mode || 'auto',\n },\n }\n );\n\n case 'SessionEnd':\n return createAgentEvent(\n 'agent:session:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Session Ended',\n description: typeof payload.reason === 'string' ? payload.reason : 'Session completed',\n data: {\n session_id: sessionId,\n reason: payload.reason || 'completed',\n duration: typeof payload.duration === 'number' ? payload.duration : undefined,\n },\n }\n );\n\n case 'PreToolUse':\n case 'PermissionRequest': {\n const toolName = String(payload.tool_name || '');\n const toolInput = (payload.tool_input as Record<string, unknown>) || {};\n const requestId = String(payload.request_id || sessionId);\n\n // Check if this is an AskUserQuestion tool\n if (toolName === 'AskUserQuestion') {\n const questions = (toolInput.questions as QuestionData[]) || [];\n const question = questions[0];\n\n return createAgentEvent(\n 'agent:question:request',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: question?.header || 'Question',\n description: question?.question || 'Please answer the question',\n text: question?.question,\n buttons: question?.options ? buildQuestionButtons(question.options) : [],\n data: {\n request_id: requestId,\n tool_name: toolName,\n args: toolInput,\n cwd: payload.cwd || '',\n },\n interaction: buildQuestionInteraction(requestId, toolName, questions),\n }\n );\n }\n\n // Regular tool permission request\n const riskLevel = calculateRiskLevel(toolName, toolInput);\n\n return createAgentEvent(\n 'agent:permission:request',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `Permission Required: ${toolName || 'Tool'}`,\n description: `${toolName} ${JSON.stringify(toolInput)}`,\n text: `Claude wants to execute ${toolName || 'a tool'}`,\n buttons: buildPermissionButtons(),\n data: {\n request_id: requestId,\n tool_name: toolName,\n args: toolInput,\n cwd: payload.cwd || '',\n risk_level: riskLevel,\n },\n interaction: buildPermissionInteraction(requestId, toolName, toolInput, riskLevel),\n }\n );\n }\n\n case 'PostToolUse':\n return createAgentEvent(\n 'agent:tool:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `${payload.tool_name || 'Tool'} Completed`,\n data: {\n tool_name: payload.tool_name || '',\n args: payload.tool_input || {},\n output: payload.output,\n },\n }\n );\n\n case 'PostToolUseFailure':\n return createAgentEvent(\n 'agent:tool:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `${payload.tool_name || 'Tool'} Failed`,\n description: typeof payload.error === 'string' ? payload.error : 'Tool execution failed',\n data: {\n tool_name: payload.tool_name || '',\n args: payload.tool_input || {},\n error: payload.error,\n },\n }\n );\n\n case 'Stop':\n return createAgentEvent(\n 'agent:turn:finished',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Turn Completed',\n description: typeof payload.reason === 'string' ? payload.reason : 'Session stopped',\n data: {\n session_id: sessionId,\n reason: payload.reason || 'stopped',\n status: 'completed',\n last_assistant_message: payload.last_assistant_message,\n transcript_path: payload.transcript_path,\n },\n }\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Map AgentEvent to AgentEventEnvelope (backward compatible)\n */\nexport function mapAgentEventToAgentEventEnvelope(\n agentEvent: AgentEvent,\n agent: string = 'claude'\n): AgentEventEnvelope | null {\n const timestamp = new Date(agentEvent.ts).toISOString();\n const baseMetadata = {\n agentType: agent as 'claude' | 'codex',\n transportType: 'hook' as const,\n sessionId: agentEvent.session_id,\n timestamp,\n rawEventType: agentEventTypeToRawEventType(agentEvent.type),\n };\n\n switch (agentEvent.type) {\n case 'agent:session:start':\n return {\n type: 'session:start',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: { sessionId: agentEvent.session_id },\n metadata: baseMetadata,\n };\n\n case 'agent:session:end':\n return {\n type: 'session:end',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n reason: agentEvent.payload.data.reason as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'agent:permission:request':\n return {\n type: 'permission:request',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n requestId: agentEvent.payload.data.request_id as string,\n },\n metadata: {\n ...baseMetadata,\n permissionRequestId: agentEvent.payload.data.request_id as string,\n },\n };\n\n case 'agent:question:request':\n return {\n type: 'question:request',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n requestId: agentEvent.payload.data.request_id as string,\n },\n metadata: {\n ...baseMetadata,\n questionRequestId: agentEvent.payload.data.request_id as string,\n },\n };\n\n case 'agent:tool:end':\n return {\n type: agentEvent.payload.data.error ? 'tool:failure' : 'tool:end',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n output: agentEvent.payload.data.output as string | undefined,\n error: agentEvent.payload.data.error as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'agent:turn:finished':\n return {\n type: 'finished',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n reason: agentEvent.payload.data.reason as string | undefined,\n lastAssistantMessage: agentEvent.payload.data.last_assistant_message as string | undefined,\n transcriptPath: agentEvent.payload.data.transcript_path as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n default:\n return null;\n }\n}\n\n/**\n * Direct mapping from Claude event to AgentEventEnvelope (shortcut)\n * This preserves the legacy type mapping for backward compatibility\n */\nexport function mapClaudeToAgentEventEnvelope(\n eventType: ClaudeHookEventType,\n payload: Record<string, unknown>,\n agent: string = 'claude'\n): AgentEventEnvelope | null {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : '';\n const timestamp = new Date().toISOString();\n\n const baseMetadata = {\n agentType: agent as 'claude' | 'codex',\n transportType: 'hook' as const,\n sessionId,\n timestamp,\n rawEventType: eventType,\n permission_mode: typeof payload.permission_mode === 'string' ? payload.permission_mode : 'auto',\n cwd: typeof payload.cwd === 'string' ? payload.cwd : '',\n };\n\n switch (eventType) {\n case 'SessionStart':\n return {\n type: 'session:start',\n sessionId,\n timestamp,\n payload: { sessionId },\n metadata: baseMetadata,\n };\n\n case 'SessionEnd':\n return {\n type: 'session:end',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n reason: typeof payload.reason === 'string' ? payload.reason : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'PreToolUse':\n case 'PermissionRequest': {\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : '';\n const isAskUserQuestion = toolName === 'AskUserQuestion';\n\n return {\n type: isAskUserQuestion ? 'question:request' : 'permission:request',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName,\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n requestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n metadata: {\n ...baseMetadata,\n [isAskUserQuestion ? 'questionRequestId' : 'permissionRequestId']:\n typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n };\n }\n\n case 'PostToolUse':\n return {\n type: 'tool:post',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName: typeof payload.tool_name === 'string' ? payload.tool_name : '',\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n output: typeof payload.output === 'string' ? payload.output : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'PostToolUseFailure':\n return {\n type: 'tool:failure',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName: typeof payload.tool_name === 'string' ? payload.tool_name : '',\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n error: typeof payload.error === 'string' ? payload.error : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'Stop':\n return {\n type: 'finished',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n reason: typeof payload.reason === 'string' ? payload.reason : undefined,\n lastAssistantMessage: typeof payload.last_assistant_message === 'string' ? payload.last_assistant_message : undefined,\n transcriptPath: typeof payload.transcript_path === 'string' ? payload.transcript_path : undefined,\n },\n metadata: baseMetadata,\n };\n\n default:\n return null;\n }\n}\n\n/**\n * Convert AgentEvent type to raw Claude event type\n */\nfunction agentEventTypeToRawEventType(agentEventType: string): string {\n const mapping: Record<string, string> = {\n 'agent:session:start': 'SessionStart',\n 'agent:session:end': 'SessionEnd',\n 'agent:permission:request': 'PermissionRequest',\n 'agent:question:request': 'PermissionRequest',\n 'agent:tool:end': 'PostToolUse',\n 'agent:turn:finished': 'Stop',\n };\n return mapping[agentEventType] || agentEventType;\n}\n\n/**\n * Create a user permission decision event\n */\nexport function createPermissionDecisionEvent(\n originalRequestId: string,\n sessionId: string,\n decision: 'allow' | 'deny' | 'always_allow',\n agent: string = 'claude'\n): AgentEvent {\n return createAgentEvent(\n 'user:permission:decision',\n 'user',\n sessionId,\n agent,\n 'user-device',\n {\n title: 'Permission Decision',\n data: {\n request_id: originalRequestId,\n decision,\n },\n }\n );\n}\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}","// src/core/adapter/protocol/claude/ClaudeProtocolHandler.ts\n\nimport { randomUUID } from 'crypto';\nimport type { ProtocolHandler } from '../ProtocolHandler.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../../core/interaction/types.js';\nimport type { AgentEvent } from '../../../../core/event/types.js';\nimport { mapClaudeToAgentEvent, type ClaudeHookEventType } from './ClaudeEventMapper.js';\nimport {\n createPendingMap,\n addPending,\n resolvePending,\n abortAll,\n} from '../permissionUtils.js';\n\nexport class ClaudeProtocolHandler implements ProtocolHandler {\n readonly agentType = 'claude' as const;\n\n private pendingRequests = createPendingMap();\n\n fromAgent(event: unknown): InteractionRequest | null {\n // HTTP hook event format: { eventType: string, payload: Record<string, unknown> }\n const hookEvent = event as { eventType?: string; payload?: Record<string, unknown> };\n if (!hookEvent.eventType || !hookEvent.payload) {\n return null;\n }\n\n // Use ClaudeEventMapper to convert event\n const agentEvent = mapClaudeToAgentEvent(\n hookEvent.eventType as ClaudeHookEventType,\n hookEvent.payload,\n 'claude'\n );\n if (!agentEvent) return null;\n\n // Check if interaction type\n if (agentEvent.type !== 'agent:permission:request' && agentEvent.type !== 'agent:question:request') {\n return null;\n }\n\n // Create InteractionRequest\n const requestId = randomUUID();\n const data = agentEvent.payload.data as {\n tool_name?: string;\n args?: Record<string, unknown>;\n request_id?: string;\n };\n\n const request: InteractionRequest = {\n requestId,\n sessionId: agentEvent.session_id,\n type: agentEvent.type === 'agent:question:request' ? 'question' : 'permission',\n toolName: data.tool_name || '',\n toolInput: data.args || {},\n timestamp: Date.now(),\n };\n\n // Add to pending\n addPending(this.pendingRequests, requestId, {\n resolve: () => {},\n reject: () => {},\n toolName: request.toolName,\n toolInput: request.toolInput,\n timestamp: request.timestamp,\n });\n\n return request;\n }\n\n toAgent(response: InteractionResponse): unknown {\n // Build Hook response format (Claude Code HTTP Hook format)\n const result: {\n action: 'allow' | 'deny' | 'skip';\n updatedPermissions?: unknown;\n } = {\n action: response.action === 'allow' ? 'allow' : response.action === 'deny' ? 'deny' : 'skip',\n };\n\n if (response.permissionUpdates && response.permissionUpdates.length > 0) {\n result.updatedPermissions = response.permissionUpdates;\n }\n\n return result;\n }\n\n abort(): void {\n abortAll(this.pendingRequests);\n }\n\n /**\n * Resolve permission response (called by AgentAdapter)\n */\n resolvePending(requestId: string, response: InteractionResponse): boolean {\n return resolvePending(this.pendingRequests, requestId, response);\n }\n}\n","// src/core/adapter/protocol/permissionUtils.ts\n\nimport type { InteractionResponse } from '../../interaction/types.js';\n\nexport interface PendingRequest {\n resolve: (response: InteractionResponse) => void;\n reject: (error: Error) => void;\n toolName: string;\n toolInput: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Create a new PendingRequest Map\n */\nexport function createPendingMap(): Map<string, PendingRequest> {\n return new Map();\n}\n\n/**\n * Add a pending request\n */\nexport function addPending(\n map: Map<string, PendingRequest>,\n requestId: string,\n pending: PendingRequest\n): void {\n map.set(requestId, pending);\n}\n\n/**\n * Resolve a pending request\n */\nexport function resolvePending(\n map: Map<string, PendingRequest>,\n requestId: string,\n response: InteractionResponse\n): boolean {\n const pending = map.get(requestId);\n if (!pending) return false;\n map.delete(requestId);\n try {\n pending.resolve(response);\n } catch {\n // Ignore errors after deletion\n }\n return true;\n}\n\n/**\n * Reject a pending request\n */\nexport function rejectPending(\n map: Map<string, PendingRequest>,\n requestId: string,\n error: Error\n): boolean {\n const pending = map.get(requestId);\n if (!pending) return false;\n map.delete(requestId);\n try {\n pending.reject(error);\n } catch {\n // Ignore errors after deletion\n }\n return true;\n}\n\n/**\n * Abort all pending requests\n */\nexport function abortAll(map: Map<string, PendingRequest>): void {\n const error = new Error('Aborted');\n const entries = Array.from(map.entries());\n map.clear();\n for (const [, pending] of entries) {\n pending.reject(error);\n }\n}\n\n/**\n * Get timed out request IDs\n */\nexport function getTimedOutRequests(\n map: Map<string, PendingRequest>,\n timeoutMs: number\n): string[] {\n const now = Date.now();\n const timedOut: string[] = [];\n for (const [id, pending] of map) {\n if (now - pending.timestamp > timeoutMs) {\n timedOut.push(id);\n }\n }\n return timedOut;\n}\n","import { randomUUID } from 'crypto';\nimport type { AgentAdapter, CreateSessionOptions, SessionHandle, SessionInfo, AgentEventEnvelope, AgentCommand } from '../../../core/adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { Gateway } from '../../../gateway/index.js';\nimport type { Logger } from 'pino';\nimport { CodexProtocolHandler } from './CodexProtocolHandler.js';\nimport { CodexAppServerClient, type ApprovalHandler } from './codexAppServerClient.js';\nimport type { ApprovalPolicy, ReviewDecision } from './codexAppServerTypes.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\n\ninterface CodexSessionState {\n handle: SessionHandle;\n client: CodexAppServerClient;\n threadId: string;\n chatId: string;\n channel: string;\n cwd?: string;\n}\n\nexport class CodexAppServerAdapter implements AgentAdapter {\n readonly agentType = 'codex' as const;\n readonly transportType = 'stdio' as const;\n readonly version = '1.0.0';\n readonly protocolHandler: ProtocolHandler = new CodexProtocolHandler();\n\n private bus: EventBus;\n private logger: Logger;\n private gateway: Gateway;\n private token: string;\n private sessions = new Map<string, CodexSessionState>();\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private unsubscribeFns: Array<() => void> = [];\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 constructor(options: {\n bus: EventBus;\n logger: Logger;\n gateway: Gateway;\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 this.bus = options.bus;\n this.logger = options.logger;\n this.gateway = options.gateway;\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 AgentAdapterRegistry.getInstance().register(this);\n\n if (!this.unsubscribeFns.length) {\n this.unsubscribeFns.push(\n this.bus.onInbound((msg) => this.handleInboundMessage(msg))\n );\n this.logger.debug('Subscribed to inbound messages');\n }\n }\n\n async shutdown(): Promise<void> {\n this.logger.info('Codex adapter shutting down');\n for (const [sessionId, state] of this.sessions) {\n try {\n await state.client.disconnect();\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Error disconnecting Codex client during shutdown');\n }\n }\n this.sessions.clear();\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n this.logger.info('Codex adapter shutdown complete');\n }\n\n async createSession(opts: CreateSessionOptions): Promise<SessionHandle> {\n const sessionId = opts.sessionId ?? `codex-${randomUUID().slice(0, 8)}`;\n const chatId = (opts.metadata?.chatId as string) ?? sessionId;\n const channel = (opts.metadata?.channel as string) ?? 'broadcast';\n const cwd = opts.cwd ?? this.defaultWorkDir ?? process.cwd();\n this.logger.info({ sessionId, chatId, cwd }, 'Creating Codex session');\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 handle: SessionHandle = {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n createdAt: new Date(),\n sendCommand: async (command) => {\n await this.handleCommand(sessionId, command);\n },\n close: async () => {\n this.logger.info({ sessionId }, 'Closing Codex session');\n await client.disconnect();\n this.sessions.delete(sessionId);\n },\n };\n\n const state: CodexSessionState = {\n handle,\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.sessions.set(sessionId, state);\n\n this.logger.info({ sessionId, threadId }, 'Codex session started');\n\n return handle;\n }\n\n async closeSession(handle: SessionHandle): Promise<void> {\n await handle.close();\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return Array.from(this.sessions.values()).map((s) => ({\n id: s.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: s.handle.createdAt,\n }));\n }\n\n async getSession(sessionId: string): Promise<SessionInfo | undefined> {\n const state = this.sessions.get(sessionId);\n if (!state) return undefined;\n return {\n id: state.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: state.handle.createdAt,\n };\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n this.logger.debug('Event handler registered');\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return { healthy: true, message: `${this.sessions.size} active sessions` };\n }\n\n private async handleCommand(sessionId: string, command: AgentCommand): Promise<void> {\n const state = this.sessions.get(sessionId);\n if (!state) {\n this.logger.warn({ sessionId, commandType: command.type }, 'Command received but session not found');\n throw new Error(`Session not found: ${sessionId}`);\n }\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: state.channel,\n chatId: state.chatId,\n text: 'Codex is still processing the previous message. Please wait.',\n });\n return;\n }\n this.turnInProgress.add(sessionId);\n try {\n this.logger.debug({ sessionId, contentLength: command.content.length }, 'Sending turn to Codex');\n await state.client.sendTurnAndWait(command.content, {\n cwd: state.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 state.client.interruptTurn();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: { reason: 'stopped' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n await state.client.disconnect();\n this.sessions.delete(sessionId);\n break;\n }\n }\n }\n\n private async handleInboundMessage(message: InboundMessage): Promise<void> {\n const text = message.text.trim();\n this.logger.debug(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n targetAgent: message.targetAgent,\n agentCommand: message.agentCommand,\n textPreview: text.slice(0, 80),\n },\n 'Inbound message received'\n );\n\n // 如果是系统命令已处理标记,跳过\n if (message.systemCommand) {\n this.logger.debug('Ignoring system command message');\n return;\n }\n\n // 入站消息已经由 InboundRouter 打过 targetAgent 标记\n // 只有 targetAgent === 'codex' 的消息才由这个 adapter 处理\n if (!message.targetAgent) {\n this.logger.debug('Ignoring inbound message: no targetAgent, not routed');\n return;\n }\n\n if (message.targetAgent !== 'codex') {\n this.logger.debug({ targetAgent: message.targetAgent }, 'Ignoring inbound message: not targeted for Codex');\n return;\n }\n\n const rawInput = this.normalizeInboundText(message);\n if (rawInput === null) {\n this.logger.debug({ textPreview: text.slice(0, 40) }, 'Message ignored: not routed to Codex');\n return;\n }\n\n const sessionId = `codex-${message.chatId}`;\n const existingSession = this.gateway.getSession(sessionId);\n\n if (!rawInput) {\n this.logger.info({ chatId: message.chatId }, 'Empty /codex prompt, replying with help');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: this.getHelpText(),\n });\n return;\n }\n\n const [keyword, ...rest] = rawInput.split(/\\s+/);\n const normalizedKeyword = keyword.toLowerCase();\n const commandOnly = rest.length === 0;\n\n if (normalizedKeyword === 'help' && commandOnly) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: this.getHelpText(),\n });\n return;\n }\n\n if (normalizedKeyword === 'status' && commandOnly) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: existingSession && existingSession.getStatus() === 'active'\n ? `Codex session is active for this chat.\\nSession ID: ${sessionId}`\n : 'No active Codex session for this chat.',\n });\n return;\n }\n\n if ((normalizedKeyword === 'stop' || normalizedKeyword === 'reset') && commandOnly) {\n if (!existingSession) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'No active Codex session to stop.',\n });\n return;\n }\n\n await existingSession.sendCommand({ type: 'stop' });\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Codex session stopped for this chat.',\n });\n return;\n }\n\n const prompt = rawInput;\n this.logger.info({ chatId: message.chatId, sessionId, promptPreview: prompt.slice(0, 60) }, 'Handling /codex request');\n\n let session = existingSession;\n if (!session) {\n try {\n this.logger.info({ sessionId, chatId: message.chatId }, 'Creating new Codex session for inbound');\n session = await this.gateway.createSession(this.token, sessionId, { chatId: message.chatId, channel: message.channel });\n } catch (err) {\n this.logger.error({ error: err, chatId: message.chatId }, 'Failed to create Codex session');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Failed to start Codex session. Please check that Codex CLI is installed.',\n });\n return;\n }\n }\n\n if (session.getStatus() !== 'active') {\n this.logger.warn({ sessionId, status: session.getStatus() }, 'Codex session not active');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Session is not active. Please start a new session.',\n });\n return;\n }\n\n this.logger.info({ sessionId, promptPreview: prompt.slice(0, 60) }, 'Sending user:message to Codex session');\n await session.sendCommand({ type: 'user:message', content: prompt });\n }\n\n private async handleCodexEvent(msg: { type: string } & Record<string, unknown>, sessionId: string, _state: CodexSessionState): 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.bus.publishAgentMessage({ sessionId, content });\n break;\n }\n\n case 'exec_command_begin':\n case 'patch_apply_begin': {\n const toolName = msg.type === 'exec_command_begin' ? 'codex_exec_command' : 'codex_patch_apply';\n this.logger.debug({ sessionId, toolName, eventType: msg.type }, 'Publishing tool:start');\n const toolInput = msg.command ? { command: msg.command } : msg.changes ? { changes: msg.changes } : {};\n this.bus.publishToolStart({ sessionId, toolName, toolInput });\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:end');\n this.bus.publishToolEnd({ sessionId, toolName, output: typeof msg.output === 'string' ? msg.output : undefined });\n break;\n }\n\n case 'task_complete': {\n this.logger.info({ sessionId }, 'Task complete, forwarding finished and closing session');\n this.gateway.handleEvent(this.token, {\n type: 'finished',\n sessionId,\n timestamp,\n payload: { reason: 'completed' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n try {\n await this.gateway.getSessionManager().closeSession(sessionId);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Failed to close completed Codex session');\n }\n this.sessions.delete(sessionId);\n break;\n }\n\n case 'turn_aborted': {\n this.logger.info({ sessionId, reason: msg.reason || 'aborted' }, 'Turn aborted, forwarding session:end and closing session');\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp,\n payload: { reason: msg.reason || 'aborted' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n try {\n await this.gateway.getSessionManager().closeSession(sessionId);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Failed to close aborted Codex session');\n }\n this.sessions.delete(sessionId);\n break;\n }\n\n case 'tool:post':\n case 'tool:failure': {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Forwarding tool event to gateway');\n this.gateway.handleEvent(this.token, {\n type: msg.type as 'tool:post' | 'tool:failure',\n sessionId,\n timestamp,\n payload: msg as Record<string, unknown>,\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n break;\n }\n }\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0], sessionId: string): Promise<ReviewDecision> {\n const state = this.sessions.get(sessionId);\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 envelope: AgentEventEnvelope = {\n type: 'permission:request',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: {\n sessionId,\n toolName,\n toolInput: params.command ? { command: params.command } :\n params.fileChanges ? { fileChanges: params.fileChanges } :\n params.input ? { input: params.input } : {},\n },\n metadata: {\n agentType: this.agentType,\n transportType: this.transportType,\n permissionRequestId: params.callId,\n },\n };\n\n try {\n const response = await this.gateway.handleEvent(this.token, envelope);\n const decision = 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 private getHelpText(): string {\n return [\n 'Codex commands:',\n '/codex help - show this help message',\n '/codex status - show the current chat session state',\n '/codex stop - stop the active session for this chat',\n '/codex reset - stop and clear the active session',\n '/codex <prompt> - run a task in the current chat',\n 'Any other text is sent to Codex as a prompt.',\n ].join('\\n');\n }\n\n private normalizeInboundText(message: InboundMessage): string | null {\n const text = message.text.trim();\n\n const explicitCommand = text.match(/^\\/codex(?:@[^\\s]+)?(?:\\s+(.*))?$/s);\n if (explicitCommand) {\n return explicitCommand[1]?.trim() ?? '';\n }\n\n const aliasCommand = message.agentCommand\n ? text.match(/^\\/(status|help|stop|reset)(?:@[^\\s]+)?$/i)\n : null;\n if (aliasCommand) {\n return aliasCommand[1].toLowerCase();\n }\n\n return message.agentCommand ? null : text;\n }\n}\n","import type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\nimport {\n createPendingMap,\n addPending,\n resolvePending,\n abortAll,\n} from '../../../core/adapter/protocol/permissionUtils.js';\n\nexport class CodexProtocolHandler implements ProtocolHandler {\n readonly agentType = 'codex' as const;\n\n private pendingRequests = createPendingMap();\n\n fromAgent(event: unknown): InteractionRequest | null {\n return null;\n }\n\n toAgent(response: InteractionResponse): unknown {\n return {\n action: response.action === 'allow' ? 'allow' : response.action === 'deny' ? 'deny' : 'skip',\n };\n }\n\n abort(): void {\n abortAll(this.pendingRequests);\n }\n\n resolvePending(requestId: string, response: InteractionResponse): boolean {\n return resolvePending(this.pendingRequests, requestId, response);\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 { AgentEventEnvelope } from '../core/adapter/types.js';\n\n/** Minimal adapter interface for hook event translation */\ninterface HookEventAdapter {\n translate(rawEventType: string, payload: unknown): AgentEventEnvelope | null;\n}\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 * Setup HTTP routes for the Gateway\n */\nexport function setupRoutes(\n httpServer: HttpServer,\n gateway: Gateway,\n adapter: HookEventAdapter,\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 'Notification',\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 sessionCounts.set(session.token, (sessionCounts.get(session.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 // 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 const registeredAgents = gateway.listRegisteredAgents();\n logger.debug({ registeredTokenCount: registeredAgents.length, tokens: registeredAgents.map(a => a.token.substring(0, 8)) }, 'Registered agents');\n const isRegistered = registeredAgents.some((a) => a.token === token);\n if (!isRegistered) {\n logger.warn(`Auto-registering unknown token from hook request: ${token.substring(0, 8)}...`);\n gateway.registerAgent('claude', token);\n }\n\n logger.info({ eventType, token: token.substring(0, 8), body }, 'Hook payload received');\n\n // TODO: Refactor to use AgentAdapter interface - this translate() call is legacy technical debt\n const envelope = adapter.translate(eventType, body);\n if (!envelope) {\n sendJson(res, 202, { accepted: true });\n return;\n }\n\n const isPermissionHook = eventType === 'PreToolUse' || eventType === 'PermissionRequest';\n\n let result: Awaited<ReturnType<typeof gateway.handleEvent>>;\n if (isPermissionHook) {\n // Permission hooks wait for user decision; timeout is managed by InteractionQueue\n result = await gateway.handleEvent(token, envelope);\n } else {\n const HOOK_TIMEOUT_MS = 5000;\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Hook processing timeout')), HOOK_TIMEOUT_MS);\n });\n result = await Promise.race([\n gateway.handleEvent(token, envelope),\n timeoutPromise,\n ]);\n }\n\n if (result && typeof result.action === 'string') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n\n // Check if this is an AskUserQuestion (question:request type)\n const isAskUserQuestion = envelope.type === 'question:request';\n\n let responseBody: string;\n\n if (isAskUserQuestion && result._toolInput) {\n // AskUserQuestion uses PermissionRequest format with updatedInput\n // The answer needs to be formatted as: answers: { [questionText]: answerValue }\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 // Get the answer value (selectedValues from options or customInput)\n // Multi-select answers are comma-separated per AskUserQuestion schema\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 // Build updatedInput with answers\n const updatedInput: Record<string, unknown> = {\n ...result._toolInput,\n answers: question?.question\n ? { [question.question]: answerValue }\n : {},\n };\n\n responseBody = JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: 'allow',\n updatedInput,\n },\n },\n });\n logger.info({ eventType, isAskUserQuestion, response: responseBody }, 'Sending AskUserQuestion response');\n } else if (eventType === 'PermissionRequest') {\n // PermissionRequest uses PermissionRequest format\n // Build updatedPermissions for \"always allow\" if provided\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 responseBody = 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 && { data: result.selectedValues.map(String).join(', ') }),\n ...(updatedPermissions !== undefined && { updatedPermissions }),\n },\n },\n });\n logger.info({ eventType, response: responseBody }, 'Sending permission response');\n } else {\n // For PreToolUse and other hooks\n responseBody = JSON.stringify({\n accepted: ['allow', 'select', 'confirm'].includes(result.action),\n message: result.message,\n ...(result.selectedValues !== undefined && { data: result.selectedValues.map(String).join(', ') }),\n });\n logger.info({ eventType, response: responseBody }, 'Sending hook response');\n }\n\n res.end(responseBody);\n } else {\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';\nimport { ACKManager } from '../core/event/ack.js';\nimport type { AgentEvent } from '../core/event/types.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 private ackManager = new ACKManager();\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 /**\n * Send AgentEvent with optional ACK waiting\n */\n async sendAgentEvent(\n clientId: string,\n event: AgentEvent,\n waitForACK: boolean = false,\n timeoutMs?: number\n ): Promise<{ success: boolean; ack?: unknown; error?: string }> {\n const sent = this.send(clientId, {\n type: 'hep',\n event,\n });\n\n if (!sent) {\n return { success: false, error: 'Client not connected' };\n }\n\n if (waitForACK && event.ack_id) {\n try {\n const ack = await this.ackManager.waitForACK(event.ack_id, timeoutMs);\n return { success: true, ack };\n } catch (error) {\n return { success: false, error: String(error) };\n }\n }\n\n return { success: true };\n }\n\n /**\n * Handle incoming AgentEvent ACK message\n */\n handleAgentEventACK(message: { original_id: string; status: string; result?: unknown }): void {\n this.ackManager.handleACK({\n original_id: message.original_id,\n status: message.status as 'received' | 'processing' | 'completed' | 'failed',\n result: message.result,\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 hep:ack messages\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'hep:ack') {\n wsServer.handleAgentEventACK({\n original_id: message.original_id as string,\n status: message.status as string,\n result: message.result,\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', 'hep:ack'];\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 type { AgentEvent } from './types.js';\nimport { createAgentEvent } from './types.js';\n\nexport type ACKStatus = 'received' | 'processing' | 'completed' | 'failed';\n\nexport interface ACKEvent {\n original_id: string;\n status: ACKStatus;\n result?: unknown;\n error?: string;\n}\n\nexport class ACKManager {\n private pendingACKs = new Map<string, {\n resolve: (value: ACKEvent) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n }>();\n\n private defaultTimeoutMs: number;\n\n constructor(timeoutMs: number = 30000) {\n this.defaultTimeoutMs = timeoutMs;\n }\n\n /**\n * Wait for ACK of specific event\n */\n waitForACK(eventId: string, timeoutMs?: number): Promise<ACKEvent> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pendingACKs.delete(eventId);\n reject(new Error(`ACK timeout for event ${eventId}`));\n }, timeoutMs ?? this.defaultTimeoutMs);\n\n this.pendingACKs.set(eventId, { resolve, reject, timeout });\n });\n }\n\n /**\n * Handle incoming ACK event\n */\n handleACK(ack: ACKEvent): boolean {\n const pending = this.pendingACKs.get(ack.original_id);\n if (!pending) {\n return false;\n }\n\n clearTimeout(pending.timeout);\n this.pendingACKs.delete(ack.original_id);\n\n if (ack.status === 'failed') {\n pending.reject(new Error(ack.error || 'ACK failed'));\n } else {\n pending.resolve(ack);\n }\n\n return true;\n }\n\n /**\n * Create system:ack event\n */\n createACKEvent(\n originalEvent: AgentEvent,\n status: ACKStatus,\n result?: unknown,\n error?: string\n ): AgentEvent {\n const ackData: ACKEvent = {\n original_id: originalEvent.id,\n status,\n };\n\n if (result !== undefined) {\n ackData.result = result;\n }\n if (error !== undefined) {\n ackData.error = error;\n }\n\n return createAgentEvent(\n 'system:ack',\n 'system',\n originalEvent.session_id,\n 'system',\n 'gateway',\n {\n title: 'ACK',\n data: ackData as Record<string, unknown>,\n }\n );\n }\n\n /**\n * Cancel pending ACK\n */\n cancelACK(eventId: string): void {\n const pending = this.pendingACKs.get(eventId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingACKs.delete(eventId);\n pending.reject(new Error('ACK cancelled'));\n }\n }\n\n /**\n * Dispose of all pending ACKs (for shutdown)\n */\n dispose(): void {\n for (const [eventId, pending] of this.pendingACKs) {\n clearTimeout(pending.timeout);\n pending.reject(new Error('ACK manager disposed'));\n }\n this.pendingACKs.clear();\n }\n}\n\nexport const defaultACKManager = new ACKManager();\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","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 AgentMessageEvent,\n ToolStartEvent,\n ToolEndEvent,\n FinishedEvent,\n NotificationEvent,\n AllBusEvents,\n ProtocolEvent,\n} from './events.js';\nimport type { AgentEvent, AllEventType } from '../event/types.js';\nimport { createAgentEvent } from '../event/types.js';\nimport { validateAgentEventSafe } from '../event/schema.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 publishFinished(finished: Omit<FinishedEvent, 'type' | 'timestamp'>): void {\n const event: FinishedEvent = { ...finished, type: 'finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onFinished(handler: EventHandler<FinishedEvent>): () => void {\n return this.on('finished', 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 publishAgentMessage(event: Omit<AgentMessageEvent, 'type' | 'timestamp'>): void {\n const evt: AgentMessageEvent = { ...event, type: 'agent:message', timestamp: new Date() };\n this.emit(evt);\n }\n\n onAgentMessage(handler: EventHandler<AgentMessageEvent>): () => void {\n return this.on('agent:message', handler);\n }\n\n publishToolStart(event: Omit<ToolStartEvent, 'type' | 'timestamp'>): void {\n const evt: ToolStartEvent = { ...event, type: 'tool:start', timestamp: new Date() };\n this.emit(evt);\n }\n\n onToolStart(handler: EventHandler<ToolStartEvent>): () => void {\n return this.on('tool:start', handler);\n }\n\n publishToolEnd(event: Omit<ToolEndEvent, 'type' | 'timestamp'>): void {\n const evt: ToolEndEvent = { ...event, type: 'tool:end', timestamp: new Date() };\n this.emit(evt);\n }\n\n onToolEnd(handler: EventHandler<ToolEndEvent>): () => void {\n return this.on('tool:end', 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 * Publish Agent event\n */\n publishAgentEvent(event: AgentEvent): void {\n const validation = validateAgentEventSafe(event);\n if (!validation.success) {\n this.logger.error('Invalid Agent event:', validation.error);\n return;\n }\n\n this.emit({\n type: 'agent:event',\n timestamp: new Date(),\n event,\n } as ProtocolEvent);\n }\n\n /**\n * Create and publish Agent event\n */\n emitAgentEvent(\n type: AllEventType,\n direction: 'agent' | 'user' | 'system',\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Parameters<typeof createAgentEvent>[5]\n ): void {\n const event = createAgentEvent(type, direction, sessionId, agent, deviceId, payload);\n this.publishAgentEvent(event);\n }\n\n /**\n * Subscribe to Agent events\n */\n onAgentEvent(handler: (event: AgentEvent) => void): () => void {\n return this.on('agent:event', (evt: ProtocolEvent) => {\n handler(evt.event);\n });\n }\n\n /**\n * Subscribe to specific Agent event type\n */\n onAgentEventType(\n eventType: AllEventType,\n handler: (event: AgentEvent) => void\n ): () => void {\n return this.onAgentEvent((event) => {\n if (event.type === eventType) {\n handler(event);\n }\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 { z } from 'zod';\n\nexport const AGENT_EVENT_VERSION = '1.0.0';\n\nexport const AgentEventButtonSchema = z.object({\n text: z.string(),\n action: z.string(),\n});\n\nexport const AgentEventPayloadSchema = z.object({\n title: z.string().optional(),\n description: z.string().optional(),\n text: z.string().optional(),\n buttons: z.array(AgentEventButtonSchema).optional(),\n data: z.record(z.unknown()),\n extensions: z.record(z.unknown()).optional(),\n});\n\nexport const AgentEventSchema = z.object({\n id: z.string(),\n ts: z.number(),\n version: z.string(),\n type: z.string(),\n direction: z.enum(['agent', 'user', 'system']),\n session_id: z.string(),\n agent: z.string(),\n device_id: z.string(),\n ack_id: z.string().optional(),\n app: z.string().optional(),\n payload: AgentEventPayloadSchema,\n});\n\nexport type ValidatedAgentEvent = z.infer<typeof AgentEventSchema>;\n\n/**\n * Validate an AgentEvent. Throws ZodError if validation fails.\n * @throws {z.ZodError} When validation fails\n */\nexport function validateAgentEvent(data: unknown): ValidatedAgentEvent {\n return AgentEventSchema.parse(data);\n}\n\nexport function validateAgentEventSafe(data: unknown): { success: true; data: ValidatedAgentEvent } | { success: false; error: z.ZodError } {\n const result = AgentEventSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\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","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}","import type { AgentType } from '../adapter/types.js';\n\nexport 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 'sessions',\n 'system',\n]);\n\nexport const AGENT_COMMAND_ROOTS = new Set<AgentType>(['claude', 'codex']);\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 getExplicitAgentCommand(text: string): AgentType | undefined {\n const root = getSlashCommandRoot(text);\n if (!root) {\n return undefined;\n }\n return AGENT_COMMAND_ROOTS.has(root as AgentType) ? (root as AgentType) : undefined;\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 getExplicitAgentCommand,\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 explicitAgent = getExplicitAgentCommand(message.text);\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 (explicitAgent) {\n if (!boundAgent) {\n this.replyNoBinding(message, explicitAgent);\n return;\n }\n\n if (boundAgent !== explicitAgent) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: `This channel is bound to ${boundAgent}. Use /bind ${explicitAgent} first or send the command in the ${explicitAgent}-bound channel.`,\n replyToMessageId: message.messageId,\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: explicitAgent,\n },\n '[InboundRouter] Routed explicit agent command'\n );\n this.bus.publishInbound({\n ...message,\n targetAgent: explicitAgent,\n agentCommand: 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 private replyNoBinding(message: InboundMessage, explicitAgent: string): void {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: `No agent is bound to this channel. Bind ${explicitAgent} first with /bind ${explicitAgent}.`,\n replyToMessageId: message.messageId,\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 'Handsoff uses two command namespaces:',\n '- System commands: `/start`, `/help`, `/status`, `/bind`, `/new`, `/clear`, `/stop`, `/session`, `/sessions`',\n '- Agent commands: `/codex ...`, `/claude ...`',\n '',\n '**Default Message Routing**',\n '- Plain text is forwarded to the agent bound to this channel.',\n '- System commands are always handled by Handsoff.',\n '- Agent-prefixed commands are forwarded to the matching bound agent.',\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 '- `/sessions` list active sessions',\n '',\n '**Agent Commands**',\n '- `/codex help`, `/codex status`, `/codex reset`',\n '- `/claude help`, `/claude status` for hook-based Claude integration',\n '',\n 'If a command is not a system command, it will be routed 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 return [\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 ].join('\\n');\n },\n};\n\nexport const sessionsRootCommand: CommandHandler = {\n description: 'List active sessions',\n usage: '/sessions',\n handler: async (args, context): Promise<string> => listHandler.handler(args, context),\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 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 clearCommand: CommandHandler = {\n description: 'Clear the current chat session context',\n usage: '/clear',\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 '- Use `/codex ...` or `/claude ...` for agent-specific 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 sessionsRootCommand,\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 sessionsRootCommand,\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 registry.register('sessions', COMMAND_ROOT_SUBCOMMAND, sessionsRootCommand);\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 FinishedEvent,\n ToolFailureEvent,\n InteractionRequestEvent,\n AgentMessageEvent,\n ToolStartEvent,\n ToolEndEvent,\n} from '../core/bus/events.js';\nimport type { SessionContextProvider } from '../core/session-context.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 private sessionChatMap = new Map<string, string>();\n\n constructor(\n private bus: EventBus,\n private logger: Logger,\n private provider?: SessionContextProvider,\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.onAgentMessage(this.handleAgentMessage.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolStart(this.handleToolStart.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolEnd(this.handleToolEnd.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.onFinished(this.handleFinished.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 if (event.chatId) {\n this.sessionChatMap.set(event.sessionId, event.chatId);\n }\n await this.publishContext({\n eventType: 'session_start',\n sessionId: event.sessionId,\n chatId: event.chatId,\n userId: event.userId,\n });\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 chatId: event.chatId,\n userId: event.userId,\n reason: event.reason,\n });\n this.sessionChatMap.delete(event.sessionId);\n }\n\n private async handleInteractionRequest(event: InteractionRequestEvent): Promise<void> {\n // Map interaction type to legacy event type for backward compatibility\n const eventTypeMap: Record<string, NotificationContext['eventType']> = {\n 'permission': 'permission_request',\n 'question': 'question_request',\n 'input': 'interaction_request',\n 'confirm': 'interaction_request',\n };\n\n // Safely extract toolName from title\n const toolName = event.content.title?.replace(/^Permission Required: /, '') ?? '';\n\n await this.publishContext({\n eventType: eventTypeMap[event.interactionType] || 'interaction_request',\n sessionId: event.sessionId,\n chatId: event.chatId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction: {\n type: event.interactionType,\n requestId: event.requestId,\n content: event.content,\n },\n });\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 reason: event.error,\n });\n }\n\n private async handleFinished(event: FinishedEvent): Promise<void> {\n // The hook payload's lastAssistantMessage is from the CURRENT session turn and is authoritative.\n // The transcript might contain stale/incorrect data from a wrong file path.\n // We use transcript only for token/duration info, NOT for lastAssistantMessage.\n let summary;\n let transcriptLastAssistantMessage: string | undefined;\n if (this.provider) {\n const fullSummary = await this.provider.getSessionSummary(event.sessionId, event.transcriptPath);\n if (fullSummary) {\n transcriptLastAssistantMessage = fullSummary.lastAssistantMessage;\n // Only use transcript for tokens/duration, not lastAssistantMessage\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { lastAssistantMessage: _, ...transcriptData } = fullSummary;\n summary = transcriptData;\n }\n }\n\n // DEBUG: Log what we got from transcript vs hook payload\n this.logger.debug({\n sessionId: event.sessionId,\n hookLastAssistantMessage: event.lastAssistantMessage,\n transcriptLastAssistantMessage,\n }, 'handleFinished: comparing hook payload vs transcript');\n\n await this.publishContext({\n eventType: 'finished',\n sessionId: event.sessionId,\n chatId: event.chatId,\n lastAssistantMessage: event.lastAssistantMessage,\n summary,\n });\n }\n\n private async handleAgentMessage(event: AgentMessageEvent): Promise<void> {\n await this.publishContext({\n eventType: 'agent:message',\n sessionId: event.sessionId,\n messageContent: event.content,\n });\n }\n\n private async handleToolStart(event: ToolStartEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:start',\n sessionId: event.sessionId,\n toolName: event.toolName,\n toolInput: event.toolInput,\n });\n }\n\n private async handleToolEnd(event: ToolEndEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:end',\n sessionId: event.sessionId,\n toolName: event.toolName,\n reason: event.output ?? event.error,\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 const resolvedChatId = context.chatId ?? this.sessionChatMap.get(sessionId) ?? 'broadcast';\n\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId,\n agentType,\n channelInstanceId,\n channelType,\n resolvedChatId,\n },\n '[NotificationHandler] Routing notification to bound channel'\n );\n\n await this.bus.publishOutbound({\n channel: channelType,\n chatId: resolvedChatId,\n context,\n metadata: {\n eventType: context.eventType,\n channelInstanceId,\n resolvedChatId,\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 // 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 { readFile } from 'fs/promises';\nimport type { SessionContextProvider, SessionSummary } from '../../../core/session-context';\nimport { getLogger } from '../../../shared/logger.js';\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 }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport class ClaudeSessionContextProvider implements SessionContextProvider {\n async getSessionSummary(_sessionId: string, transcriptPath?: string): Promise<SessionSummary | undefined> {\n if (!transcriptPath) {\n return undefined;\n }\n\n const summary = await this.tryReadTranscript(transcriptPath);\n return summary;\n }\n\n private async tryReadTranscript(transcriptPath: string, maxAttempts = 5, delayMs = 200): Promise<SessionSummary | undefined> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const content = await readFile(transcriptPath, 'utf-8');\n const summary = this.parseTranscript(content);\n // Retry if summary has no data at all (no assistant message and no duration)\n // This handles the timing issue where transcript isn't fully written when Stop hook fires\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 // Log partial summary for debugging\n if (summary) {\n getLogger().debug({ attempt, summary }, 'Transcript read but incomplete, retrying...');\n }\n } catch (error) {\n lastError = error;\n }\n if (attempt < maxAttempts) {\n await sleep(delayMs);\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 private 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 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 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 const usage = entry.message?.usage;\n if (usage) {\n if (typeof usage.input_tokens === 'number') {\n inputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n outputTokens = usage.output_tokens;\n }\n }\n }\n }\n }\n\n function resolveDuration(assistantRef: { ts: number; uuid?: string; parentUuid?: string } | undefined): 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 const durationMs = resolveDuration(lastTextAssistant) ?? resolveDuration(lastAnyAssistant);\n\n const summary: SessionSummary = {\n ...(lastAssistantMessage !== undefined && { lastAssistantMessage }),\n ...(inputTokens !== undefined && { inputTokens }),\n ...(outputTokens !== undefined && { outputTokens }),\n ...(durationMs !== undefined && { durationMs }),\n };\n\n return summary;\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.cwd) {\n lines.push(`Working Dir: ${context.cwd}`);\n }\n if (context.toolInput && Object.keys(context.toolInput).length > 0) {\n lines.push('');\n lines.push('Args:');\n lines.push(JSON.stringify(context.toolInput, null, 2));\n }\n break;\n\n case 'finished':\n lines.push('✅ Task Completed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.summary?.durationMs !== undefined) {\n const seconds = (context.summary.durationMs / 1000).toFixed(1);\n lines.push(`Duration: ${seconds}s`);\n }\n if (context.summary?.inputTokens !== undefined && context.summary?.outputTokens !== undefined) {\n lines.push(`Tokens: in ${context.summary.inputTokens} / out ${context.summary.outputTokens}`);\n }\n if (context.lastAssistantMessage || context.summary?.lastAssistantMessage) {\n lines.push('');\n lines.push('Result:');\n lines.push(context.lastAssistantMessage || context.summary?.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 if (context.reason) {\n lines.push(`Reason: ${context.reason}`);\n }\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.reason) {\n lines.push(`Error: ${context.reason}`);\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, idx) => {\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';\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 `🔐 <b>${this.escape(title)}</b>`,\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 `❓ <b>${this.escape(title)}</b>`,\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 switch (context.eventType) {\n case 'permission_request':\n return this.formatPermissionRequest(\n 'Permission Request',\n context.toolName ?? 'Unknown',\n context.toolInput,\n context.cwd\n );\n\n case 'question_request':\n if (context.interaction?.content?.question) {\n const q = context.interaction.content.question;\n return this.formatQuestionRequest(\n context.interaction.content.title || 'Question',\n q.header,\n q.text,\n q.options\n );\n }\n return this.formatQuestionRequest(\n context.interaction?.content?.title || 'Question',\n undefined,\n context.interaction?.content?.description || '',\n []\n );\n\n case 'finished':\n return this.formatFinished(\n context.summary?.durationMs,\n context.summary?.inputTokens,\n context.summary?.outputTokens,\n context.summary?.lastAssistantMessage ?? context.lastAssistantMessage\n );\n\n case 'session_start':\n return `🚀 <b>Session Started</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'session_end':\n return `👋 <b>Session Ended</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'tool_failure':\n return `❌ <b>Tool Failed</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName ?? 'Unknown')}`;\n\n case 'agent:message':\n return this.truncate(`🤖 <b>Agent Message</b>\\n\\n${this.escape(context.messageContent || '')}`);\n\n case 'tool:start':\n return `🔧 <b>Tool Started</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName || 'Unknown')}`;\n\n case 'tool:end':\n return `✅ <b>Tool Completed</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName || 'Unknown')}`;\n\n default:\n return `📋 <b>Notification</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n }\n }\n\n /**\n * 格式化结果通知消息\n */\n formatFinished(\n durationMs?: number,\n inputTokens?: number,\n outputTokens?: number,\n result?: string\n ): string {\n const lines = [\n '✅ <b>Task Completed</b>',\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 */\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 interaction = message.context?.interaction;\n const requestId = message.context?.requestId;\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 = message.context?.toolName || '';\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.content.question) {\n const question = interaction.content.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 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 { 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' || message.metadata?.eventType === 'question_request') &&\n message.chatId === '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 interaction = message.context?.interaction;\n const requestId = message.context?.requestId;\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 = message.context?.toolName || '';\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.content.question) {\n const question = interaction.content.question;\n this.pendingOptions.set(\n requestId,\n question.options.map((opt) => ({ id: opt.id, value: opt.value }))\n );\n buttons = question.options.map((opt) => ({\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 || !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 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 'permission_request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Working Dir:** ${context.cwd || 'N/A'}\\n\\n`;\n md += `**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n break;\n case 'finished':\n md = `**Session:** ${context.sessionId}\\n`;\n if (context.summary?.durationMs !== undefined) {\n md += `**Duration:** ${(context.summary.durationMs / 1000).toFixed(1)}s\\n`;\n }\n {\n const msg = context.summary?.lastAssistantMessage ?? context.lastAssistantMessage;\n if (msg) {\n md += `\\n**Result:**\\n${msg}`;\n }\n }\n break;\n case 'agent:message':\n md = `Agent Message\\n\\n**Session:** ${context.sessionId}\\n\\n**Message:**\\n${context.messageContent || ''}`;\n break;\n case 'tool:start':\n md = `**Session:** ${context.sessionId}\\n**Tool:** ${context.toolName || 'N/A'}\\n\\n**Status:** Started`;\n break;\n case 'tool:end':\n md = `**Session:** ${context.sessionId}\\n**Tool:** ${context.toolName || 'N/A'}\\n\\n**Status:** Completed`;\n break;\n default:\n md = `**Event:** ${context.eventType}\\n**Session:** ${context.sessionId}`;\n }\n return md;\n }\n\n /**\n * 根据上下文获取标题\n */\n private getTitleForContext(context?: NotificationContext): string {\n if (!context) return 'Notification';\n switch (context.eventType) {\n case 'permission_request':\n return 'Permission Request';\n case 'finished':\n return 'Task Completed';\n case 'session_start':\n return 'Session Started';\n case 'session_end':\n return 'Session Ended';\n case 'tool_failure':\n return 'Tool Failed';\n case 'agent:message':\n return 'Agent Message';\n case 'tool:start':\n return 'Tool Started';\n case 'tool:end':\n return 'Tool Completed';\n default:\n return 'Notification';\n }\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 } 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',\n timestamp,\n payload: {\n sessionId: context.sessionId,\n message: {\n id: options.createMessageId?.() ?? createId('msg'),\n sessionId: context.sessionId,\n role: 'assistant',\n type: 'text',\n text: context.messageContent ?? message.text ?? '',\n createdAt: timestamp,\n status: 'completed',\n metadata: {},\n },\n },\n };\n\n case 'permission_request':\n case 'question_request':\n case 'interaction_request':\n return mapInteractionRequested(context, eventId, timestamp);\n\n case 'finished':\n return {\n type: 'event',\n eventId,\n name: 'agent.finished',\n timestamp,\n payload: {\n sessionId: context.sessionId,\n reason: context.reason,\n lastAssistantMessage: context.lastAssistantMessage,\n summary: context.summary,\n },\n };\n\n default:\n return null;\n }\n}\n\nfunction mapInteractionRequested(\n context: NotificationContext,\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.content.title,\n description: interaction.content.description,\n status: 'pending',\n createdAt: timestamp,\n toolName: context.toolName,\n toolInput: context.toolInput,\n riskLevel: interaction.content.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 } 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 metadata?: Record<string, unknown>,\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 if (typeof payload.cwd === 'string' && payload.cwd.trim() !== '') {\n metadata.cwd = payload.cwd;\n metadata.workspacePath = payload.cwd;\n }\n\n await gateway.createSession(connection.token, sessionId, metadata);\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 const session = options.gateway.getSession(pendingSessionId);\n if (!session?.protocolHandler.resolvePending(payload.interactionId, response)) {\n return error(frame.id, 'NOT_IMPLEMENTED', 'Interaction response transport is unavailable');\n }\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:\n readString(metadata.workspacePath) ??\n readString(metadata.cwd) ??\n readString(metadata.workDir) ??\n readString(metadata.work_dir),\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","#!/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 { ClaudeHookAdapter } from '../adapters/agent/claude/hook/index.js';\nimport { CodexAppServerAdapter } from '../adapters/agent/codex/index.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 { ClaudeSessionContextProvider } from '../adapters/agent/claude/session-context.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 { 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 // Start NotificationHandler\n const sessionContextProvider = new ClaudeSessionContextProvider();\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 sessionContextProvider,\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: CodexAppServerAdapter | undefined;\n if (config.agent.codex?.enabled) {\n const codexToken = gateway.getAgentRegistry().registerAgent('codex');\n codexAdapter = new CodexAppServerAdapter({\n bus,\n logger: createAgentLogger('codex'),\n 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 adapter = new ClaudeHookAdapter({\n logger: createAgentLogger('claude'),\n bus,\n gateway,\n token: hookToken,\n });\n await adapter.initialize();\n // Adapter is now registered in AgentAdapterRegistry for discovery by other components\n setupRoutes(httpServer, gateway, adapter, () => 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.channels?.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.channels.app.channel_id,\n auth_token: config.channels.app.auth_token,\n heartbeat_interval_ms: config.channels.app.heartbeat_interval_ms,\n notify_types: config.channels.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","z","i","acc","ext","start","final","ext","qmark","star","regExpEscape","i","match","existsSync","readFileSync","error","readFileSync","existsSync","join","error","logger","logger","filter","randomUUID","hostname","resolve","error","join","resolve","randomUUID","error","randomUUID","randomUUID","randomUUID","path","error","filter","defaults","resolve","match","randomUUID","readdir","readFile","join","existsSync","match","createServer","URL","logger","path","createServer","URL","resolve","error","match","URL","resolve","error","VERSION","logger","path","resolve","URL","error","filter","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","homedir","join","homedir","path","existsSync","readFileSync","error","randomUUID","randomUUID","resolve","error","logger","error","resolve","writeFileSync","join","homedir","TOML","logger","logger","logger","error","logger","logger","oldChannelId","bindingService","bindingService","process","formatDuration","logger","logger","logger","logger","bindingService","readFile","resolve","readFile","error","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","VERSION","homedir","logger","bindingService","error"]}
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/config.ts","../../src/gateway/interaction-service.ts","../../src/gateway/index.ts","../../src/gateway/publisher.ts","../../src/adapters/agent/claude/ClaudeAdapter.ts","../../src/core/session-scanner/registry.ts","../../src/adapters/agent/claude/hook/HookServer.ts","../../src/core/event/types.ts","../../src/core/adapter/protocol/claude/ClaudeEventMapper.ts","../../src/adapters/agent/claude/scanner.ts","../../src/core/adapter/protocol/claude/ClaudeProtocolHandler.ts","../../src/core/adapter/protocol/permissionUtils.ts","../../src/adapters/agent/claude/session-context.ts","../../src/adapters/agent/claude/ClaudeRemoteAdapter.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/codex/CodexAppServerAdapter.ts","../../src/adapters/agent/codex/CodexProtocolHandler.ts","../../src/adapters/agent/codex/codexAppServerClient.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/core/event/ack.ts","../../src/shared/credentials.ts","../../src/adapters/interaction/queue.ts","../../src/core/bus/index.ts","../../src/core/event/schema.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/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/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.onAgentMessage((e) => this.write(e.sessionId, 'agent:message', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolStart((e) => this.write(e.sessionId, 'tool:start', 'agent', e))\n );\n this.unsubscribeFns.push(\n this.bus.onToolEnd((e) => this.write(e.sessionId, 'tool:end', '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.onFinished((e) => this.write(e.sessionId, '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 handle = await adapter.createSession({\n ...options,\n });\n\n const session = new Session({\n id: sessionId,\n agentType,\n adapter,\n protocolHandler: adapter.protocolHandler,\n handle,\n token: options?.token,\n metadata: options?.metadata,\n });\n\n this.sessions.set(sessionId, session);\n this.logger.info({ sessionId, agentType, 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 } from '../adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../adapter/protocol/ProtocolHandler.js';\nimport type { AgentCommand, SessionHandle, 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 protocolHandler: ProtocolHandler;\n readonly createdAt: number;\n\n private status: 'active' | 'closed' | 'archived' = 'active';\n private handle: SessionHandle;\n\n constructor(options: {\n id: string;\n agentType: 'claude' | 'codex';\n adapter: AgentAdapter;\n protocolHandler: ProtocolHandler;\n handle: SessionHandle;\n token?: string;\n metadata?: Record<string, unknown>;\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.protocolHandler = options.protocolHandler;\n this.handle = options.handle;\n this.createdAt = 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.handle.sendCommand(command);\n }\n\n async close(): Promise<void> {\n if (this.status !== 'active') {\n return;\n }\n // Abort any pending protocol requests to prevent memory leaks\n this.protocolHandler.abort();\n await this.handle.close();\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 };\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 if (!rule.pattern) {\n return true;\n }\n\n // For Bash tools, match against the command\n if (toolName === 'Bash' && 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, rule.pattern) || matchesPattern(firstWord, rule.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, rule.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'].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\nconst DEFAULT_LOW_RISK_TOOLS = ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'] as const;\n\n/**\n * Check if a tool is low-risk (Claude Code won't prompt for permission)\n * @param toolName The name of the tool to check\n * @param lowRiskTools Optional custom list of low-risk tools\n */\nexport function isLowRiskTool(toolName: string, lowRiskTools: readonly string[] = DEFAULT_LOW_RISK_TOOLS): boolean {\n return lowRiskTools.includes(toolName);\n}\n\n/**\n * Check only deny rules for low-risk tools\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 { 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 default_agent: string;\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 AgentPermissionConfig {\n lowRiskTools: string[];\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n sandbox_mode: 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}\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 ChannelsConfig {\n app?: AppChannelConfig;\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig & { permission?: AgentPermissionConfig };\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 channels?: ChannelsConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n default_agent: 'claude',\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 },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n permission: {\n lowRiskTools: ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'],\n },\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n sandbox_mode: '',\n },\n },\n channels: {},\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 },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n permission: {\n ...DEFAULT_CONFIG.agent.claude!.permission,\n ...(raw.agent?.claude?.permission || {}),\n },\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 sandbox_mode: raw.agent?.codex?.sandbox_mode || DEFAULT_CONFIG.agent.codex!.sandbox_mode,\n },\n },\n channels: {\n ...DEFAULT_CONFIG.channels,\n ...(raw.channels || {}),\n app: raw.channels?.app\n ? {\n enabled: raw.channels.app.enabled === true,\n channel_id: String(raw.channels.app.channel_id || ''),\n auth_token: String(raw.channels.app.auth_token || ''),\n heartbeat_interval_ms: raw.channels.app.heartbeat_interval_ms\n ? parseInt(String(raw.channels.app.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channels.app.notify_types)\n ? raw.channels.app.notify_types.map(String)\n : undefined,\n }\n : DEFAULT_CONFIG.channels?.app,\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 { InteractionQueue } from '../adapters/interaction/index.js';\nimport { loadPermissionsConfig, checkPermission, checkDenyOnly, isLowRiskTool } from '../shared/permissions.js';\nimport { loadConfig } from '../config.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 (agentType === 'codex') {\n // Codex approvals should be resolved by the bound channel, not Claude's low-risk rules.\n return { immediate: false };\n }\n\n if (permissionMode === 'bypassPermissions') {\n return {\n immediate: true,\n response: { requestId: '', action: 'allow', message: 'permissionMode is bypassPermissions' },\n };\n }\n\n const config = loadConfig();\n const projectConfig = cwd ? loadPermissionsConfig(cwd) : null;\n\n if (isLowRiskTool(toolName, config.agent?.claude?.permission?.lowRiskTools)) {\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: 'Low-risk tool, no deny match' },\n };\n }\n\n if (permissionMode === 'acceptEdits' && ['Edit', 'Write', 'MultiEdit'].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.metadata.sessionId || envelope.sessionId);\n const toolName = String(payload.toolName);\n const toolInput = payload.toolInput || {};\n const permissionMode = (envelope.metadata.permission_mode as string) || 'auto';\n const cwd = (envelope.metadata.cwd as string) || '';\n const agentType = String(envelope.metadata.agentType || 'claude');\n\n logger.info({ sessionId, toolName, type: envelope.type }, '[Interaction] Request received');\n\n // Determine interaction type\n const interactionType = envelope.type === 'question:request' ? 'question' : 'permission';\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 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 } from '../core/adapter/types.js';\nimport { InteractionService } from './interaction-service.js';\nimport { EventPublisher } from './publisher.js';\nimport type { 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';\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 */\nexport class Gateway {\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 */\n async createSession(\n token: string,\n sessionId: string,\n metadata?: Record<string, unknown>\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 { sessionId, metadata, token }\n );\n\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 payload: metadata ?? {},\n metadata: { agentType: session.agentType, transportType: session.adapter.transportType },\n },\n session\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 endSession(sessionId: string): void {\n // For now, closeSession is async but endSession is sync in old API\n // We need to handle this - for HTTP context, we'll await it\n this.sessionManager.closeSession(sessionId).catch((err) => {\n console.error(`Failed to end session ${sessionId}:`, err);\n });\n }\n\n /**\n * Handle an incoming event from an agent\n */\n async handleEvent(\n token: string,\n envelope: AgentEventEnvelope\n ): Promise<InteractionResponse | undefined> {\n const sessionId = envelope.sessionId;\n if (!sessionId) {\n return;\n }\n\n // Validate token\n if (!this.agentRegistry.isTokenRegistered(token)) {\n return;\n }\n\n let session = this.sessionManager.getSession(sessionId);\n if (!session) {\n try {\n session = await this.createSession(\n token,\n sessionId,\n envelope.payload as Record<string, unknown>\n );\n } catch {\n return;\n }\n }\n\n if (envelope.type === 'session:end') {\n this.sessionManager.closeSession(sessionId).catch((err) => {\n console.error(`Failed to close session ${sessionId}:`, err);\n });\n }\n\n // Handle interaction requests (permission, question, etc.)\n if (envelope.type === 'permission:request' || envelope.type === 'question:request') {\n this.eventPublisher.publish(envelope, session);\n return await this.interactionService.evaluate(envelope);\n }\n\n this.eventPublisher.publish(envelope, session);\n return undefined;\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\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 this.bus.publishSessionStart({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n agentType: session.agentType,\n });\n break;\n case 'session:end':\n this.bus.publishSessionEnd({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n });\n break;\n case 'finished':\n this.bus.publishFinished({\n sessionId: session.id,\n chatId: session.metadata.chatId as string ?? session.id,\n userId: session.token ?? 'unknown',\n reason: envelope.payload.reason as string | undefined,\n lastAssistantMessage: envelope.payload.lastAssistantMessage as string | undefined,\n transcriptPath: envelope.payload.transcriptPath as string | undefined,\n });\n break;\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:post':\n this.bus.publishToolPost({\n sessionId: session.id,\n toolName: envelope.payload.toolName as string,\n toolInput: envelope.payload.toolInput as Record<string, unknown> | undefined,\n output: envelope.payload.output as string | 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 }\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/ClaudeAdapter.ts\n// Unified Claude Adapter using AgentEvent as internal format\n\nimport { randomUUID } from 'crypto';\nimport type { Logger } from 'pino';\nimport type {\n AgentAdapter,\n AgentEventEnvelope,\n CreateSessionOptions,\n SessionHandle,\n SessionInfo,\n PermissionResponseCommand,\n} from '../../../core/adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport type { Gateway } from '../../../gateway/index.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\nimport { HookServer } from './hook/HookServer.js';\nimport type { AgentEvent } from '../../../core/event/types.js';\nimport { ClaudeSessionScanner } from './scanner.js';\nimport { ClaudeProtocolHandler } from '../../../core/adapter/protocol/claude/ClaudeProtocolHandler.js';\nimport {\n mapClaudeToAgentEvent,\n mapClaudeToAgentEventEnvelope,\n isClaudeHookEventType,\n} from './ClaudeEventMapper.js';\n\n/**\n * Claude Adapter\n *\n * Uses AgentEvent as the internal event format.\n * Supports both legacy and unified hook URL formats.\n *\n * Event flow:\n * Claude Code → HookServer → AgentEvent → (Optional: AgentEventEnvelope) → Gateway\n *\n * Benefits:\n * - Single event pipeline\n * - Standardized AgentEvent format for all internal processing\n * - Backward compatible with existing Gateway interface\n */\nexport class ClaudeAdapter implements AgentAdapter {\n readonly agentType = 'claude';\n readonly transportType = 'hook';\n readonly version = '2.0.0';\n readonly protocolHandler: ProtocolHandler = new ClaudeProtocolHandler();\n\n private hookServer: HookServer | null = null;\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private agentEventHandler: ((event: AgentEvent) => void) | null = null;\n private sessions: Map<string, SessionInfo> = new Map();\n private pendingPermissionHandlers: Map<string, (decision: PermissionResponseCommand) => void> = new Map();\n private port: number = 0;\n private token: string = '';\n private _initializing: Promise<void> | null = null;\n private static scanner: ClaudeSessionScanner | null = null;\n private logger: Logger | undefined;\n private bus?: EventBus;\n private gateway?: Gateway;\n private inboundUnsubscribe: (() => void) | null = null;\n\n constructor(options?: { logger?: Logger; bus?: EventBus; gateway?: Gateway; token?: string }) {\n this.logger = options?.logger;\n this.bus = options?.bus;\n this.gateway = options?.gateway;\n this.token = options?.token ?? '';\n }\n\n async initialize(): Promise<void> {\n // Register Claude SessionScanner\n if (!ClaudeAdapter.scanner) {\n ClaudeAdapter.scanner = new ClaudeSessionScanner();\n SessionScannerRegistry.getInstance().register(ClaudeAdapter.scanner);\n this.logger?.info('Claude session scanner registered');\n }\n\n // Register with AgentAdapterRegistry for discovery\n AgentAdapterRegistry.getInstance().register(this);\n this.logger?.info('Claude adapter initialized');\n\n if (this.bus && !this.inboundUnsubscribe) {\n this.inboundUnsubscribe = this.bus.onInbound((message) => this.handleInboundMessage(message));\n this.logger?.debug('Subscribed Claude adapter to inbound messages');\n }\n }\n\n async shutdown(): Promise<void> {\n this.logger?.info('Claude adapter shutting down');\n await this.hookServer?.stop();\n this.sessions.clear();\n this.pendingPermissionHandlers.clear();\n this.inboundUnsubscribe?.();\n this.inboundUnsubscribe = null;\n }\n\n async createSession(opts: CreateSessionOptions): Promise<SessionHandle> {\n if (!this.hookServer) {\n if (this._initializing) {\n await this._initializing;\n } else {\n this._initializing = (async () => {\n this.token = (opts.agentOptions?.token as string) || this.generateToken();\n this.port = opts.hookPort || 0;\n\n this.hookServer = new HookServer({\n port: this.port,\n token: this.token,\n logger: this.logger,\n // AgentEvent handler (new style)\n onAgentEvent: (agentEvent) => {\n this.logger?.debug({ agentEventType: agentEvent.type, sessionId: agentEvent.session_id }, 'Forwarding AgentEvent to handler');\n if (this.agentEventHandler) {\n this.agentEventHandler(agentEvent);\n } else {\n this.logger?.warn({ agentEventType: agentEvent.type }, 'No agentEventHandler registered');\n }\n },\n // Legacy event handler (backward compatible)\n onEvent: (envelope) => {\n this.logger?.debug({ eventType: envelope.type, sessionId: envelope.sessionId }, 'Forwarding legacy envelope to handler');\n if (this.eventHandler) {\n this.eventHandler(envelope);\n } else {\n this.logger?.warn({ eventType: envelope.type }, 'No eventHandler registered');\n }\n },\n // Permission request handler\n onPermissionRequest: (envelope, respond) => {\n const requestId = envelope.metadata.permissionRequestId || envelope.sessionId;\n this.logger?.info({ eventType: envelope.type, sessionId: envelope.sessionId, requestId }, 'Permission request received from hook');\n this.pendingPermissionHandlers.set(requestId, respond);\n\n // Emit to both handlers\n if (this.agentEventHandler) {\n // Convert envelope back to AgentEvent for the handler\n const agentEvent = this.convertEnvelopeToAgentEvent(envelope);\n if (agentEvent) {\n this.logger?.debug({ requestId, agentEventType: agentEvent.type }, 'Forwarding permission as AgentEvent');\n this.agentEventHandler(agentEvent);\n }\n }\n if (this.eventHandler) {\n this.logger?.debug({ requestId, envelopeType: envelope.type }, 'Forwarding permission as legacy envelope');\n this.eventHandler(envelope);\n }\n },\n });\n\n this.port = await this.hookServer.start(this.port);\n })();\n await this._initializing;\n this._initializing = null;\n }\n }\n\n const sessionId = this.generateSessionId();\n const handle: SessionHandle = {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n createdAt: new Date(),\n sendCommand: async (command) => {\n if (command.type === 'permission:response') {\n const responder = this.pendingPermissionHandlers.get(command.requestId);\n if (responder) {\n responder(command);\n this.pendingPermissionHandlers.delete(command.requestId);\n }\n }\n },\n close: async () => {\n this.sessions.delete(sessionId);\n },\n };\n\n this.sessions.set(sessionId, {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: new Date(),\n cwd: opts.cwd,\n });\n\n this.logger?.info({ sessionId, port: this.port }, 'Claude session created');\n return handle;\n }\n\n async closeSession(handle: SessionHandle): Promise<void> {\n await handle.close();\n this.sessions.delete(handle.id);\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return Array.from(this.sessions.values());\n }\n\n async getSession(sessionId: string): Promise<SessionInfo | undefined> {\n return this.sessions.get(sessionId);\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n this.logger?.debug('Legacy event handler registered');\n }\n\n /**\n * Set handler for AgentEvents (new style)\n */\n setAgentEventHandler(handler: (event: AgentEvent) => void): void {\n this.agentEventHandler = handler;\n this.logger?.debug('AgentEvent handler registered');\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return {\n healthy: this.hookServer !== null,\n message: this.hookServer ? `Hook server running on port ${this.port}` : 'Not initialized',\n };\n }\n\n getPort(): number {\n return this.port;\n }\n\n getToken(): string {\n return this.token;\n }\n\n /**\n * Get the unified hook URL (recommended)\n * All events are sent to this single URL with event_type in the body\n */\n getHookUrl(): string {\n if (!this.hookServer) {\n return '';\n }\n return this.hookServer.getHookUrl(this.port);\n }\n\n /**\n * Get legacy hook URL for a specific event type\n * @deprecated Use getHookUrl() for unified endpoint\n */\n getLegacyHookUrl(eventType: string): string {\n if (!this.hookServer) {\n return '';\n }\n return this.hookServer.getLegacyHookUrl(this.port, eventType);\n }\n\n /**\n * Get the settings.json hooks configuration (unified format)\n */\n getSettingsConfig(): Record<string, unknown> {\n const hookUrl = this.getHookUrl();\n if (!hookUrl) {\n throw new Error('Hook server not initialized. Call createSession first.');\n }\n\n return {\n hooks: {\n SessionStart: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n SessionEnd: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n Stop: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PreToolUse: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PermissionRequest: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PostToolUse: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n PostToolUseFailure: [{ matcher: '', hooks: [{ type: 'http', url: hookUrl }] }],\n },\n };\n }\n\n /**\n * Convert AgentEventEnvelope to AgentEvent (simplified)\n * This is used when we need to emit AgentEvent from legacy envelope\n */\n private convertEnvelopeToAgentEvent(envelope: AgentEventEnvelope): AgentEvent | null {\n // Map back from raw event type\n const rawEventType = envelope.metadata.rawEventType;\n if (!rawEventType) return null;\n\n // Build payload from envelope\n const payload: Record<string, unknown> = {\n session_id: envelope.sessionId,\n ...envelope.payload,\n };\n\n if (envelope.metadata.cwd) {\n payload.cwd = envelope.metadata.cwd;\n }\n\n return mapClaudeToAgentEvent(rawEventType as any, payload, 'claude');\n }\n\n /**\n * Check if this adapter can handle the given raw event type\n * @deprecated Use the isClaudeHookEventType function instead\n */\n canHandle(rawEventType: string): boolean {\n return isClaudeHookEventType(rawEventType);\n }\n\n /**\n * @deprecated Still used by setupRoutes in src/server/http.ts\n * This provides backward compatibility for the HTTP route handler\n */\n translate(rawEventType: string, payload: unknown): AgentEventEnvelope | null {\n this.logger?.debug({ rawEventType }, 'translate called');\n if (!payload || typeof payload !== 'object') {\n this.logger?.warn({ rawEventType }, 'translate failed: invalid payload');\n return null;\n }\n\n if (!['SessionStart', 'SessionEnd', 'PreToolUse', 'PermissionRequest',\n 'PostToolUse', 'PostToolUseFailure', 'Stop'].includes(rawEventType)) {\n this.logger?.warn({ rawEventType }, 'translate failed: unsupported event type');\n return null;\n }\n\n const envelope = mapClaudeToAgentEventEnvelope(\n rawEventType as any,\n payload as Record<string, unknown>,\n 'claude'\n );\n if (envelope) {\n this.logger?.info({ rawEventType, envelopeType: envelope.type, sessionId: envelope.sessionId }, 'Event translated');\n } else {\n this.logger?.warn({ rawEventType }, 'translate failed: mapping returned null');\n }\n return envelope;\n }\n\n private generateToken(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n }\n\n private generateSessionId(): string {\n return `claude-${randomUUID().slice(0, 8)}`;\n }\n\n private handleInboundMessage(message: InboundMessage): void {\n if (!this.bus) {\n return;\n }\n\n this.logger?.debug(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n targetAgent: message.targetAgent,\n agentCommand: message.agentCommand,\n textPreview: message.text.slice(0, 80),\n },\n 'Claude inbound message received'\n );\n\n if (message.systemCommand || message.targetAgent !== 'claude') {\n return;\n }\n\n const normalized = this.normalizeInboundText(message);\n if (normalized === null) {\n return;\n }\n\n const [keyword, ...rest] = normalized.split(/\\s+/);\n const lowered = keyword.toLowerCase();\n const commandOnly = rest.length === 0;\n\n if (!normalized || (lowered === 'help' && commandOnly)) {\n this.reply(message, this.getHelpText());\n return;\n }\n\n if (lowered === 'status' && commandOnly) {\n this.reply(message, this.getStatusText());\n return;\n }\n\n if ((lowered === 'reset' || lowered === 'stop') && commandOnly) {\n this.reply(\n message,\n 'Claude chat sessions are not owned by Handsoff. Stop or restart the local Claude Code session in your workspace, then continue here for approvals and notifications.'\n );\n return;\n }\n\n this.reply(message, this.getPromptingNotSupportedText());\n }\n\n private normalizeInboundText(message: InboundMessage): string | null {\n const text = message.text.trim();\n const explicitCommand = text.match(/^\\/claude(?:@[^\\s]+)?(?:\\s+(.*))?$/s);\n if (explicitCommand) {\n return explicitCommand[1]?.trim() ?? '';\n }\n\n return message.agentCommand ? null : text;\n }\n\n private getHelpText(): string {\n return [\n 'Claude commands:',\n '/claude help - show this help message',\n '/claude status - show Claude hook status',\n '/claude stop - explain how to stop the local Claude session',\n '/claude reset - explain how to reset the local Claude session',\n '',\n 'Current Claude integration is hook-based.',\n 'Send prompts in your local Claude Code workspace, and use Handsoff channels for approvals, notifications, and status.',\n ].join('\\n');\n }\n\n private getStatusText(): string {\n const activeSessions = Array.from(this.sessions.values()).filter((session) => session.status === 'active');\n const hookStatus = this.hookServer ? `running on port ${this.port}` : 'not initialized';\n\n return [\n '**Claude Status**',\n '',\n `Hook server: ${hookStatus}`,\n `Tracked Claude sessions: ${activeSessions.length}`,\n this.token ? `Registered token: ${this.token.slice(0, 8)}...` : 'Registered token: unavailable',\n '',\n 'Claude sessions are started from the local Claude Code client, not from the chat channel.',\n ].join('\\n');\n }\n\n private getPromptingNotSupportedText(): string {\n return [\n 'This channel is bound to Claude, but the current Claude integration is hook-based.',\n 'Start or continue the task from your local Claude Code session, and use this channel for approvals, notifications, and `/claude status`.',\n ].join('\\n');\n }\n\n private reply(message: InboundMessage, text: string): void {\n this.bus?.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text,\n replyToMessageId: message.messageId,\n });\n }\n}\n\n// Re-export for backward compatibility\nexport { ClaudeAdapter as ClaudeHookAdapter };\nexport { HookServer } from './hook/HookServer.js';\nexport {\n mapClaudeToAgentEvent,\n mapAgentEventToAgentEventEnvelope,\n mapClaudeToAgentEventEnvelope,\n calculateRiskLevel,\n createPermissionDecisionEvent,\n isClaudeHookEventType,\n type ClaudeHookEventType,\n} from './ClaudeEventMapper.js';\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/hook/HookServer.ts\n// Unified Hook Server - supports both legacy and unified URL formats\n\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport type { Logger } from 'pino';\nimport type {\n AgentEventEnvelope,\n PermissionResponseCommand,\n} from '../../../../core/adapter/types.js';\nimport type { AgentEvent } from '../../../../core/event/types.js';\nimport {\n isClaudeHookEventType,\n mapClaudeToAgentEvent,\n mapAgentEventToAgentEventEnvelope,\n} from '../ClaudeEventMapper.js';\n\nexport interface HookServerOptions {\n port: number;\n token: string;\n logger?: Logger;\n /** Legacy event handler (for backward compatibility) */\n onEvent?: (envelope: AgentEventEnvelope) => void;\n /** AgentEvent handler (new style) */\n onAgentEvent?: (event: AgentEvent) => void;\n /** Permission request handler with response callback */\n onPermissionRequest?: (\n envelope: AgentEventEnvelope,\n respond: (decision: PermissionResponseCommand) => void\n ) => void;\n}\n\ninterface PendingRequest {\n response: ServerResponse;\n timeout: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Unified Hook Server\n *\n * Supports two URL formats:\n * 1. Legacy: /hook/{token}/{eventType} (event type in URL path)\n * 2. Unified: /hook/{token}/event (event type in body.hook_event_name)\n *\n * Events are always converted to:\n * - AgentEvent format (for new consumers)\n * - AgentEventEnvelope format (for backward compatibility)\n */\nexport class HookServer {\n private server: ReturnType<typeof createServer> | null = null;\n private pendingRequests: Map<string, PendingRequest> = new Map();\n private token: string;\n private onEvent: HookServerOptions['onEvent'];\n private onAgentEvent: HookServerOptions['onAgentEvent'];\n private onPermissionRequest: HookServerOptions['onPermissionRequest'];\n private logger: Logger | undefined;\n\n constructor(options: HookServerOptions) {\n this.token = options.token;\n this.onEvent = options.onEvent;\n this.onAgentEvent = options.onAgentEvent;\n this.onPermissionRequest = options.onPermissionRequest;\n this.logger = options.logger;\n }\n\n async start(port: number): Promise<number> {\n return new Promise((resolve, reject) => {\n this.server = createServer(this.handleRequest.bind(this));\n this.server.on('error', reject);\n this.server.listen(port, () => {\n const address = this.server?.address();\n const actualPort =\n typeof address === 'object' && address ? address.port : port;\n this.logger?.info({ port: actualPort }, 'Claude hook server listening');\n resolve(actualPort);\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise((resolve) => {\n this.logger?.info('Claude hook server stopping');\n // Clear all pending requests\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timeout);\n pending.response.writeHead(503, { 'Content-Type': 'application/json' });\n pending.response.end(\n JSON.stringify({ accepted: false, error: 'Server shutting down' })\n );\n }\n this.pendingRequests.clear();\n this.server?.close(() => {\n this.logger?.info('Claude hook server stopped');\n resolve();\n });\n });\n }\n\n resolvePermission(requestId: string, decision: PermissionResponseCommand): void {\n const pending = this.pendingRequests.get(requestId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRequests.delete(requestId);\n\n const behavior =\n decision.decision === 'allow'\n ? 'allow'\n : decision.decision === 'always_allow'\n ? 'always_allow'\n : 'deny';\n\n pending.response.writeHead(200, { 'Content-Type': 'application/json' });\n pending.response.end(\n JSON.stringify({\n hookSpecificOutput: {\n decision: { behavior, message: '' },\n },\n })\n );\n }\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url || '/', 'http://localhost');\n const pathname = url.pathname;\n\n this.logger?.debug({ method: req.method, url: pathname }, 'Hook request received');\n\n // Token validation\n const tokenMatch = pathname.match(/^\\/hook\\/([^/]+)\\/(.+)$/);\n if (!tokenMatch || tokenMatch[1] !== this.token) {\n this.logger?.warn({ pathname }, 'Hook request unauthorized');\n res.writeHead(401);\n res.end('Unauthorized');\n return;\n }\n\n const pathPart = tokenMatch[2];\n\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n try {\n const payload = body ? JSON.parse(body) : {};\n\n // Determine event type based on URL format\n // Legacy: /hook/{token}/Stop\n // Unified: /hook/{token}/event with body.hook_event_name\n let eventType: string;\n if (pathPart === 'event' && payload.hook_event_name) {\n eventType = String(payload.hook_event_name);\n } else {\n eventType = pathPart;\n }\n\n if (!isClaudeHookEventType(eventType)) {\n this.logger?.info({ eventType }, 'Hook event ignored: unknown event type');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'Unknown event type' }));\n return;\n }\n\n this.processEvent(eventType, payload, res);\n } catch (err) {\n this.logger?.error({ error: err instanceof Error ? err.message : String(err) }, 'Hook request JSON parse error');\n res.writeHead(400);\n res.end('Invalid JSON');\n }\n });\n }\n\n private processEvent(\n eventType: string,\n payload: Record<string, unknown>,\n res: ServerResponse\n ): void {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : undefined;\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : undefined;\n const requestId = typeof payload.request_id === 'string' ? payload.request_id : sessionId;\n this.logger?.info({ eventType, sessionId, toolName, requestId }, 'Processing Claude hook event');\n\n // Convert to AgentEvent format first\n const agentEvent = mapClaudeToAgentEvent(eventType as any, payload, 'claude');\n if (!agentEvent) {\n this.logger?.warn({ eventType, sessionId }, 'Event mapping returned null');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'Event not mapped' }));\n return;\n }\n\n // Emit AgentEvent (new consumers)\n if (this.onAgentEvent) {\n this.logger?.debug({ eventType, agentEventType: agentEvent.type, sessionId }, 'Emitting AgentEvent');\n this.onAgentEvent(agentEvent);\n }\n\n // Convert to legacy format for backward compatibility\n const envelope = mapAgentEventToAgentEventEnvelope(agentEvent, 'claude');\n if (!envelope) {\n this.logger?.warn({ eventType, agentEventType: agentEvent.type, sessionId }, 'AgentEvent to legacy envelope conversion failed');\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'AgentEvent to legacy conversion failed' }));\n return;\n }\n\n // Check if this is a permission request\n const isPermissionHook =\n eventType === 'PreToolUse' || eventType === 'PermissionRequest';\n\n if (isPermissionHook && this.onPermissionRequest) {\n const permissionRequestId =\n envelope.metadata.permissionRequestId || envelope.sessionId;\n\n this.logger?.info({ eventType, sessionId, requestId: permissionRequestId, toolName }, 'Permission request queued for response');\n\n // Permission request - wait for response\n const timeout = setTimeout(() => {\n if (this.pendingRequests.has(permissionRequestId)) {\n this.logger?.warn({ requestId: permissionRequestId }, 'Permission request timeout');\n this.pendingRequests.delete(permissionRequestId);\n res.writeHead(200);\n res.end(\n JSON.stringify({\n hookSpecificOutput: {\n decision: { behavior: 'deny', message: 'Timeout' },\n },\n })\n );\n }\n }, 60000);\n\n this.pendingRequests.set(permissionRequestId, { response: res, timeout });\n\n try {\n this.onPermissionRequest(envelope, (decision) => {\n this.logger?.info({ requestId: permissionRequestId, decision: decision.decision }, 'Permission resolved');\n this.resolvePermission(permissionRequestId, decision);\n });\n } catch (error) {\n this.logger?.error({ requestId: permissionRequestId, error: error instanceof Error ? error.message : String(error) }, 'Error in permission request callback');\n clearTimeout(timeout);\n this.pendingRequests.delete(permissionRequestId);\n res.writeHead(500);\n res.end(JSON.stringify({ error: 'Internal error' }));\n }\n } else {\n // Non-permission event - don't block\n this.logger?.info({ eventType, sessionId, envelopeType: envelope.type }, 'Non-permission event handled');\n if (this.onEvent) {\n this.logger?.debug({ eventType, sessionId, envelopeType: envelope.type }, 'Emitting legacy envelope');\n this.onEvent(envelope);\n }\n res.writeHead(202);\n res.end(\n JSON.stringify({\n accepted: true,\n event_type: agentEvent.type,\n agent_event_id: agentEvent.id,\n })\n );\n }\n }\n\n /**\n * Get the hook URL for this server\n * Returns unified format by default\n */\n getHookUrl(port: number): string {\n return `http://localhost:${port}/hook/${this.token}/event`;\n }\n\n /**\n * Get legacy hook URL pattern\n */\n getLegacyHookUrl(port: number, eventType: string): string {\n return `http://localhost:${port}/hook/${this.token}/${eventType}`;\n }\n}\n","/**\n * Agent Event Protocol v1.0.0\n * Standardized event format for Agent ↔ App communication\n */\n\nexport type AgentEventDirection = 'agent' | 'user' | 'system';\n\n// Note: 'input' and 'confirm' are reserved for future use\nexport type InteractionType = 'permission' | 'question';\n\nexport interface AgentEventButton {\n text: string;\n action: string;\n value?: unknown;\n metadata?: Record<string, unknown>;\n}\n\nexport interface InteractionContext {\n type: InteractionType;\n requestId: string;\n toolName: string;\n permission?: {\n riskLevel: string;\n args: Record<string, unknown>;\n };\n question?: {\n question: string;\n header?: string;\n options: Array<{\n label: string;\n value: unknown;\n description?: string;\n }>;\n multiSelect: boolean;\n };\n}\n\n// Response action: 'allow'/'deny' for permission, 'select' for question, 'input' for text input\nexport interface InteractionResponse {\n requestId: string;\n action: 'allow' | 'deny' | 'select' | 'input';\n data?: unknown;\n}\n\nexport interface AgentEventPayload {\n title?: string;\n description?: string;\n text?: string;\n buttons?: AgentEventButton[];\n data: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n interaction?: InteractionContext;\n}\n\nexport interface AgentEvent {\n id: string;\n ts: number;\n version: string;\n type: string;\n direction: AgentEventDirection;\n session_id: string;\n agent: string;\n device_id: string;\n ack_id?: string;\n app?: string;\n payload: AgentEventPayload;\n}\n\n// Event type constants\nexport const AGENT_EVENTS = [\n 'agent:session:start',\n 'agent:session:end',\n 'agent:permission:request',\n 'agent:question:request',\n 'agent:tool:start',\n 'agent:tool:end',\n 'agent:turn:finished',\n 'agent:message:text',\n 'agent:message:file',\n] as const;\n\nexport const USER_EVENTS = [\n 'user:message:text',\n 'user:permission:decision',\n 'user:command:exec',\n 'user:command:session',\n 'user:command:pause',\n 'user:command:resume',\n 'user:command:stop',\n 'user:command:status',\n 'user:interaction:response',\n] as const;\n\nexport const SYSTEM_EVENTS = [\n 'system:ack',\n 'system:error',\n 'system:heartbeat',\n] as const;\n\nexport type AgentEventType = typeof AGENT_EVENTS[number];\nexport type UserEventType = typeof USER_EVENTS[number];\nexport type SystemEventType = typeof SYSTEM_EVENTS[number];\nexport type AllEventType = AgentEventType | UserEventType | SystemEventType;\n\n// Factory functions\nexport function createAgentEvent(\n type: AllEventType,\n direction: AgentEventDirection,\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Omit<AgentEventPayload, 'data'> & { data: Record<string, unknown> }\n): AgentEvent {\n return {\n id: generateEventId(sessionId),\n ts: Date.now(),\n version: '1.0.0',\n type,\n direction,\n session_id: sessionId,\n agent,\n device_id: deviceId,\n payload: {\n title: payload.title,\n description: payload.description,\n text: payload.text,\n buttons: payload.buttons,\n data: payload.data,\n extensions: payload.extensions,\n interaction: payload.interaction,\n },\n };\n}\n\nfunction generateEventId(sessionId: string): string {\n return `${sessionId}:${Date.now()}`;\n}\n","/**\n * Claude Event Mapper\n *\n * Maps Claude Code hook events to standardized formats:\n * 1. Claude Event → AgentEvent\n * 2. AgentEvent → AgentEventEnvelope (backward compatible)\n *\n * This is the single source of truth for all Claude event transformations.\n */\n\nimport type { AgentEvent, InteractionContext, AgentEventButton } from '../../../../core/event/types.js';\nimport { createAgentEvent, AGENT_EVENTS, USER_EVENTS, SYSTEM_EVENTS } from '../../../../core/event/types.js';\nimport type { AgentEventEnvelope, AgentEventType } from '../../../../core/adapter/types.js';\nimport { hostname } from 'os';\n\nconst DEVICE_ID = hostname();\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\n/**\n * Calculate risk level for permission requests\n */\nexport function calculateRiskLevel(\n toolName: string,\n args: Record<string, unknown>\n): 'low' | 'medium' | 'high' {\n const highRiskTools = ['Bash', 'Write', 'Edit'];\n\n if (highRiskTools.includes(toolName)) {\n const command = String(args.command || args.file_path || '');\n // High risk commands that can cause data loss or system damage\n if (command.match(/\\brm\\b/) || command.includes('sudo') || command.includes('>')) {\n return 'high';\n }\n return 'medium';\n }\n\n return 'low';\n}\n\n/**\n * Question option from AskUserQuestion tool input\n */\ninterface QuestionOption {\n label: string;\n value?: unknown;\n description?: string;\n}\n\n/**\n * Question data from AskUserQuestion tool input\n */\ninterface QuestionData {\n question: string;\n header?: string;\n options: QuestionOption[];\n multiSelect?: boolean;\n}\n\n/**\n * Build interaction context for AskUserQuestion\n */\nfunction buildQuestionInteraction(\n requestId: string,\n toolName: string,\n questions: QuestionData[]\n): InteractionContext {\n const question = questions[0]; // Use first question for now\n return {\n type: 'question',\n requestId,\n toolName,\n question: {\n question: question.question,\n header: question.header,\n options: question.options.map(opt => ({\n label: opt.label,\n value: opt.value ?? opt.label,\n description: opt.description,\n })),\n multiSelect: question.multiSelect ?? false,\n },\n };\n}\n\n/**\n * Build interaction context for permission request\n */\nfunction buildPermissionInteraction(\n requestId: string,\n toolName: string,\n args: Record<string, unknown>,\n riskLevel: 'low' | 'medium' | 'high'\n): InteractionContext {\n return {\n type: 'permission',\n requestId,\n toolName,\n permission: {\n riskLevel,\n args,\n },\n };\n}\n\n/**\n * Build buttons for question interaction\n */\nfunction buildQuestionButtons(options: QuestionOption[]): AgentEventButton[] {\n return options.map((option, index) => ({\n text: option.label,\n action: 'select',\n value: option.value ?? option.label,\n metadata: {\n index,\n description: option.description,\n },\n }));\n}\n\n/**\n * Build buttons for permission interaction\n */\nfunction buildPermissionButtons(): AgentEventButton[] {\n return [\n { text: 'Allow', action: 'allow' },\n { text: 'Deny', action: 'deny' },\n { text: 'Always Allow', action: 'always_allow' },\n ];\n}\n\n/**\n * Map Claude hook event to AgentEvent\n */\nexport function mapClaudeToAgentEvent(\n eventType: ClaudeHookEventType,\n payload: Record<string, unknown>,\n agent: string = 'claude'\n): AgentEvent | null {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : 'unknown';\n\n switch (eventType) {\n case 'SessionStart':\n return createAgentEvent(\n 'agent:session:start',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Session Started',\n description: `Working directory: ${payload.cwd || 'unknown'}`,\n data: {\n session_id: sessionId,\n work_dir: payload.cwd || '',\n permission_mode: payload.permission_mode || 'auto',\n },\n }\n );\n\n case 'SessionEnd':\n return createAgentEvent(\n 'agent:session:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Session Ended',\n description: typeof payload.reason === 'string' ? payload.reason : 'Session completed',\n data: {\n session_id: sessionId,\n reason: payload.reason || 'completed',\n duration: typeof payload.duration === 'number' ? payload.duration : undefined,\n },\n }\n );\n\n case 'PreToolUse':\n case 'PermissionRequest': {\n const toolName = String(payload.tool_name || '');\n const toolInput = (payload.tool_input as Record<string, unknown>) || {};\n const requestId = String(payload.request_id || sessionId);\n\n // Check if this is an AskUserQuestion tool\n if (toolName === 'AskUserQuestion') {\n const questions = (toolInput.questions as QuestionData[]) || [];\n const question = questions[0];\n\n return createAgentEvent(\n 'agent:question:request',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: question?.header || 'Question',\n description: question?.question || 'Please answer the question',\n text: question?.question,\n buttons: question?.options ? buildQuestionButtons(question.options) : [],\n data: {\n request_id: requestId,\n tool_name: toolName,\n args: toolInput,\n cwd: payload.cwd || '',\n },\n interaction: buildQuestionInteraction(requestId, toolName, questions),\n }\n );\n }\n\n // Regular tool permission request\n const riskLevel = calculateRiskLevel(toolName, toolInput);\n\n return createAgentEvent(\n 'agent:permission:request',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `Permission Required: ${toolName || 'Tool'}`,\n description: `${toolName} ${JSON.stringify(toolInput)}`,\n text: `Claude wants to execute ${toolName || 'a tool'}`,\n buttons: buildPermissionButtons(),\n data: {\n request_id: requestId,\n tool_name: toolName,\n args: toolInput,\n cwd: payload.cwd || '',\n risk_level: riskLevel,\n },\n interaction: buildPermissionInteraction(requestId, toolName, toolInput, riskLevel),\n }\n );\n }\n\n case 'PostToolUse':\n return createAgentEvent(\n 'agent:tool:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `${payload.tool_name || 'Tool'} Completed`,\n data: {\n tool_name: payload.tool_name || '',\n args: payload.tool_input || {},\n output: payload.output,\n },\n }\n );\n\n case 'PostToolUseFailure':\n return createAgentEvent(\n 'agent:tool:end',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `${payload.tool_name || 'Tool'} Failed`,\n description: typeof payload.error === 'string' ? payload.error : 'Tool execution failed',\n data: {\n tool_name: payload.tool_name || '',\n args: payload.tool_input || {},\n error: payload.error,\n },\n }\n );\n\n case 'Stop':\n return createAgentEvent(\n 'agent:turn:finished',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: 'Turn Completed',\n description: typeof payload.reason === 'string' ? payload.reason : 'Session stopped',\n data: {\n session_id: sessionId,\n reason: payload.reason || 'stopped',\n status: 'completed',\n last_assistant_message: payload.last_assistant_message,\n transcript_path: payload.transcript_path,\n },\n }\n );\n\n default:\n return null;\n }\n}\n\n/**\n * Map AgentEvent to AgentEventEnvelope (backward compatible)\n */\nexport function mapAgentEventToAgentEventEnvelope(\n agentEvent: AgentEvent,\n agent: string = 'claude'\n): AgentEventEnvelope | null {\n const timestamp = new Date(agentEvent.ts).toISOString();\n const baseMetadata = {\n agentType: agent as 'claude' | 'codex',\n transportType: 'hook' as const,\n sessionId: agentEvent.session_id,\n timestamp,\n rawEventType: agentEventTypeToRawEventType(agentEvent.type),\n };\n\n switch (agentEvent.type) {\n case 'agent:session:start':\n return {\n type: 'session:start',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: { sessionId: agentEvent.session_id },\n metadata: baseMetadata,\n };\n\n case 'agent:session:end':\n return {\n type: 'session:end',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n reason: agentEvent.payload.data.reason as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'agent:permission:request':\n return {\n type: 'permission:request',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n requestId: agentEvent.payload.data.request_id as string,\n },\n metadata: {\n ...baseMetadata,\n permissionRequestId: agentEvent.payload.data.request_id as string,\n },\n };\n\n case 'agent:question:request':\n return {\n type: 'question:request',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n requestId: agentEvent.payload.data.request_id as string,\n },\n metadata: {\n ...baseMetadata,\n questionRequestId: agentEvent.payload.data.request_id as string,\n },\n };\n\n case 'agent:tool:end':\n return {\n type: agentEvent.payload.data.error ? 'tool:failure' : 'tool:end',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n toolName: agentEvent.payload.data.tool_name as string,\n toolInput: agentEvent.payload.data.args as Record<string, unknown>,\n output: agentEvent.payload.data.output as string | undefined,\n error: agentEvent.payload.data.error as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'agent:turn:finished':\n return {\n type: 'finished',\n sessionId: agentEvent.session_id,\n timestamp,\n payload: {\n sessionId: agentEvent.session_id,\n reason: agentEvent.payload.data.reason as string | undefined,\n lastAssistantMessage: agentEvent.payload.data.last_assistant_message as string | undefined,\n transcriptPath: agentEvent.payload.data.transcript_path as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n default:\n return null;\n }\n}\n\n/**\n * Direct mapping from Claude event to AgentEventEnvelope (shortcut)\n * This preserves the legacy type mapping for backward compatibility\n */\nexport function mapClaudeToAgentEventEnvelope(\n eventType: ClaudeHookEventType,\n payload: Record<string, unknown>,\n agent: string = 'claude'\n): AgentEventEnvelope | null {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : '';\n const timestamp = new Date().toISOString();\n\n const baseMetadata = {\n agentType: agent as 'claude' | 'codex',\n transportType: 'hook' as const,\n sessionId,\n timestamp,\n rawEventType: eventType,\n permission_mode: typeof payload.permission_mode === 'string' ? payload.permission_mode : 'auto',\n cwd: typeof payload.cwd === 'string' ? payload.cwd : '',\n };\n\n switch (eventType) {\n case 'SessionStart':\n return {\n type: 'session:start',\n sessionId,\n timestamp,\n payload: { sessionId },\n metadata: baseMetadata,\n };\n\n case 'SessionEnd':\n return {\n type: 'session:end',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n reason: typeof payload.reason === 'string' ? payload.reason : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'PreToolUse':\n case 'PermissionRequest': {\n const toolName = typeof payload.tool_name === 'string' ? payload.tool_name : '';\n const isAskUserQuestion = toolName === 'AskUserQuestion';\n\n return {\n type: isAskUserQuestion ? 'question:request' : 'permission:request',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName,\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n requestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n metadata: {\n ...baseMetadata,\n [isAskUserQuestion ? 'questionRequestId' : 'permissionRequestId']:\n typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n };\n }\n\n case 'PostToolUse':\n return {\n type: 'tool:post',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName: typeof payload.tool_name === 'string' ? payload.tool_name : '',\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n output: typeof payload.output === 'string' ? payload.output : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'PostToolUseFailure':\n return {\n type: 'tool:failure',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n toolName: typeof payload.tool_name === 'string' ? payload.tool_name : '',\n toolInput: (payload.tool_input as Record<string, unknown>) || {},\n error: typeof payload.error === 'string' ? payload.error : undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'Stop':\n return {\n type: 'finished',\n sessionId,\n timestamp,\n payload: {\n sessionId,\n reason: typeof payload.reason === 'string' ? payload.reason : undefined,\n lastAssistantMessage: typeof payload.last_assistant_message === 'string' ? payload.last_assistant_message : undefined,\n transcriptPath: typeof payload.transcript_path === 'string' ? payload.transcript_path : undefined,\n },\n metadata: baseMetadata,\n };\n\n default:\n return null;\n }\n}\n\n/**\n * Convert AgentEvent type to raw Claude event type\n */\nfunction agentEventTypeToRawEventType(agentEventType: string): string {\n const mapping: Record<string, string> = {\n 'agent:session:start': 'SessionStart',\n 'agent:session:end': 'SessionEnd',\n 'agent:permission:request': 'PermissionRequest',\n 'agent:question:request': 'PermissionRequest',\n 'agent:tool:end': 'PostToolUse',\n 'agent:turn:finished': 'Stop',\n };\n return mapping[agentEventType] || agentEventType;\n}\n\n/**\n * Create a user permission decision event\n */\nexport function createPermissionDecisionEvent(\n originalRequestId: string,\n sessionId: string,\n decision: 'allow' | 'deny' | 'always_allow',\n agent: string = 'claude'\n): AgentEvent {\n return createAgentEvent(\n 'user:permission:decision',\n 'user',\n sessionId,\n agent,\n 'user-device',\n {\n title: 'Permission Decision',\n data: {\n request_id: originalRequestId,\n decision,\n },\n }\n );\n}\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}","// src/core/adapter/protocol/claude/ClaudeProtocolHandler.ts\n\nimport { randomUUID } from 'crypto';\nimport type { ProtocolHandler } from '../ProtocolHandler.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../../core/interaction/types.js';\nimport type { AgentEvent } from '../../../../core/event/types.js';\nimport { mapClaudeToAgentEvent, type ClaudeHookEventType } from './ClaudeEventMapper.js';\nimport {\n createPendingMap,\n addPending,\n resolvePending,\n abortAll,\n} from '../permissionUtils.js';\n\nexport class ClaudeProtocolHandler implements ProtocolHandler {\n readonly agentType = 'claude' as const;\n\n private pendingRequests = createPendingMap();\n\n fromAgent(event: unknown): InteractionRequest | null {\n // HTTP hook event format: { eventType: string, payload: Record<string, unknown> }\n const hookEvent = event as { eventType?: string; payload?: Record<string, unknown> };\n if (!hookEvent.eventType || !hookEvent.payload) {\n return null;\n }\n\n // Use ClaudeEventMapper to convert event\n const agentEvent = mapClaudeToAgentEvent(\n hookEvent.eventType as ClaudeHookEventType,\n hookEvent.payload,\n 'claude'\n );\n if (!agentEvent) return null;\n\n // Check if interaction type\n if (agentEvent.type !== 'agent:permission:request' && agentEvent.type !== 'agent:question:request') {\n return null;\n }\n\n // Create InteractionRequest\n const requestId = randomUUID();\n const data = agentEvent.payload.data as {\n tool_name?: string;\n args?: Record<string, unknown>;\n request_id?: string;\n };\n\n const request: InteractionRequest = {\n requestId,\n sessionId: agentEvent.session_id,\n type: agentEvent.type === 'agent:question:request' ? 'question' : 'permission',\n toolName: data.tool_name || '',\n toolInput: data.args || {},\n timestamp: Date.now(),\n };\n\n // Add to pending\n addPending(this.pendingRequests, requestId, {\n resolve: () => {},\n reject: () => {},\n toolName: request.toolName,\n toolInput: request.toolInput,\n timestamp: request.timestamp,\n });\n\n return request;\n }\n\n toAgent(response: InteractionResponse): unknown {\n // Build Hook response format (Claude Code HTTP Hook format)\n const result: {\n action: 'allow' | 'deny' | 'skip';\n updatedPermissions?: unknown;\n } = {\n action: response.action === 'allow' ? 'allow' : response.action === 'deny' ? 'deny' : 'skip',\n };\n\n if (response.permissionUpdates && response.permissionUpdates.length > 0) {\n result.updatedPermissions = response.permissionUpdates;\n }\n\n return result;\n }\n\n abort(): void {\n abortAll(this.pendingRequests);\n }\n\n /**\n * Resolve permission response (called by AgentAdapter)\n */\n resolvePending(requestId: string, response: InteractionResponse): boolean {\n return resolvePending(this.pendingRequests, requestId, response);\n }\n}\n","// src/core/adapter/protocol/permissionUtils.ts\n\nimport type { InteractionResponse } from '../../interaction/types.js';\n\nexport interface PendingRequest {\n resolve: (response: InteractionResponse) => void;\n reject: (error: Error) => void;\n toolName: string;\n toolInput: Record<string, unknown>;\n timestamp: number;\n}\n\n/**\n * Create a new PendingRequest Map\n */\nexport function createPendingMap(): Map<string, PendingRequest> {\n return new Map();\n}\n\n/**\n * Add a pending request\n */\nexport function addPending(\n map: Map<string, PendingRequest>,\n requestId: string,\n pending: PendingRequest\n): void {\n map.set(requestId, pending);\n}\n\n/**\n * Resolve a pending request\n */\nexport function resolvePending(\n map: Map<string, PendingRequest>,\n requestId: string,\n response: InteractionResponse\n): boolean {\n const pending = map.get(requestId);\n if (!pending) return false;\n map.delete(requestId);\n try {\n pending.resolve(response);\n } catch {\n // Ignore errors after deletion\n }\n return true;\n}\n\n/**\n * Reject a pending request\n */\nexport function rejectPending(\n map: Map<string, PendingRequest>,\n requestId: string,\n error: Error\n): boolean {\n const pending = map.get(requestId);\n if (!pending) return false;\n map.delete(requestId);\n try {\n pending.reject(error);\n } catch {\n // Ignore errors after deletion\n }\n return true;\n}\n\n/**\n * Abort all pending requests\n */\nexport function abortAll(map: Map<string, PendingRequest>): void {\n const error = new Error('Aborted');\n const entries = Array.from(map.entries());\n map.clear();\n for (const [, pending] of entries) {\n pending.reject(error);\n }\n}\n\n/**\n * Get timed out request IDs\n */\nexport function getTimedOutRequests(\n map: Map<string, PendingRequest>,\n timeoutMs: number\n): string[] {\n const now = Date.now();\n const timedOut: string[] = [];\n for (const [id, pending] of map) {\n if (now - pending.timestamp > timeoutMs) {\n timedOut.push(id);\n }\n }\n return timedOut;\n}\n","import { readFile } from 'fs/promises';\nimport type { SessionContextProvider, SessionSummary } from '../../../core/session-context';\nimport { getLogger } from '../../../shared/logger.js';\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 }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport class ClaudeSessionContextProvider implements SessionContextProvider {\n async getSessionSummary(_sessionId: string, transcriptPath?: string): Promise<SessionSummary | undefined> {\n if (!transcriptPath) {\n return undefined;\n }\n\n const summary = await this.tryReadTranscript(transcriptPath);\n return summary;\n }\n\n private async tryReadTranscript(transcriptPath: string, maxAttempts = 5, delayMs = 200): Promise<SessionSummary | undefined> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const content = await readFile(transcriptPath, 'utf-8');\n const summary = this.parseTranscript(content);\n // Retry if summary has no data at all (no assistant message and no duration)\n // This handles the timing issue where transcript isn't fully written when Stop hook fires\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 // Log partial summary for debugging\n if (summary) {\n getLogger().debug({ attempt, summary }, 'Transcript read but incomplete, retrying...');\n }\n } catch (error) {\n lastError = error;\n }\n if (attempt < maxAttempts) {\n await sleep(delayMs);\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 private 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 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 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 const usage = entry.message?.usage;\n if (usage) {\n if (typeof usage.input_tokens === 'number') {\n inputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n outputTokens = usage.output_tokens;\n }\n }\n }\n }\n }\n\n function resolveDuration(assistantRef: { ts: number; uuid?: string; parentUuid?: string } | undefined): 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 const durationMs = resolveDuration(lastTextAssistant) ?? resolveDuration(lastAnyAssistant);\n\n const summary: SessionSummary = {\n ...(lastAssistantMessage !== undefined && { lastAssistantMessage }),\n ...(inputTokens !== undefined && { inputTokens }),\n ...(outputTokens !== undefined && { outputTokens }),\n ...(durationMs !== undefined && { durationMs }),\n };\n\n return summary;\n }\n}\n","import { randomUUID } from 'crypto';\nimport type { Logger } from 'pino';\nimport type {\n AgentAdapter,\n AgentEventEnvelope,\n AgentCommand,\n CreateSessionOptions,\n SessionHandle,\n SessionInfo,\n} from '../../../core/adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { Gateway } from '../../../gateway/index.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\nimport { ClaudeProtocolHandler } from '../../../core/adapter/protocol/claude/ClaudeProtocolHandler.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 } from './sdk/types.js';\n\ninterface RemoteSessionState {\n handle: SessionHandle;\n query: ReturnType<typeof query>;\n input: PushableAsyncIterable<SDKUserMessage>;\n chatId: string;\n channel: string;\n cwd: string;\n turnInProgress: boolean;\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 ClaudeRemoteAdapter implements AgentAdapter {\n readonly agentType = 'claude' as const;\n readonly transportType = 'remote' as const;\n readonly version = '1.0.0';\n readonly protocolHandler: ProtocolHandler = new ClaudeProtocolHandler();\n private static scanner: ClaudeSessionScanner | null = null;\n\n private bus: EventBus;\n private logger: Logger;\n private gateway: Gateway;\n private token: string;\n private sessions = new Map<string, RemoteSessionState>();\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private unsubscribeFns: Array<() => void> = [];\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 constructor(options: {\n bus: EventBus;\n logger: Logger;\n gateway: Gateway;\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 this.bus = options.bus;\n this.logger = options.logger;\n this.gateway = options.gateway;\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\n async initialize(): Promise<void> {\n this.logger.info('Claude remote adapter 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 (!ClaudeRemoteAdapter.scanner) {\n ClaudeRemoteAdapter.scanner = new ClaudeSessionScanner();\n SessionScannerRegistry.getInstance().register(ClaudeRemoteAdapter.scanner);\n this.logger.info('Claude session scanner registered');\n }\n\n AgentAdapterRegistry.getInstance().register(this);\n\n if (!this.unsubscribeFns.length) {\n this.unsubscribeFns.push(this.bus.onInbound((msg) => this.handleInboundMessage(msg)));\n this.logger.debug('Subscribed to inbound messages');\n }\n }\n\n async shutdown(): Promise<void> {\n this.logger.info('Claude remote adapter shutting down');\n for (const [sessionId, state] of this.sessions) {\n try {\n state.query.kill('SIGTERM');\n state.input.end();\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Error ending session input during shutdown');\n }\n }\n this.sessions.clear();\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n this.logger.info('Claude remote adapter shutdown complete');\n }\n\n async createSession(opts: CreateSessionOptions): Promise<SessionHandle> {\n const sessionId = opts.sessionId ?? `claude-${randomUUID().slice(0, 8)}`;\n const chatId = (opts.metadata?.chatId as string) ?? sessionId;\n const channel = (opts.metadata?.channel as string) ?? 'broadcast';\n const cwd = opts.cwd ?? this.defaultWorkDir ?? process.cwd();\n this.logger.info({ sessionId, chatId, cwd }, 'Creating Claude remote session');\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 canCallTool: (toolName, toolInput, { signal }) => this.handleCanCallTool(sessionId, toolName, toolInput, signal),\n },\n });\n\n const handle: SessionHandle = {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n createdAt: new Date(),\n sendCommand: async (command) => {\n await this.handleCommand(sessionId, command);\n },\n close: async () => {\n this.logger.info({ sessionId }, 'Closing Claude remote session');\n input.end();\n this.sessions.delete(sessionId);\n },\n };\n\n const state: RemoteSessionState = {\n handle,\n query: q,\n input,\n chatId,\n channel,\n cwd,\n turnInProgress: false,\n };\n\n this.sessions.set(sessionId, state);\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 session started');\n return handle;\n }\n\n async closeSession(handle: SessionHandle): Promise<void> {\n await handle.close();\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return Array.from(this.sessions.values()).map((s) => ({\n id: s.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: s.handle.createdAt,\n }));\n }\n\n async getSession(sessionId: string): Promise<SessionInfo | undefined> {\n const state = this.sessions.get(sessionId);\n if (!state) return undefined;\n return {\n id: state.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: state.handle.createdAt,\n };\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n this.logger.debug('Event handler registered');\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return { healthy: true, message: `${this.sessions.size} active remote sessions` };\n }\n\n private async consumeQueryMessages(q: ReturnType<typeof query>, sessionId: string, state: RemoteSessionState): 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.turnInProgress = false;\n this.sessions.delete(sessionId);\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: { reason: 'stream_ended' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n }\n }\n\n private async handleSdkMessage(msg: SDKMessage, sessionId: string, state: RemoteSessionState): Promise<void> {\n const timestamp = new Date().toISOString();\n\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 this.gateway.handleEvent(this.token, {\n type: 'session:start',\n sessionId,\n timestamp,\n payload: { claudeSessionId: system.session_id },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\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 this.bus.publishAgentMessage({ sessionId, content: block.text });\n }\n if (block.type === 'thinking' && typeof block.thinking === 'string') {\n this.bus.publishAgentMessage({ sessionId, content: block.thinking });\n }\n if (block.type === 'tool_use') {\n const toolName = typeof block.name === 'string' ? block.name : 'unknown';\n this.bus.publishToolStart({ sessionId, toolName, toolInput: 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 this.bus.publishToolEnd({ sessionId, toolName: 'unknown', output: block.text });\n } else if (block.type === 'text' && typeof block.text === 'string') {\n this.bus.publishAgentMessage({ sessionId, content: block.text });\n }\n }\n }\n break;\n }\n\n case 'result': {\n const result = msg as { subtype?: string; result?: string };\n this.logger.info({ sessionId, subtype: result.subtype }, 'Claude turn result');\n this.gateway.handleEvent(this.token, {\n type: 'finished',\n sessionId,\n timestamp,\n payload: { result: result.result, subtype: result.subtype },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\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 handleCommand(sessionId: string, command: AgentCommand): Promise<void> {\n const state = this.sessions.get(sessionId);\n if (!state) {\n this.logger.warn({ sessionId, commandType: command.type }, 'Command received but session not found');\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n switch (command.type) {\n case 'user:message': {\n if (state.turnInProgress) {\n this.logger.warn({ sessionId }, 'Concurrent turn rejected');\n this.bus.publishOutbound({\n channel: state.channel,\n chatId: state.chatId,\n text: 'Claude is still processing the previous message. Please wait.',\n });\n return;\n }\n state.turnInProgress = true;\n state.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 state.query.interrupt();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n state.input.end();\n this.sessions.delete(sessionId);\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: { reason: 'stopped' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n break;\n }\n default: {\n this.logger.warn({ sessionId, commandType: command.type }, 'Unsupported command');\n }\n }\n }\n\n private async handleCanCallTool(sessionId: string, toolName: string, toolInput: unknown, signal: AbortSignal): Promise<PermissionResult> {\n const state = this.sessions.get(sessionId);\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 envelope: AgentEventEnvelope = {\n type: 'permission:request',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: { sessionId, toolName, toolInput: toolInput ?? {} },\n metadata: {\n agentType: this.agentType,\n transportType: this.transportType,\n permissionRequestId: requestId,\n },\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 }, 60000);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve({ behavior: 'deny', message: 'Aborted' });\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n this.gateway.handleEvent(this.token, envelope).then((response) => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n const decision = response?.action === 'allow' ? 'allow' : 'deny';\n this.logger.info({ sessionId, requestId, toolName, decision }, 'Claude remote permission resolved');\n resolve({\n behavior: decision,\n updatedInput: (toolInput as Record<string, unknown>) ?? {},\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 handleInboundMessage(message: InboundMessage): Promise<void> {\n const text = message.text.trim();\n this.logger.debug({ channel: message.channel, chatId: message.chatId, targetAgent: message.targetAgent, textPreview: text.slice(0, 80) }, 'Inbound message received');\n\n if (message.systemCommand) return;\n if (message.targetAgent !== 'claude') return;\n\n const rawInput = this.normalizeInboundText(message);\n if (rawInput === null) return;\n\n const sessionId = `claude-${message.chatId}`;\n const existingSession = this.gateway.getSession(sessionId);\n\n if (!rawInput) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n }\n\n const [keyword, ...rest] = rawInput.split(/\\s+/);\n const normalizedKeyword = keyword.toLowerCase();\n const commandOnly = rest.length === 0;\n\n if (normalizedKeyword === 'help' && commandOnly) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: this.getHelpText() });\n return;\n }\n\n if (normalizedKeyword === 'status' && commandOnly) {\n const active = existingSession && existingSession.getStatus() === 'active';\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: active ? `Claude remote session is active.\\nSession ID: ${sessionId}` : 'No active Claude remote session for this chat.',\n });\n return;\n }\n\n if ((normalizedKeyword === 'stop' || normalizedKeyword === 'reset') && commandOnly) {\n if (!existingSession) {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: 'No active session to stop.' });\n return;\n }\n await existingSession.sendCommand({ type: 'stop' });\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: 'Claude session stopped.' });\n return;\n }\n\n let session = existingSession;\n if (!session) {\n try {\n session = await this.gateway.createSession(this.token, sessionId, { chatId: message.chatId, channel: message.channel });\n } catch (err) {\n this.logger.error({ error: err, chatId: message.chatId }, 'Failed to create Claude remote session');\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: 'Failed to start Claude session. Please check that Claude CLI is installed.' });\n return;\n }\n }\n\n if (session.getStatus() !== 'active') {\n this.bus.publishOutbound({ channel: message.channel, chatId: message.chatId, text: 'Session is not active. Please start a new session.' });\n return;\n }\n\n await session.sendCommand({ type: 'user:message', content: rawInput });\n }\n\n private normalizeInboundText(message: InboundMessage): string | null {\n const text = message.text.trim();\n const explicitCommand = text.match(/^\\/claude(?:@[^\\s]+)?(?:\\s+(.*))?$/s);\n if (explicitCommand) {\n return explicitCommand[1]?.trim() ?? '';\n }\n const aliasCommand = message.agentCommand ? text.match(/^\\/(status|help|stop|reset)(?:@[^\\s]+)?$/i) : null;\n if (aliasCommand) {\n return aliasCommand[1].toLowerCase();\n }\n return message.agentCommand ? null : text;\n }\n\n private getHelpText(): string {\n return [\n 'Claude remote commands:',\n '/claude help - show this help message',\n '/claude status - show the current chat session state',\n '/claude stop - stop the active session for this chat',\n '/claude reset - stop and clear the active session',\n '/claude <prompt> - run a task in the current chat',\n 'Any other text is sent to Claude as a prompt.',\n ].join('\\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 ControlCancelRequest,\n PermissionResult,\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.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 ) {\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> {\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 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 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);\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 CanUseToolControlResponse {\n type: 'control_response';\n response: {\n subtype: 'success' | 'error';\n request_id: string;\n response?: PermissionResult;\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\nexport interface CanCallToolCallback {\n (toolName: string, input: unknown, options: { signal: AbortSignal }): Promise<PermissionResult>;\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 settingsPath?: string;\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","import { randomUUID } from 'crypto';\nimport type { AgentAdapter, CreateSessionOptions, SessionHandle, SessionInfo, AgentEventEnvelope, AgentCommand } from '../../../core/adapter/AgentAdapter.js';\nimport type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { Gateway } from '../../../gateway/index.js';\nimport type { Logger } from 'pino';\nimport { CodexProtocolHandler } from './CodexProtocolHandler.js';\nimport { CodexAppServerClient, type ApprovalHandler } from './codexAppServerClient.js';\nimport type { ApprovalPolicy, ReviewDecision } from './codexAppServerTypes.js';\nimport type { InboundMessage } from '../../../core/bus/events.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\n\ninterface CodexSessionState {\n handle: SessionHandle;\n client: CodexAppServerClient;\n threadId: string;\n chatId: string;\n channel: string;\n cwd?: string;\n}\n\nexport class CodexAppServerAdapter implements AgentAdapter {\n readonly agentType = 'codex' as const;\n readonly transportType = 'stdio' as const;\n readonly version = '1.0.0';\n readonly protocolHandler: ProtocolHandler = new CodexProtocolHandler();\n\n private bus: EventBus;\n private logger: Logger;\n private gateway: Gateway;\n private token: string;\n private sessions = new Map<string, CodexSessionState>();\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private unsubscribeFns: Array<() => void> = [];\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 constructor(options: {\n bus: EventBus;\n logger: Logger;\n gateway: Gateway;\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 this.bus = options.bus;\n this.logger = options.logger;\n this.gateway = options.gateway;\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 AgentAdapterRegistry.getInstance().register(this);\n\n if (!this.unsubscribeFns.length) {\n this.unsubscribeFns.push(\n this.bus.onInbound((msg) => this.handleInboundMessage(msg))\n );\n this.logger.debug('Subscribed to inbound messages');\n }\n }\n\n async shutdown(): Promise<void> {\n this.logger.info('Codex adapter shutting down');\n for (const [sessionId, state] of this.sessions) {\n try {\n await state.client.disconnect();\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Error disconnecting Codex client during shutdown');\n }\n }\n this.sessions.clear();\n this.unsubscribeFns.forEach((fn) => fn());\n this.unsubscribeFns = [];\n this.logger.info('Codex adapter shutdown complete');\n }\n\n async createSession(opts: CreateSessionOptions): Promise<SessionHandle> {\n const sessionId = opts.sessionId ?? `codex-${randomUUID().slice(0, 8)}`;\n const chatId = (opts.metadata?.chatId as string) ?? sessionId;\n const channel = (opts.metadata?.channel as string) ?? 'broadcast';\n const cwd = opts.cwd ?? this.defaultWorkDir ?? process.cwd();\n this.logger.info({ sessionId, chatId, cwd }, 'Creating Codex session');\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 handle: SessionHandle = {\n id: sessionId,\n agentType: this.agentType,\n transportType: this.transportType,\n createdAt: new Date(),\n sendCommand: async (command) => {\n await this.handleCommand(sessionId, command);\n },\n close: async () => {\n this.logger.info({ sessionId }, 'Closing Codex session');\n await client.disconnect();\n this.sessions.delete(sessionId);\n },\n };\n\n const state: CodexSessionState = {\n handle,\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.sessions.set(sessionId, state);\n\n this.logger.info({ sessionId, threadId }, 'Codex session started');\n\n return handle;\n }\n\n async closeSession(handle: SessionHandle): Promise<void> {\n await handle.close();\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n return Array.from(this.sessions.values()).map((s) => ({\n id: s.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: s.handle.createdAt,\n }));\n }\n\n async getSession(sessionId: string): Promise<SessionInfo | undefined> {\n const state = this.sessions.get(sessionId);\n if (!state) return undefined;\n return {\n id: state.handle.id,\n agentType: this.agentType,\n transportType: this.transportType,\n status: 'active',\n startedAt: state.handle.createdAt,\n };\n }\n\n setEventHandler(handler: (event: AgentEventEnvelope) => void): void {\n this.eventHandler = handler;\n this.logger.debug('Event handler registered');\n }\n\n async healthCheck(): Promise<{ healthy: boolean; message?: string }> {\n return { healthy: true, message: `${this.sessions.size} active sessions` };\n }\n\n private async handleCommand(sessionId: string, command: AgentCommand): Promise<void> {\n const state = this.sessions.get(sessionId);\n if (!state) {\n this.logger.warn({ sessionId, commandType: command.type }, 'Command received but session not found');\n throw new Error(`Session not found: ${sessionId}`);\n }\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: state.channel,\n chatId: state.chatId,\n text: 'Codex is still processing the previous message. Please wait.',\n });\n return;\n }\n this.turnInProgress.add(sessionId);\n try {\n this.logger.debug({ sessionId, contentLength: command.content.length }, 'Sending turn to Codex');\n await state.client.sendTurnAndWait(command.content, {\n cwd: state.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 state.client.interruptTurn();\n break;\n }\n case 'stop': {\n this.logger.info({ sessionId }, 'Stopping session');\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: { reason: 'stopped' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n await state.client.disconnect();\n this.sessions.delete(sessionId);\n break;\n }\n }\n }\n\n private async handleInboundMessage(message: InboundMessage): Promise<void> {\n const text = message.text.trim();\n this.logger.debug(\n {\n channel: message.channel,\n channelInstanceId: message.channelInstanceId,\n chatId: message.chatId,\n messageId: message.messageId,\n targetAgent: message.targetAgent,\n agentCommand: message.agentCommand,\n textPreview: text.slice(0, 80),\n },\n 'Inbound message received'\n );\n\n // 如果是系统命令已处理标记,跳过\n if (message.systemCommand) {\n this.logger.debug('Ignoring system command message');\n return;\n }\n\n // 入站消息已经由 InboundRouter 打过 targetAgent 标记\n // 只有 targetAgent === 'codex' 的消息才由这个 adapter 处理\n if (!message.targetAgent) {\n this.logger.debug('Ignoring inbound message: no targetAgent, not routed');\n return;\n }\n\n if (message.targetAgent !== 'codex') {\n this.logger.debug({ targetAgent: message.targetAgent }, 'Ignoring inbound message: not targeted for Codex');\n return;\n }\n\n const rawInput = this.normalizeInboundText(message);\n if (rawInput === null) {\n this.logger.debug({ textPreview: text.slice(0, 40) }, 'Message ignored: not routed to Codex');\n return;\n }\n\n const sessionId = `codex-${message.chatId}`;\n const existingSession = this.gateway.getSession(sessionId);\n\n if (!rawInput) {\n this.logger.info({ chatId: message.chatId }, 'Empty /codex prompt, replying with help');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: this.getHelpText(),\n });\n return;\n }\n\n const [keyword, ...rest] = rawInput.split(/\\s+/);\n const normalizedKeyword = keyword.toLowerCase();\n const commandOnly = rest.length === 0;\n\n if (normalizedKeyword === 'help' && commandOnly) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: this.getHelpText(),\n });\n return;\n }\n\n if (normalizedKeyword === 'status' && commandOnly) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: existingSession && existingSession.getStatus() === 'active'\n ? `Codex session is active for this chat.\\nSession ID: ${sessionId}`\n : 'No active Codex session for this chat.',\n });\n return;\n }\n\n if ((normalizedKeyword === 'stop' || normalizedKeyword === 'reset') && commandOnly) {\n if (!existingSession) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'No active Codex session to stop.',\n });\n return;\n }\n\n await existingSession.sendCommand({ type: 'stop' });\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Codex session stopped for this chat.',\n });\n return;\n }\n\n const prompt = rawInput;\n this.logger.info({ chatId: message.chatId, sessionId, promptPreview: prompt.slice(0, 60) }, 'Handling /codex request');\n\n let session = existingSession;\n if (!session) {\n try {\n this.logger.info({ sessionId, chatId: message.chatId }, 'Creating new Codex session for inbound');\n session = await this.gateway.createSession(this.token, sessionId, { chatId: message.chatId, channel: message.channel });\n } catch (err) {\n this.logger.error({ error: err, chatId: message.chatId }, 'Failed to create Codex session');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Failed to start Codex session. Please check that Codex CLI is installed.',\n });\n return;\n }\n }\n\n if (session.getStatus() !== 'active') {\n this.logger.warn({ sessionId, status: session.getStatus() }, 'Codex session not active');\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: 'Session is not active. Please start a new session.',\n });\n return;\n }\n\n this.logger.info({ sessionId, promptPreview: prompt.slice(0, 60) }, 'Sending user:message to Codex session');\n await session.sendCommand({ type: 'user:message', content: prompt });\n }\n\n private async handleCodexEvent(msg: { type: string } & Record<string, unknown>, sessionId: string, _state: CodexSessionState): 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.bus.publishAgentMessage({ sessionId, content });\n break;\n }\n\n case 'exec_command_begin':\n case 'patch_apply_begin': {\n const toolName = msg.type === 'exec_command_begin' ? 'codex_exec_command' : 'codex_patch_apply';\n this.logger.debug({ sessionId, toolName, eventType: msg.type }, 'Publishing tool:start');\n const toolInput = msg.command ? { command: msg.command } : msg.changes ? { changes: msg.changes } : {};\n this.bus.publishToolStart({ sessionId, toolName, toolInput });\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:end');\n this.bus.publishToolEnd({ sessionId, toolName, output: typeof msg.output === 'string' ? msg.output : undefined });\n break;\n }\n\n case 'task_complete': {\n this.logger.info({ sessionId }, 'Task complete, forwarding finished and closing session');\n this.gateway.handleEvent(this.token, {\n type: 'finished',\n sessionId,\n timestamp,\n payload: { reason: 'completed' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n try {\n await this.gateway.getSessionManager().closeSession(sessionId);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Failed to close completed Codex session');\n }\n this.sessions.delete(sessionId);\n break;\n }\n\n case 'turn_aborted': {\n this.logger.info({ sessionId, reason: msg.reason || 'aborted' }, 'Turn aborted, forwarding session:end and closing session');\n this.gateway.handleEvent(this.token, {\n type: 'session:end',\n sessionId,\n timestamp,\n payload: { reason: msg.reason || 'aborted' },\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n try {\n await this.gateway.getSessionManager().closeSession(sessionId);\n } catch (err) {\n this.logger.warn({ sessionId, error: err }, 'Failed to close aborted Codex session');\n }\n this.sessions.delete(sessionId);\n break;\n }\n\n case 'tool:post':\n case 'tool:failure': {\n this.logger.debug({ sessionId, eventType: msg.type }, 'Forwarding tool event to gateway');\n this.gateway.handleEvent(this.token, {\n type: msg.type as 'tool:post' | 'tool:failure',\n sessionId,\n timestamp,\n payload: msg as Record<string, unknown>,\n metadata: { agentType: this.agentType, transportType: this.transportType },\n }).catch(() => {});\n break;\n }\n }\n }\n\n private async handleApproval(params: Parameters<ApprovalHandler>[0], sessionId: string): Promise<ReviewDecision> {\n const state = this.sessions.get(sessionId);\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 envelope: AgentEventEnvelope = {\n type: 'permission:request',\n sessionId,\n timestamp: new Date().toISOString(),\n payload: {\n sessionId,\n toolName,\n toolInput: params.command ? { command: params.command } :\n params.fileChanges ? { fileChanges: params.fileChanges } :\n params.input ? { input: params.input } : {},\n },\n metadata: {\n agentType: this.agentType,\n transportType: this.transportType,\n permissionRequestId: params.callId,\n },\n };\n\n try {\n const response = await this.gateway.handleEvent(this.token, envelope);\n const decision = 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 private getHelpText(): string {\n return [\n 'Codex commands:',\n '/codex help - show this help message',\n '/codex status - show the current chat session state',\n '/codex stop - stop the active session for this chat',\n '/codex reset - stop and clear the active session',\n '/codex <prompt> - run a task in the current chat',\n 'Any other text is sent to Codex as a prompt.',\n ].join('\\n');\n }\n\n private normalizeInboundText(message: InboundMessage): string | null {\n const text = message.text.trim();\n\n const explicitCommand = text.match(/^\\/codex(?:@[^\\s]+)?(?:\\s+(.*))?$/s);\n if (explicitCommand) {\n return explicitCommand[1]?.trim() ?? '';\n }\n\n const aliasCommand = message.agentCommand\n ? text.match(/^\\/(status|help|stop|reset)(?:@[^\\s]+)?$/i)\n : null;\n if (aliasCommand) {\n return aliasCommand[1].toLowerCase();\n }\n\n return message.agentCommand ? null : text;\n }\n}\n","import type { ProtocolHandler } from '../../../core/adapter/protocol/ProtocolHandler.js';\nimport type { InteractionRequest, InteractionResponse } from '../../../core/interaction/types.js';\nimport {\n createPendingMap,\n addPending,\n resolvePending,\n abortAll,\n} from '../../../core/adapter/protocol/permissionUtils.js';\n\nexport class CodexProtocolHandler implements ProtocolHandler {\n readonly agentType = 'codex' as const;\n\n private pendingRequests = createPendingMap();\n\n fromAgent(event: unknown): InteractionRequest | null {\n return null;\n }\n\n toAgent(response: InteractionResponse): unknown {\n return {\n action: response.action === 'allow' ? 'allow' : response.action === 'deny' ? 'deny' : 'skip',\n };\n }\n\n abort(): void {\n abortAll(this.pendingRequests);\n }\n\n resolvePending(requestId: string, response: InteractionResponse): boolean {\n return resolvePending(this.pendingRequests, requestId, response);\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 { AgentEventEnvelope } from '../core/adapter/types.js';\n\n/** Minimal adapter interface for hook event translation */\ninterface HookEventAdapter {\n translate(rawEventType: string, payload: unknown): AgentEventEnvelope | null;\n}\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 * Setup HTTP routes for the Gateway\n */\nexport function setupRoutes(\n httpServer: HttpServer,\n gateway: Gateway,\n adapter: HookEventAdapter,\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 'Notification',\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 sessionCounts.set(session.token, (sessionCounts.get(session.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 // 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 const registeredAgents = gateway.listRegisteredAgents();\n logger.debug({ registeredTokenCount: registeredAgents.length, tokens: registeredAgents.map(a => a.token.substring(0, 8)) }, 'Registered agents');\n const isRegistered = registeredAgents.some((a) => a.token === token);\n if (!isRegistered) {\n logger.warn(`Auto-registering unknown token from hook request: ${token.substring(0, 8)}...`);\n gateway.registerAgent('claude', token);\n }\n\n logger.info({ eventType, token: token.substring(0, 8), body }, 'Hook payload received');\n\n // TODO: Refactor to use AgentAdapter interface - this translate() call is legacy technical debt\n const translate = (adapter as any).translate;\n const envelope = typeof translate === 'function' ? translate.call(adapter, eventType, body) : null;\n if (!envelope) {\n sendJson(res, 202, { accepted: true });\n return;\n }\n\n const isPermissionHook = eventType === 'PreToolUse' || eventType === 'PermissionRequest';\n\n let result: Awaited<ReturnType<typeof gateway.handleEvent>>;\n if (isPermissionHook) {\n // Permission hooks wait for user decision; timeout is managed by InteractionQueue\n result = await gateway.handleEvent(token, envelope);\n } else {\n const HOOK_TIMEOUT_MS = 5000;\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Hook processing timeout')), HOOK_TIMEOUT_MS);\n });\n result = await Promise.race([\n gateway.handleEvent(token, envelope),\n timeoutPromise,\n ]);\n }\n\n if (result && typeof result.action === 'string') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n\n // Check if this is an AskUserQuestion (question:request type)\n const isAskUserQuestion = envelope.type === 'question:request';\n\n let responseBody: string;\n\n if (isAskUserQuestion && result._toolInput) {\n // AskUserQuestion uses PermissionRequest format with updatedInput\n // The answer needs to be formatted as: answers: { [questionText]: answerValue }\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 // Get the answer value (selectedValues from options or customInput)\n // Multi-select answers are comma-separated per AskUserQuestion schema\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 // Build updatedInput with answers\n const updatedInput: Record<string, unknown> = {\n ...result._toolInput,\n answers: question?.question\n ? { [question.question]: answerValue }\n : {},\n };\n\n responseBody = JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: 'allow',\n updatedInput,\n },\n },\n });\n logger.info({ eventType, isAskUserQuestion, response: responseBody }, 'Sending AskUserQuestion response');\n } else if (eventType === 'PermissionRequest') {\n // PermissionRequest uses PermissionRequest format\n // Build updatedPermissions for \"always allow\" if provided\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 responseBody = 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 && { data: result.selectedValues.map(String).join(', ') }),\n ...(updatedPermissions !== undefined && { updatedPermissions }),\n },\n },\n });\n logger.info({ eventType, response: responseBody }, 'Sending permission response');\n } else {\n // For PreToolUse and other hooks\n responseBody = JSON.stringify({\n accepted: ['allow', 'select', 'confirm'].includes(result.action),\n message: result.message,\n ...(result.selectedValues !== undefined && { data: result.selectedValues.map(String).join(', ') }),\n });\n logger.info({ eventType, response: responseBody }, 'Sending hook response');\n }\n\n res.end(responseBody);\n } else {\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';\nimport { ACKManager } from '../core/event/ack.js';\nimport type { AgentEvent } from '../core/event/types.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 private ackManager = new ACKManager();\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 /**\n * Send AgentEvent with optional ACK waiting\n */\n async sendAgentEvent(\n clientId: string,\n event: AgentEvent,\n waitForACK: boolean = false,\n timeoutMs?: number\n ): Promise<{ success: boolean; ack?: unknown; error?: string }> {\n const sent = this.send(clientId, {\n type: 'hep',\n event,\n });\n\n if (!sent) {\n return { success: false, error: 'Client not connected' };\n }\n\n if (waitForACK && event.ack_id) {\n try {\n const ack = await this.ackManager.waitForACK(event.ack_id, timeoutMs);\n return { success: true, ack };\n } catch (error) {\n return { success: false, error: String(error) };\n }\n }\n\n return { success: true };\n }\n\n /**\n * Handle incoming AgentEvent ACK message\n */\n handleAgentEventACK(message: { original_id: string; status: string; result?: unknown }): void {\n this.ackManager.handleACK({\n original_id: message.original_id,\n status: message.status as 'received' | 'processing' | 'completed' | 'failed',\n result: message.result,\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 hep:ack messages\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'hep:ack') {\n wsServer.handleAgentEventACK({\n original_id: message.original_id as string,\n status: message.status as string,\n result: message.result,\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', 'hep:ack'];\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 type { AgentEvent } from './types.js';\nimport { createAgentEvent } from './types.js';\n\nexport type ACKStatus = 'received' | 'processing' | 'completed' | 'failed';\n\nexport interface ACKEvent {\n original_id: string;\n status: ACKStatus;\n result?: unknown;\n error?: string;\n}\n\nexport class ACKManager {\n private pendingACKs = new Map<string, {\n resolve: (value: ACKEvent) => void;\n reject: (reason: Error) => void;\n timeout: NodeJS.Timeout;\n }>();\n\n private defaultTimeoutMs: number;\n\n constructor(timeoutMs: number = 30000) {\n this.defaultTimeoutMs = timeoutMs;\n }\n\n /**\n * Wait for ACK of specific event\n */\n waitForACK(eventId: string, timeoutMs?: number): Promise<ACKEvent> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pendingACKs.delete(eventId);\n reject(new Error(`ACK timeout for event ${eventId}`));\n }, timeoutMs ?? this.defaultTimeoutMs);\n\n this.pendingACKs.set(eventId, { resolve, reject, timeout });\n });\n }\n\n /**\n * Handle incoming ACK event\n */\n handleACK(ack: ACKEvent): boolean {\n const pending = this.pendingACKs.get(ack.original_id);\n if (!pending) {\n return false;\n }\n\n clearTimeout(pending.timeout);\n this.pendingACKs.delete(ack.original_id);\n\n if (ack.status === 'failed') {\n pending.reject(new Error(ack.error || 'ACK failed'));\n } else {\n pending.resolve(ack);\n }\n\n return true;\n }\n\n /**\n * Create system:ack event\n */\n createACKEvent(\n originalEvent: AgentEvent,\n status: ACKStatus,\n result?: unknown,\n error?: string\n ): AgentEvent {\n const ackData: ACKEvent = {\n original_id: originalEvent.id,\n status,\n };\n\n if (result !== undefined) {\n ackData.result = result;\n }\n if (error !== undefined) {\n ackData.error = error;\n }\n\n return createAgentEvent(\n 'system:ack',\n 'system',\n originalEvent.session_id,\n 'system',\n 'gateway',\n {\n title: 'ACK',\n data: ackData as Record<string, unknown>,\n }\n );\n }\n\n /**\n * Cancel pending ACK\n */\n cancelACK(eventId: string): void {\n const pending = this.pendingACKs.get(eventId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingACKs.delete(eventId);\n pending.reject(new Error('ACK cancelled'));\n }\n }\n\n /**\n * Dispose of all pending ACKs (for shutdown)\n */\n dispose(): void {\n for (const [eventId, pending] of this.pendingACKs) {\n clearTimeout(pending.timeout);\n pending.reject(new Error('ACK manager disposed'));\n }\n this.pendingACKs.clear();\n }\n}\n\nexport const defaultACKManager = new ACKManager();\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","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 AgentMessageEvent,\n ToolStartEvent,\n ToolEndEvent,\n FinishedEvent,\n NotificationEvent,\n AllBusEvents,\n ProtocolEvent,\n} from './events.js';\nimport type { AgentEvent, AllEventType } from '../event/types.js';\nimport { createAgentEvent } from '../event/types.js';\nimport { validateAgentEventSafe } from '../event/schema.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 publishFinished(finished: Omit<FinishedEvent, 'type' | 'timestamp'>): void {\n const event: FinishedEvent = { ...finished, type: 'finished', timestamp: new Date() };\n this.emit(event);\n }\n\n onFinished(handler: EventHandler<FinishedEvent>): () => void {\n return this.on('finished', 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 publishAgentMessage(event: Omit<AgentMessageEvent, 'type' | 'timestamp'>): void {\n const evt: AgentMessageEvent = { ...event, type: 'agent:message', timestamp: new Date() };\n this.emit(evt);\n }\n\n onAgentMessage(handler: EventHandler<AgentMessageEvent>): () => void {\n return this.on('agent:message', handler);\n }\n\n publishToolStart(event: Omit<ToolStartEvent, 'type' | 'timestamp'>): void {\n const evt: ToolStartEvent = { ...event, type: 'tool:start', timestamp: new Date() };\n this.emit(evt);\n }\n\n onToolStart(handler: EventHandler<ToolStartEvent>): () => void {\n return this.on('tool:start', handler);\n }\n\n publishToolEnd(event: Omit<ToolEndEvent, 'type' | 'timestamp'>): void {\n const evt: ToolEndEvent = { ...event, type: 'tool:end', timestamp: new Date() };\n this.emit(evt);\n }\n\n onToolEnd(handler: EventHandler<ToolEndEvent>): () => void {\n return this.on('tool:end', 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 * Publish Agent event\n */\n publishAgentEvent(event: AgentEvent): void {\n const validation = validateAgentEventSafe(event);\n if (!validation.success) {\n this.logger.error('Invalid Agent event:', validation.error);\n return;\n }\n\n this.emit({\n type: 'agent:event',\n timestamp: new Date(),\n event,\n } as ProtocolEvent);\n }\n\n /**\n * Create and publish Agent event\n */\n emitAgentEvent(\n type: AllEventType,\n direction: 'agent' | 'user' | 'system',\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Parameters<typeof createAgentEvent>[5]\n ): void {\n const event = createAgentEvent(type, direction, sessionId, agent, deviceId, payload);\n this.publishAgentEvent(event);\n }\n\n /**\n * Subscribe to Agent events\n */\n onAgentEvent(handler: (event: AgentEvent) => void): () => void {\n return this.on('agent:event', (evt: ProtocolEvent) => {\n handler(evt.event);\n });\n }\n\n /**\n * Subscribe to specific Agent event type\n */\n onAgentEventType(\n eventType: AllEventType,\n handler: (event: AgentEvent) => void\n ): () => void {\n return this.onAgentEvent((event) => {\n if (event.type === eventType) {\n handler(event);\n }\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 { z } from 'zod';\n\nexport const AGENT_EVENT_VERSION = '1.0.0';\n\nexport const AgentEventButtonSchema = z.object({\n text: z.string(),\n action: z.string(),\n});\n\nexport const AgentEventPayloadSchema = z.object({\n title: z.string().optional(),\n description: z.string().optional(),\n text: z.string().optional(),\n buttons: z.array(AgentEventButtonSchema).optional(),\n data: z.record(z.unknown()),\n extensions: z.record(z.unknown()).optional(),\n});\n\nexport const AgentEventSchema = z.object({\n id: z.string(),\n ts: z.number(),\n version: z.string(),\n type: z.string(),\n direction: z.enum(['agent', 'user', 'system']),\n session_id: z.string(),\n agent: z.string(),\n device_id: z.string(),\n ack_id: z.string().optional(),\n app: z.string().optional(),\n payload: AgentEventPayloadSchema,\n});\n\nexport type ValidatedAgentEvent = z.infer<typeof AgentEventSchema>;\n\n/**\n * Validate an AgentEvent. Throws ZodError if validation fails.\n * @throws {z.ZodError} When validation fails\n */\nexport function validateAgentEvent(data: unknown): ValidatedAgentEvent {\n return AgentEventSchema.parse(data);\n}\n\nexport function validateAgentEventSafe(data: unknown): { success: true; data: ValidatedAgentEvent } | { success: false; error: z.ZodError } {\n const result = AgentEventSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\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","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}","import type { AgentType } from '../adapter/types.js';\n\nexport 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 'sessions',\n 'system',\n]);\n\nexport const AGENT_COMMAND_ROOTS = new Set<AgentType>(['claude', 'codex']);\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 getExplicitAgentCommand(text: string): AgentType | undefined {\n const root = getSlashCommandRoot(text);\n if (!root) {\n return undefined;\n }\n return AGENT_COMMAND_ROOTS.has(root as AgentType) ? (root as AgentType) : undefined;\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 getExplicitAgentCommand,\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 explicitAgent = getExplicitAgentCommand(message.text);\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 (explicitAgent) {\n if (!boundAgent) {\n this.replyNoBinding(message, explicitAgent);\n return;\n }\n\n if (boundAgent !== explicitAgent) {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: `This channel is bound to ${boundAgent}. Use /bind ${explicitAgent} first or send the command in the ${explicitAgent}-bound channel.`,\n replyToMessageId: message.messageId,\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: explicitAgent,\n },\n '[InboundRouter] Routed explicit agent command'\n );\n this.bus.publishInbound({\n ...message,\n targetAgent: explicitAgent,\n agentCommand: 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 private replyNoBinding(message: InboundMessage, explicitAgent: string): void {\n this.bus.publishOutbound({\n channel: message.channel,\n chatId: message.chatId,\n text: `No agent is bound to this channel. Bind ${explicitAgent} first with /bind ${explicitAgent}.`,\n replyToMessageId: message.messageId,\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 'Handsoff uses two command namespaces:',\n '- System commands: `/start`, `/help`, `/status`, `/bind`, `/new`, `/clear`, `/stop`, `/session`, `/sessions`',\n '- Agent commands: `/codex ...`, `/claude ...`',\n '',\n '**Default Message Routing**',\n '- Plain text is forwarded to the agent bound to this channel.',\n '- System commands are always handled by Handsoff.',\n '- Agent-prefixed commands are forwarded to the matching bound agent.',\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 '- `/sessions` list active sessions',\n '',\n '**Agent Commands**',\n '- `/codex help`, `/codex status`, `/codex reset`',\n '- `/claude help`, `/claude status` for hook-based Claude integration',\n '',\n 'If a command is not a system command, it will be routed 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 return [\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 ].join('\\n');\n },\n};\n\nexport const sessionsRootCommand: CommandHandler = {\n description: 'List active sessions',\n usage: '/sessions',\n handler: async (args, context): Promise<string> => listHandler.handler(args, context),\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 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 clearCommand: CommandHandler = {\n description: 'Clear the current chat session context',\n usage: '/clear',\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 '- Use `/codex ...` or `/claude ...` for agent-specific 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 sessionsRootCommand,\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 sessionsRootCommand,\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 registry.register('sessions', COMMAND_ROOT_SUBCOMMAND, sessionsRootCommand);\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 FinishedEvent,\n ToolFailureEvent,\n InteractionRequestEvent,\n AgentMessageEvent,\n ToolStartEvent,\n ToolEndEvent,\n} from '../core/bus/events.js';\nimport type { SessionContextProvider } from '../core/session-context.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 private sessionChatMap = new Map<string, string>();\n\n constructor(\n private bus: EventBus,\n private logger: Logger,\n private provider?: SessionContextProvider,\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.onAgentMessage(this.handleAgentMessage.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolStart(this.handleToolStart.bind(this))\n );\n this.unsubscribeFns.push(\n this.bus.onToolEnd(this.handleToolEnd.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.onFinished(this.handleFinished.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 if (event.chatId) {\n this.sessionChatMap.set(event.sessionId, event.chatId);\n }\n await this.publishContext({\n eventType: 'session_start',\n sessionId: event.sessionId,\n chatId: event.chatId,\n userId: event.userId,\n });\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 chatId: event.chatId,\n userId: event.userId,\n reason: event.reason,\n });\n this.sessionChatMap.delete(event.sessionId);\n }\n\n private async handleInteractionRequest(event: InteractionRequestEvent): Promise<void> {\n // Map interaction type to legacy event type for backward compatibility\n const eventTypeMap: Record<string, NotificationContext['eventType']> = {\n 'permission': 'permission_request',\n 'question': 'question_request',\n 'input': 'interaction_request',\n 'confirm': 'interaction_request',\n };\n\n // Safely extract toolName from title\n const toolName = event.content.title?.replace(/^Permission Required: /, '') ?? '';\n\n await this.publishContext({\n eventType: eventTypeMap[event.interactionType] || 'interaction_request',\n sessionId: event.sessionId,\n chatId: event.chatId,\n requestId: event.requestId,\n toolName,\n toolInput: event.content.permission?.args,\n cwd: event.cwd,\n interaction: {\n type: event.interactionType,\n requestId: event.requestId,\n content: event.content,\n },\n });\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 reason: event.error,\n });\n }\n\n private async handleFinished(event: FinishedEvent): Promise<void> {\n // The hook payload's lastAssistantMessage is from the CURRENT session turn and is authoritative.\n // The transcript might contain stale/incorrect data from a wrong file path.\n // We use transcript only for token/duration info, NOT for lastAssistantMessage.\n let summary;\n let transcriptLastAssistantMessage: string | undefined;\n if (this.provider) {\n const fullSummary = await this.provider.getSessionSummary(event.sessionId, event.transcriptPath);\n if (fullSummary) {\n transcriptLastAssistantMessage = fullSummary.lastAssistantMessage;\n // Only use transcript for tokens/duration, not lastAssistantMessage\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { lastAssistantMessage: _, ...transcriptData } = fullSummary;\n summary = transcriptData;\n }\n }\n\n // DEBUG: Log what we got from transcript vs hook payload\n this.logger.debug({\n sessionId: event.sessionId,\n hookLastAssistantMessage: event.lastAssistantMessage,\n transcriptLastAssistantMessage,\n }, 'handleFinished: comparing hook payload vs transcript');\n\n await this.publishContext({\n eventType: 'finished',\n sessionId: event.sessionId,\n chatId: event.chatId,\n lastAssistantMessage: event.lastAssistantMessage,\n summary,\n });\n }\n\n private async handleAgentMessage(event: AgentMessageEvent): Promise<void> {\n await this.publishContext({\n eventType: 'agent:message',\n sessionId: event.sessionId,\n messageContent: event.content,\n });\n }\n\n private async handleToolStart(event: ToolStartEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:start',\n sessionId: event.sessionId,\n toolName: event.toolName,\n toolInput: event.toolInput,\n });\n }\n\n private async handleToolEnd(event: ToolEndEvent): Promise<void> {\n await this.publishContext({\n eventType: 'tool:end',\n sessionId: event.sessionId,\n toolName: event.toolName,\n reason: event.output ?? event.error,\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 const resolvedChatId = context.chatId ?? this.sessionChatMap.get(sessionId) ?? 'broadcast';\n\n this.logger.debug(\n {\n eventType: context.eventType,\n sessionId,\n agentType,\n channelInstanceId,\n channelType,\n resolvedChatId,\n },\n '[NotificationHandler] Routing notification to bound channel'\n );\n\n await this.bus.publishOutbound({\n channel: channelType,\n chatId: resolvedChatId,\n context,\n metadata: {\n eventType: context.eventType,\n channelInstanceId,\n resolvedChatId,\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 // 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.cwd) {\n lines.push(`Working Dir: ${context.cwd}`);\n }\n if (context.toolInput && Object.keys(context.toolInput).length > 0) {\n lines.push('');\n lines.push('Args:');\n lines.push(JSON.stringify(context.toolInput, null, 2));\n }\n break;\n\n case 'finished':\n lines.push('✅ Task Completed');\n lines.push(`Session: ${context.sessionId}`);\n if (context.summary?.durationMs !== undefined) {\n const seconds = (context.summary.durationMs / 1000).toFixed(1);\n lines.push(`Duration: ${seconds}s`);\n }\n if (context.summary?.inputTokens !== undefined && context.summary?.outputTokens !== undefined) {\n lines.push(`Tokens: in ${context.summary.inputTokens} / out ${context.summary.outputTokens}`);\n }\n if (context.lastAssistantMessage || context.summary?.lastAssistantMessage) {\n lines.push('');\n lines.push('Result:');\n lines.push(context.lastAssistantMessage || context.summary?.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 if (context.reason) {\n lines.push(`Reason: ${context.reason}`);\n }\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.reason) {\n lines.push(`Error: ${context.reason}`);\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, idx) => {\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';\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 `🔐 <b>${this.escape(title)}</b>`,\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 `❓ <b>${this.escape(title)}</b>`,\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 switch (context.eventType) {\n case 'permission_request':\n return this.formatPermissionRequest(\n 'Permission Request',\n context.toolName ?? 'Unknown',\n context.toolInput,\n context.cwd\n );\n\n case 'question_request':\n if (context.interaction?.content?.question) {\n const q = context.interaction.content.question;\n return this.formatQuestionRequest(\n context.interaction.content.title || 'Question',\n q.header,\n q.text,\n q.options\n );\n }\n return this.formatQuestionRequest(\n context.interaction?.content?.title || 'Question',\n undefined,\n context.interaction?.content?.description || '',\n []\n );\n\n case 'finished':\n return this.formatFinished(\n context.summary?.durationMs,\n context.summary?.inputTokens,\n context.summary?.outputTokens,\n context.summary?.lastAssistantMessage ?? context.lastAssistantMessage\n );\n\n case 'session_start':\n return `🚀 <b>Session Started</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'session_end':\n return `👋 <b>Session Ended</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n\n case 'tool_failure':\n return `❌ <b>Tool Failed</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName ?? 'Unknown')}`;\n\n case 'agent:message':\n return this.truncate(`🤖 <b>Agent Message</b>\\n\\n${this.escape(context.messageContent || '')}`);\n\n case 'tool:start':\n return `🔧 <b>Tool Started</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName || 'Unknown')}`;\n\n case 'tool:end':\n return `✅ <b>Tool Completed</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}\\n<b>Tool:</b> ${this.escape(context.toolName || 'Unknown')}`;\n\n default:\n return `📋 <b>Notification</b>\\n\\n<b>Session:</b> ${this.escape(context.sessionId)}`;\n }\n }\n\n /**\n * 格式化结果通知消息\n */\n formatFinished(\n durationMs?: number,\n inputTokens?: number,\n outputTokens?: number,\n result?: string\n ): string {\n const lines = [\n '✅ <b>Task Completed</b>',\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 */\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 interaction = message.context?.interaction;\n const requestId = message.context?.requestId;\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 = message.context?.toolName || '';\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.content.question) {\n const question = interaction.content.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 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 { 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' || message.metadata?.eventType === 'question_request') &&\n message.chatId === '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 interaction = message.context?.interaction;\n const requestId = message.context?.requestId;\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 = message.context?.toolName || '';\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.content.question) {\n const question = interaction.content.question;\n this.pendingOptions.set(\n requestId,\n question.options.map((opt) => ({ id: opt.id, value: opt.value }))\n );\n buttons = question.options.map((opt) => ({\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 || !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 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 'permission_request':\n md = `**Session:** ${context.sessionId}\\n`;\n md += `**Tool:** ${context.toolName || 'N/A'}\\n`;\n md += `**Working Dir:** ${context.cwd || 'N/A'}\\n\\n`;\n md += `**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(context.toolInput, null, 2)}\\n\\`\\`\\``;\n break;\n case 'finished':\n md = `**Session:** ${context.sessionId}\\n`;\n if (context.summary?.durationMs !== undefined) {\n md += `**Duration:** ${(context.summary.durationMs / 1000).toFixed(1)}s\\n`;\n }\n {\n const msg = context.summary?.lastAssistantMessage ?? context.lastAssistantMessage;\n if (msg) {\n md += `\\n**Result:**\\n${msg}`;\n }\n }\n break;\n case 'agent:message':\n md = `Agent Message\\n\\n**Session:** ${context.sessionId}\\n\\n**Message:**\\n${context.messageContent || ''}`;\n break;\n case 'tool:start':\n md = `**Session:** ${context.sessionId}\\n**Tool:** ${context.toolName || 'N/A'}\\n\\n**Status:** Started`;\n break;\n case 'tool:end':\n md = `**Session:** ${context.sessionId}\\n**Tool:** ${context.toolName || 'N/A'}\\n\\n**Status:** Completed`;\n break;\n default:\n md = `**Event:** ${context.eventType}\\n**Session:** ${context.sessionId}`;\n }\n return md;\n }\n\n /**\n * 根据上下文获取标题\n */\n private getTitleForContext(context?: NotificationContext): string {\n if (!context) return 'Notification';\n switch (context.eventType) {\n case 'permission_request':\n return 'Permission Request';\n case 'finished':\n return 'Task Completed';\n case 'session_start':\n return 'Session Started';\n case 'session_end':\n return 'Session Ended';\n case 'tool_failure':\n return 'Tool Failed';\n case 'agent:message':\n return 'Agent Message';\n case 'tool:start':\n return 'Tool Started';\n case 'tool:end':\n return 'Tool Completed';\n default:\n return 'Notification';\n }\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 } 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',\n timestamp,\n payload: {\n sessionId: context.sessionId,\n message: {\n id: options.createMessageId?.() ?? createId('msg'),\n sessionId: context.sessionId,\n role: 'assistant',\n type: 'text',\n text: context.messageContent ?? message.text ?? '',\n createdAt: timestamp,\n status: 'completed',\n metadata: {},\n },\n },\n };\n\n case 'permission_request':\n case 'question_request':\n case 'interaction_request':\n return mapInteractionRequested(context, eventId, timestamp);\n\n case 'finished':\n return {\n type: 'event',\n eventId,\n name: 'agent.finished',\n timestamp,\n payload: {\n sessionId: context.sessionId,\n reason: context.reason,\n lastAssistantMessage: context.lastAssistantMessage,\n summary: context.summary,\n },\n };\n\n default:\n return null;\n }\n}\n\nfunction mapInteractionRequested(\n context: NotificationContext,\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.content.title,\n description: interaction.content.description,\n status: 'pending',\n createdAt: timestamp,\n toolName: context.toolName,\n toolInput: context.toolInput,\n riskLevel: interaction.content.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 } 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 metadata?: Record<string, unknown>,\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 if (typeof payload.cwd === 'string' && payload.cwd.trim() !== '') {\n metadata.cwd = payload.cwd;\n metadata.workspacePath = payload.cwd;\n }\n\n await gateway.createSession(connection.token, sessionId, metadata);\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 const session = options.gateway.getSession(pendingSessionId);\n if (!session?.protocolHandler.resolvePending(payload.interactionId, response)) {\n return error(frame.id, 'NOT_IMPLEMENTED', 'Interaction response transport is unavailable');\n }\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:\n readString(metadata.workspacePath) ??\n readString(metadata.cwd) ??\n readString(metadata.workDir) ??\n readString(metadata.work_dir),\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","#!/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 { ClaudeHookAdapter, ClaudeRemoteAdapter } from '../adapters/agent/claude/index.js';\nimport { CodexAppServerAdapter } from '../adapters/agent/codex/index.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 { ClaudeSessionContextProvider } from '../adapters/agent/claude/session-context.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 { 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 // Start NotificationHandler\n const sessionContextProvider = new ClaudeSessionContextProvider();\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 sessionContextProvider,\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: CodexAppServerAdapter | undefined;\n if (config.agent.codex?.enabled) {\n const codexToken = gateway.getAgentRegistry().registerAgent('codex');\n codexAdapter = new CodexAppServerAdapter({\n bus,\n logger: createAgentLogger('codex'),\n 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 ClaudeRemoteAdapter({\n logger: createAgentLogger('claude'),\n bus,\n 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,\n })\n : new ClaudeHookAdapter({\n logger: createAgentLogger('claude'),\n bus,\n 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 // Adapter is now registered in AgentAdapterRegistry for discovery by other components\n setupRoutes(httpServer, gateway, adapter, () => 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.channels?.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.channels.app.channel_id,\n auth_token: config.channels.app.auth_token,\n heartbeat_interval_ms: config.channels.app.heartbeat_interval_ms,\n notify_types: config.channels.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","z","i","acc","ext","start","final","ext","qmark","star","regExpEscape","i","match","existsSync","readFileSync","error","readFileSync","existsSync","join","error","logger","logger","filter","randomUUID","hostname","resolve","error","join","resolve","randomUUID","error","randomUUID","randomUUID","readFile","resolve","readFile","error","randomUUID","existsSync","resolve","error","error","resolve","existsSync","resolve","randomUUID","randomUUID","spawn","createInterface","path","error","filter","defaults","resolve","match","randomUUID","readdir","readFile","join","existsSync","match","createServer","URL","logger","path","createServer","URL","resolve","error","match","URL","resolve","error","VERSION","logger","path","resolve","URL","error","filter","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","homedir","join","homedir","path","existsSync","readFileSync","error","randomUUID","randomUUID","resolve","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","VERSION","homedir","logger","bindingService","error"]}