handsoff 0.0.1-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.
- package/README.md +217 -0
- package/config.example.toml +29 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +1940 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/daemon/process.js +8228 -0
- package/dist/daemon/process.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shared/pidfile.ts","../../src/shared/logger.ts","../../src/gateway/session.ts","../../src/gateway/events.ts","../../src/gateway/plugins.ts","../../src/gateway/index.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/permission-service.ts","../../src/gateway/publisher.ts","../../src/adapters/agent/claude/ClaudeAdapter.ts","../../src/core/session-scanner/registry.ts","../../src/core/adapter/AgentAdapterRegistry.ts","../../src/adapters/agent/claude/hook/HookServer.ts","../../src/hep/types.ts","../../src/adapters/agent/claude/ClaudeEventMapper.ts","../../src/adapters/agent/claude/scanner.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/hep/ack.ts","../../src/shared/credentials.ts","../../src/adapters/permissions/queue.ts","../../src/core/bus/index.ts","../../src/hep/schema.ts","../../src/core/channel/registry.ts","../../src/core/channel/manager.ts","../../src/core/command/parser.ts","../../src/core/command/executor.ts","../../src/core/command/builtin/session.ts","../../src/core/command/builtin/system.ts","../../src/core/command/builtin/help.ts","../../src/core/command/builtin/start.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/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/daemon/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;\n\nfunction createSyncLogger(logFilePath: string): pino.Logger {\n const logDir = dirname(logFilePath);\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n\n const hostnameValue = hostname();\n\n const writeLog = (level: string, msg: string, obj?: object) => {\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 };\n\n const log = (logLevel: string) => {\n return (obj: object | string, msg?: string) => {\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): pino.Logger {\n fileLogger = createSyncLogger(logFilePath);\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/channel/${channelName}.log`;\n return createSyncLogger(logFile);\n}\n\nexport function createFileLogger(logFilePath: string, _level: LogLevel = LogLevel.DEBUG): pino.Logger {\n return createSyncLogger(logFilePath);\n}\n\nexport function getLogger(_level?: LogLevel): pino.Logger {\n if (!consoleLogger) {\n consoleLogger = pino({\n level: _level || LogLevel.INFO,\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 { randomBytes } from 'crypto';\n\n/**\n * Session interface representing an internal agent session with lifecycle tracking.\n * Used by SessionManager for session lifecycle management.\n */\nexport interface Session {\n id: string;\n agentType: string;\n token: string;\n workDir?: string;\n startedAt: Date;\n lastActivityAt: Date;\n endedAt?: Date;\n metadata: Record<string, unknown>;\n isEnded(): boolean;\n updateActivity(): void;\n}\n\n/**\n * Session filter options for listing sessions\n */\nexport interface SessionFilter {\n agentType?: string;\n includeEnded?: boolean;\n}\n\nclass SessionImpl implements Session {\n id: string;\n agentType: string;\n token: string;\n workDir?: string;\n startedAt: Date;\n lastActivityAt: Date;\n endedAt?: Date;\n metadata: Record<string, unknown>;\n\n constructor(\n id: string,\n agentType: string,\n token: string,\n metadata: Record<string, unknown> = {}\n ) {\n this.id = id;\n this.agentType = agentType;\n this.token = token;\n this.metadata = metadata;\n this.workDir = metadata.work_dir as string | undefined;\n this.startedAt = new Date();\n this.lastActivityAt = new Date();\n }\n\n isEnded(): boolean {\n return this.endedAt !== undefined;\n }\n\n updateActivity(): void {\n this.lastActivityAt = new Date();\n }\n}\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\n/**\n * SessionManager handles session lifecycle management\n *\n * Design notes:\n * - One token can have multiple sessions (e.g., user runs multiple Claude instances)\n * - Sessions are indexed by sessionId for O(1) lookup\n * - Token is used only for authorization and to determine agentType\n * - Agent registration is delegated to AgentRegistry for single responsibility\n */\nexport class SessionManager {\n // Maps sessionId to Session (primary index)\n private sessionsById = new Map<string, Session>();\n\n // Registry for token-based agent registration\n private registry: AgentRegistry;\n\n constructor(registry?: AgentRegistry) {\n this.registry = registry ?? new AgentRegistry();\n }\n\n /**\n * Register an agent and generate a token for it\n */\n registerAgent(agentType: string, customToken?: string): string {\n return this.registry.registerAgent(agentType, customToken);\n }\n\n /**\n * Create a new session for a registered agent\n */\n createSession(\n token: string,\n sessionId: string,\n metadata: Record<string, unknown> = {}\n ): Session {\n const agentType = this.registry.getAgentType(token);\n if (!agentType) {\n throw new Error('Invalid token: no agent registered');\n }\n\n // Check if session already exists\n const existingSession = this.sessionsById.get(sessionId);\n if (existingSession) {\n return existingSession;\n }\n\n const session = new SessionImpl(sessionId, agentType, token, metadata);\n this.sessionsById.set(sessionId, session);\n return session;\n }\n\n /**\n * Get a session by its session ID\n */\n getSessionById(sessionId: string): Session | undefined {\n return this.sessionsById.get(sessionId);\n }\n\n /**\n * List all sessions with optional filtering\n */\n listSessions(filter?: SessionFilter): Session[] {\n let sessions = Array.from(this.sessionsById.values());\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.isEnded());\n }\n\n return sessions;\n }\n\n /**\n * Update the last activity timestamp for a session\n */\n updateActivity(sessionId: string): void {\n const session = this.sessionsById.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n if (session.isEnded()) {\n throw new Error(`Session has ended: ${sessionId}`);\n }\n session.updateActivity();\n }\n\n /**\n * End a session\n */\n endSession(sessionId: string): void {\n const session = this.sessionsById.get(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n (session as SessionImpl).endedAt = new Date();\n }\n\n /**\n * Unregister an agent by its token\n * Note: This does not end existing sessions, just prevents new ones\n */\n unregisterAgent(token: string): boolean {\n return this.registry.unregisterAgent(token);\n }\n\n /**\n * List all registered agents\n */\n listRegisteredAgents(): { token: string; agentType: string }[] {\n return this.registry.listRegisteredAgents();\n }\n\n /**\n * Check if a token is registered\n */\n isTokenRegistered(token: string): boolean {\n return this.registry.isTokenRegistered(token);\n }\n\n /**\n * Get agent type for a token\n */\n getAgentType(token: string): string | undefined {\n return this.registry.getAgentType(token);\n }\n}\n","/**\n * Event frame structure for normalized events\n */\nexport interface EventFrame {\n type: 'event';\n event: string;\n payload: {\n agentType: string;\n sessionId: string;\n timestamp: string;\n data: unknown;\n };\n seq?: number;\n}\n\n/**\n * Response frame structure\n */\nexport interface ResponseFrame {\n type: 'res';\n id: string;\n result?: unknown;\n error?: { code: number; message: string };\n}\n\n/**\n * Event handler type\n */\nexport type EventHandler<T = unknown> = (event: T) => void | Promise<void>;\n\n/**\n * EventBus for decoupled component communication\n */\nexport class EventBus {\n private handlers = new Map<string, Set<EventHandler<unknown>>>();\n\n on<T>(eventType: string, handler: EventHandler<T>): () => void {\n if (!this.handlers.has(eventType)) {\n this.handlers.set(eventType, new Set());\n }\n this.handlers.get(eventType)!.add(handler as EventHandler<unknown>);\n\n return () => {\n this.handlers.get(eventType)?.delete(handler as EventHandler<unknown>);\n };\n }\n\n once<T>(eventType: string, handler: EventHandler<T>): void {\n const wrapped: EventHandler<unknown> = (event) => {\n this.off(eventType, wrapped);\n return handler(event as T);\n };\n this.on(eventType, wrapped as EventHandler<T>);\n }\n\n emit<T>(eventType: string, payload: T): void {\n const handlers = this.handlers.get(eventType);\n if (!handlers) return;\n\n for (const handler of handlers) {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in event handler for ${eventType}:`, error);\n }\n }\n }\n\n off(eventType?: string, handler?: EventHandler<unknown>): void {\n if (!eventType) {\n this.handlers.clear();\n return;\n }\n\n if (!handler) {\n this.handlers.delete(eventType);\n return;\n }\n\n this.handlers.get(eventType)?.delete(handler);\n }\n}\n\n/**\n * Default event type mappings for Claude Code\n * Centralized mapping to avoid duplication\n */\nexport const EVENT_TYPE_MAP: Record<string, string> = {\n SessionStart: 'session_start',\n SessionEnd: 'session_end',\n Stop: 'finished',\n PostToolUse: 'tool_use',\n PostToolUseFailure: 'error',\n PreToolUse: 'permission_request',\n Notification: 'notification',\n SubagentStart: 'message',\n SubagentStop: 'message',\n UserPromptSubmit: 'message',\n};\n\n/**\n * Normalize event type from agent-specific to standard format\n */\nexport function normalizeEventType(eventType: string): string {\n return EVENT_TYPE_MAP[eventType] ?? eventType.toLowerCase();\n}\n\n/**\n * Extract session ID from payload (supports both snake_case and camelCase)\n */\nexport function extractSessionId(payload: unknown): string | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const p = payload as Record<string, unknown>;\n const sessionId = p.session_id ?? p.sessionId;\n return typeof sessionId === 'string' ? sessionId : undefined;\n}\n","/**\n * Extension points for the plugin system\n */\nexport enum ExtensionPoint {\n /** Transform events from agent-specific format to normalized format */\n EVENT_TRANSFORM = 'event:transform',\n /** Called when a session is created */\n SESSION_CREATE = 'session:create',\n /** Called when a session ends */\n SESSION_END = 'session:end',\n /** Filter events before they are broadcast */\n EVENT_FILTER = 'event:filter',\n}\n\n/**\n * Event transformation context\n */\nexport interface EventTransformContext {\n agentType: string;\n sessionId: string;\n eventType: string;\n payload: unknown;\n}\n\n/**\n * Transformed event result\n */\nexport interface TransformedEvent {\n event: string;\n payload: unknown;\n}\n\n/**\n * Event transformer function type\n */\nexport type EventTransformer = (\n context: EventTransformContext\n) => TransformedEvent | null | undefined;\n\n/**\n * Generic handler function type\n */\nexport type ExtensionHandler = (...args: unknown[]) => unknown;\n\n/**\n * Extension interface\n */\nexport interface Extension {\n name: string;\n extensionPoint: ExtensionPoint;\n handler: ExtensionHandler;\n}\n\n/**\n * Plugin interface\n */\nexport interface Plugin {\n name: string;\n version: string;\n extensions: Extension[];\n}\n\n/**\n * Plugin registry for managing extensions\n */\nexport class PluginRegistry {\n private extensions = new Map<ExtensionPoint, Extension[]>();\n\n /**\n * Register an extension\n */\n register(extension: Extension): void {\n if (!this.extensions.has(extension.extensionPoint)) {\n this.extensions.set(extension.extensionPoint, []);\n }\n this.extensions.get(extension.extensionPoint)!.push(extension);\n }\n\n /**\n * Unregister an extension by name\n */\n unregister(extensionName: string): void {\n for (const [point, extensions] of this.extensions) {\n const filtered = extensions.filter((e) => e.name !== extensionName);\n if (filtered.length !== extensions.length) {\n this.extensions.set(point, filtered);\n }\n }\n }\n\n /**\n * Execute all handlers for an extension point\n */\n execute<T>(point: ExtensionPoint, ...args: unknown[]): T[] {\n const extensions = this.extensions.get(point) || [];\n const results: T[] = [];\n\n for (const ext of extensions) {\n try {\n const result = ext.handler(...args) as T;\n if (result !== undefined && result !== null) {\n results.push(result);\n }\n } catch (error) {\n console.error(`Error executing extension ${ext.name} for ${point}:`, error);\n }\n }\n\n return results;\n }\n\n /**\n * Execute handlers and return the first non-null result\n */\n executeFirst<T>(point: ExtensionPoint, ...args: unknown[]): T | undefined {\n const results = this.execute<T>(point, ...args);\n return results[0];\n }\n\n /**\n * Transform an event using registered transformers\n */\n transformEvent(context: EventTransformContext): TransformedEvent | null {\n const transformers = this.extensions.get(ExtensionPoint.EVENT_TRANSFORM) || [];\n\n for (const ext of transformers) {\n try {\n const result = (ext.handler as EventTransformer)(context);\n if (result) {\n return result;\n }\n } catch (error) {\n console.error(`Error in event transformer ${ext.name}:`, error);\n }\n }\n\n return null;\n }\n\n /**\n * Check if any extensions are registered for a point\n */\n hasExtensions(point: ExtensionPoint): boolean {\n return (this.extensions.get(point)?.length || 0) > 0;\n }\n\n /**\n * Get all registered extensions for a point\n */\n getExtensions(point: ExtensionPoint): Extension[] {\n return this.extensions.get(point) || [];\n }\n\n /**\n * Clear all extensions\n */\n clear(): void {\n this.extensions.clear();\n }\n}\n","import type { SessionManager } from './session.js';\nimport type { EventBus } from './events.js';\nimport type { Session, SessionFilter } from './session.js';\nimport type { PluginRegistry } from './plugins.js';\nimport type { AgentEventEnvelope } from '../core/agent-event.js';\nimport { PermissionService } from './permission-service.js';\nimport { EventPublisher } from './publisher.js';\nimport type { PermissionDecision } from '../adapters/permissions/types.js';\n\n/**\n * Gateway is the core domain aggregate root.\n * It orchestrates sessions, events, and agent management.\n */\nexport class Gateway {\n constructor(\n private sessionManager: SessionManager,\n private eventBus: EventBus,\n private permissionService: PermissionService,\n private eventPublisher: EventPublisher,\n private pluginRegistry?: PluginRegistry\n ) {}\n\n /**\n * Get the plugin registry for registering extensions\n */\n getPluginRegistry(): PluginRegistry | undefined {\n return this.pluginRegistry;\n }\n\n /**\n * Register a new agent type and get its token\n */\n registerAgent(agentType: string, token?: string): string {\n return this.sessionManager.registerAgent(agentType, token);\n }\n\n /**\n * List all registered agents\n */\n listRegisteredAgents(): Array<{ token: string; agentType: string }> {\n return this.sessionManager.listRegisteredAgents();\n }\n\n /**\n * Create a new session (for testing/manual creation)\n */\n createSession(\n token: string,\n sessionId: string,\n metadata?: Record<string, unknown>\n ): Session {\n return this.sessionManager.createSession(token, sessionId, metadata);\n }\n\n /**\n * Get a session by ID\n */\n getSession(sessionId: string): Session | undefined {\n return this.sessionManager.getSessionById(sessionId);\n }\n\n /**\n * List all sessions\n */\n listSessions(filter?: SessionFilter): Session[] {\n return this.sessionManager.listSessions(filter);\n }\n\n /**\n * End a session\n */\n endSession(sessionId: string): void {\n this.sessionManager.endSession(sessionId);\n }\n\n async handleEvent(\n token: string,\n envelope: AgentEventEnvelope\n ): Promise<PermissionDecision | undefined> {\n const sessionId = envelope.metadata.sessionId;\n if (!sessionId) {\n return;\n }\n\n let session = this.sessionManager.getSessionById(sessionId);\n if (!session) {\n try {\n session = this.sessionManager.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.endSession(sessionId);\n } else {\n session.updateActivity();\n }\n\n if (envelope.type === 'permission:request') {\n // Publish permission event to bus/WebSocket even for immediate decisions\n this.eventPublisher.publish(envelope, session);\n return await this.permissionService.evaluate(envelope);\n }\n\n this.eventPublisher.publish(envelope, session);\n return undefined;\n }\n}\n\n// Re-export all gateway types\nexport * from './session.js';\nexport * from './events.js';\nexport * from './plugins.js';\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 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 AgentConfig {\n claude?: ClaudeAgentConfig & { permission?: AgentPermissionConfig };\n}\n\nexport interface Config {\n general: GeneralConfig;\n channel: ChannelConfig;\n agent: AgentConfig;\n}\n\nconst 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 },\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 },\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","// src/gateway/permission-service.ts\nimport { PermissionQueue } from '../adapters/permissions/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/agent-event.js';\nimport type { PermissionDecision } from '../adapters/permissions/types.js';\n\ninterface SmartPermissionOptions {\n toolName: string;\n toolInput: Record<string, unknown>;\n permissionMode: string;\n cwd: string;\n}\n\ninterface SmartPermissionResult {\n immediate: boolean;\n decision: 'allow' | 'deny' | 'pending';\n reason: string;\n}\n\nfunction evaluateSmartPermission(options: SmartPermissionOptions): SmartPermissionResult {\n const { toolName, toolInput, permissionMode, cwd } = options;\n\n if (permissionMode === 'bypassPermissions') {\n return { immediate: true, decision: 'allow', reason: 'permissionMode is bypassPermissions' };\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 { immediate: true, decision: 'deny', reason: denyResult.reason };\n }\n return { immediate: true, decision: 'allow', reason: 'Low-risk tool, no deny match' };\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 { immediate: true, decision: 'deny', reason: denyResult.reason };\n }\n return { immediate: true, decision: 'allow', reason: 'acceptEdits mode for Edit/Write' };\n }\n\n const result = checkPermission(toolName, toolInput, projectConfig);\n\n if (result.decision === 'deny') {\n return { immediate: true, decision: 'deny', reason: result.reason };\n }\n if (result.decision === 'allow') {\n return { immediate: true, decision: 'allow', reason: result.reason };\n }\n\n return { immediate: false, decision: 'pending', reason: 'Need user decision' };\n}\n\nexport class PermissionService {\n constructor(\n readonly permissionQueue: PermissionQueue,\n private bus: EventBus\n ) {}\n\n async evaluate(envelope: AgentEventEnvelope): Promise<PermissionDecision> {\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 = payload.sessionId || envelope.metadata.sessionId;\n const toolName = 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\n logger.info(`[PreToolUse] Received: ${toolName} | session=${sessionId} | cwd=${cwd || 'NOT_FOUND'}`);\n\n const smart = evaluateSmartPermission({ toolName, toolInput, permissionMode, cwd });\n\n if (smart.immediate) {\n logger.info(`[PreToolUse] ${toolName}: ${smart.decision} - ${smart.reason}`);\n return { behavior: smart.decision as 'allow' | 'deny', message: smart.reason };\n }\n\n const { requestId, decisionPromise } = this.permissionQueue.request({\n sessionId,\n toolName,\n toolInput: { ...toolInput, _cwd: cwd },\n });\n\n logger.info(`[PreToolUse] Blocking: ${toolName} | requestId=${requestId}`);\n\n this.bus.publishPermissionRequest({\n requestId,\n sessionId,\n toolName,\n args: toolInput,\n chatId: sessionId,\n messageId: '',\n cwd,\n });\n\n const queueDecision = await decisionPromise;\n logger.info(`[PreToolUse] Released: ${toolName} | decision=${queueDecision.behavior}${queueDecision.message ? ' | reason=' + queueDecision.message : ''}`);\n return queueDecision;\n }\n}\n","import type { EventBus as CoreEventBus } from '../core/bus/index.js';\nimport type { AgentEventEnvelope } from '../core/agent-event.js';\nimport type { EventFrame } from './events.js';\nimport { PluginRegistry, ExtensionPoint } from './plugins.js';\nimport type { Session } from './session.js';\nimport type { Persistence } from '../shared/persistence.js';\n\nexport interface BroadcastFn {\n (frame: EventFrame): void;\n}\n\nexport class EventPublisher {\n private plugins: PluginRegistry;\n\n constructor(\n private bus: CoreEventBus,\n private broadcastFn?: BroadcastFn,\n pluginRegistry?: PluginRegistry,\n private persistence?: Persistence\n ) {\n this.plugins = pluginRegistry ?? new PluginRegistry();\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,\n });\n this.plugins.execute(ExtensionPoint.SESSION_CREATE, session);\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,\n reason: envelope.payload.reason as string | undefined,\n });\n this.plugins.execute(ExtensionPoint.SESSION_END, session);\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,\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 PermissionService 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 getPluginRegistry(): PluginRegistry {\n return this.plugins;\n }\n}\n","// src/adapters/agent/claude/ClaudeAdapter.ts\n// Unified Claude Adapter using HEP (Handsoff Event Protocol) as internal format\n\nimport { randomUUID } from 'crypto';\nimport type {\n AgentAdapter,\n AgentEventEnvelope,\n CreateSessionOptions,\n SessionHandle,\n SessionInfo,\n PermissionResponseCommand,\n} from '../../../core/adapter/AgentAdapter.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport { AgentAdapterRegistry } from '../../../core/adapter/AgentAdapterRegistry.js';\nimport { HookServer } from './hook/HookServer.js';\nimport type { HandsoffEvent } from '../../../hep/types.js';\nimport { ClaudeSessionScanner } from './scanner.js';\nimport {\n mapClaudeToHEP,\n mapClaudeToAgentEventEnvelope,\n isClaudeHookEventType,\n} from './ClaudeEventMapper.js';\n\n/**\n * Claude Adapter\n *\n * Uses HEP (Handsoff Event Protocol) as the internal event format.\n * Supports both legacy and unified hook URL formats.\n *\n * Event flow:\n * Claude Code → HookServer → HEP → (Optional: AgentEventEnvelope) → Gateway\n *\n * Benefits:\n * - Single event pipeline\n * - Standardized HEP 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\n private hookServer: HookServer | null = null;\n private eventHandler: ((event: AgentEventEnvelope) => void) | null = null;\n private hepEventHandler: ((event: HandsoffEvent) => 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\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 }\n\n // Register with AgentAdapterRegistry for discovery\n AgentAdapterRegistry.getInstance().register(this);\n }\n\n async shutdown(): Promise<void> {\n await this.hookServer?.stop();\n this.sessions.clear();\n this.pendingPermissionHandlers.clear();\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 // HEP event handler (new style)\n onHEPEvent: (hepEvent) => {\n if (this.hepEventHandler) {\n this.hepEventHandler(hepEvent);\n }\n },\n // Legacy event handler (backward compatible)\n onEvent: (envelope) => {\n if (this.eventHandler) {\n this.eventHandler(envelope);\n }\n },\n // Permission request handler\n onPermissionRequest: (envelope, respond) => {\n const requestId = envelope.metadata.permissionRequestId || envelope.sessionId;\n this.pendingPermissionHandlers.set(requestId, respond);\n\n // Emit to both handlers\n if (this.hepEventHandler) {\n // Convert envelope back to HEP for the handler\n // This is a simplified conversion - in production you'd want to store the original HEP\n const hepEvent = this.convertEnvelopeToHEP(envelope);\n if (hepEvent) {\n this.hepEventHandler(hepEvent);\n }\n }\n if (this.eventHandler) {\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 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 }\n\n /**\n * Set handler for HEP events (new style)\n */\n setHEPEventHandler(handler: (event: HandsoffEvent) => void): void {\n this.hepEventHandler = handler;\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 HEP (simplified)\n * This is used when we need to emit HEP from legacy envelope\n */\n private convertEnvelopeToHEP(envelope: AgentEventEnvelope): HandsoffEvent | 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 mapClaudeToHEP(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 if (!payload || typeof payload !== 'object') {\n return null;\n }\n\n if (!['SessionStart', 'SessionEnd', 'PreToolUse', 'PermissionRequest',\n 'PostToolUse', 'PostToolUseFailure', 'Stop'].includes(rawEventType)) {\n return null;\n }\n\n return mapClaudeToAgentEventEnvelope(\n rawEventType as any,\n payload as Record<string, unknown>,\n 'claude'\n );\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\n// Re-export for backward compatibility\nexport { ClaudeAdapter as ClaudeHookAdapter };\nexport { HookServer } from './hook/HookServer.js';\nexport {\n mapClaudeToHEP,\n mapHEPToAgentEventEnvelope,\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}","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 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/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 {\n AgentEventEnvelope,\n PermissionResponseCommand,\n} from '../../../../core/adapter/types.js';\nimport type { HandsoffEvent } from '../../../../hep/types.js';\nimport {\n isClaudeHookEventType,\n mapClaudeToHEP,\n mapHEPToAgentEventEnvelope,\n} from '../ClaudeEventMapper.js';\n\nexport interface HookServerOptions {\n port: number;\n token: string;\n /** Legacy event handler (for backward compatibility) */\n onEvent?: (envelope: AgentEventEnvelope) => void;\n /** HEP event handler (new style) */\n onHEPEvent?: (event: HandsoffEvent) => 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 * - HEP 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 onHEPEvent: HookServerOptions['onHEPEvent'];\n private onPermissionRequest: HookServerOptions['onPermissionRequest'];\n\n constructor(options: HookServerOptions) {\n this.token = options.token;\n this.onEvent = options.onEvent;\n this.onHEPEvent = options.onHEPEvent;\n this.onPermissionRequest = options.onPermissionRequest;\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 resolve(actualPort);\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise((resolve) => {\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(() => resolve());\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 // Token validation\n const tokenMatch = pathname.match(/^\\/hook\\/([^/]+)\\/(.+)$/);\n if (!tokenMatch || tokenMatch[1] !== this.token) {\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 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 {\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 // Convert to HEP format first\n const hepEvent = mapClaudeToHEP(eventType as any, payload, 'claude');\n if (!hepEvent) {\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'Event not mapped' }));\n return;\n }\n\n // Emit HEP event (new consumers)\n if (this.onHEPEvent) {\n this.onHEPEvent(hepEvent);\n }\n\n // Convert to legacy format for backward compatibility\n const envelope = mapHEPToAgentEventEnvelope(hepEvent, 'claude');\n if (!envelope) {\n res.writeHead(202);\n res.end(JSON.stringify({ accepted: true, warning: 'HEP 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 requestId =\n envelope.metadata.permissionRequestId || envelope.sessionId;\n\n // Permission request - wait for response\n const timeout = setTimeout(() => {\n if (this.pendingRequests.has(requestId)) {\n this.pendingRequests.delete(requestId);\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(requestId, { response: res, timeout });\n\n try {\n this.onPermissionRequest(envelope, (decision) => {\n this.resolvePermission(requestId, decision);\n });\n } catch (error) {\n console.error('Error in permission request callback:', error);\n clearTimeout(timeout);\n this.pendingRequests.delete(requestId);\n res.writeHead(500);\n res.end(JSON.stringify({ error: 'Internal error' }));\n }\n } else {\n // Non-permission event - don't block\n if (this.onEvent) {\n this.onEvent(envelope);\n }\n res.writeHead(202);\n res.end(\n JSON.stringify({\n accepted: true,\n event_type: hepEvent.type,\n hep_event_id: hepEvent.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 * Handsoff Event Protocol (HEP) v1.0.0\n * Standardized event format for Agent ↔ App communication\n */\n\nexport type HEPDirection = 'agent' | 'user' | 'system';\n\nexport interface HEPButton {\n text: string;\n action: string;\n}\n\nexport interface HEPPayload {\n title?: string;\n description?: string;\n text?: string;\n buttons?: HEPButton[];\n data: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n}\n\nexport interface HandsoffEvent {\n id: string;\n ts: number;\n version: string;\n type: string;\n direction: HEPDirection;\n session_id: string;\n agent: string;\n device_id: string;\n ack_id?: string;\n app?: string;\n payload: HEPPayload;\n}\n\n// Event type constants\nexport const HEP_AGENT_EVENTS = [\n 'agent:session:start',\n 'agent:session:end',\n 'agent:permission: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 HEP_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] as const;\n\nexport const HEP_SYSTEM_EVENTS = [\n 'system:ack',\n 'system:error',\n 'system:heartbeat',\n] as const;\n\nexport type HEPAgentEventType = typeof HEP_AGENT_EVENTS[number];\nexport type HEPUserEventType = typeof HEP_USER_EVENTS[number];\nexport type HEPSystemEventType = typeof HEP_SYSTEM_EVENTS[number];\nexport type HEPEventType = HEPAgentEventType | HEPUserEventType | HEPSystemEventType;\n\n// Factory functions\nexport function createHEPEvent(\n type: HEPEventType,\n direction: HEPDirection,\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Omit<HEPPayload, 'data'> & { data: Record<string, unknown> }\n): HandsoffEvent {\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 },\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 → HEP (Handsoff Event Protocol)\n * 2. HEP → AgentEventEnvelope (backward compatible)\n *\n * This is the single source of truth for all Claude event transformations.\n */\n\nimport type { HandsoffEvent } from '../../../hep/types.js';\nimport { createHEPEvent } from '../../../hep/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 * Map Claude hook event to HEP event\n */\nexport function mapClaudeToHEP(\n eventType: ClaudeHookEventType,\n payload: Record<string, unknown>,\n agent: string = 'claude'\n): HandsoffEvent | null {\n const sessionId = typeof payload.session_id === 'string' ? payload.session_id : 'unknown';\n\n switch (eventType) {\n case 'SessionStart':\n return createHEPEvent(\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 createHEPEvent(\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 return createHEPEvent(\n 'agent:permission:request',\n 'agent',\n sessionId,\n agent,\n DEVICE_ID,\n {\n title: `Permission Required: ${payload.tool_name || 'Tool'}`,\n description: `${payload.tool_name || 'Tool'} ${JSON.stringify(payload.tool_input || {})}`,\n text: `Claude wants to execute ${payload.tool_name || 'a tool'}`,\n buttons: [\n { text: 'Allow', action: 'allow' },\n { text: 'Deny', action: 'deny' },\n { text: 'Always Allow', action: 'always_allow' },\n ],\n data: {\n request_id: payload.request_id || sessionId,\n tool_name: payload.tool_name || '',\n args: payload.tool_input || {},\n cwd: payload.cwd || '',\n risk_level: calculateRiskLevel(\n String(payload.tool_name || ''),\n (payload.tool_input as Record<string, unknown>) || {}\n ),\n },\n }\n );\n\n case 'PostToolUse':\n return createHEPEvent(\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 createHEPEvent(\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 createHEPEvent(\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 HEP event to AgentEventEnvelope (backward compatible)\n */\nexport function mapHEPToAgentEventEnvelope(\n hepEvent: HandsoffEvent,\n agent: string = 'claude'\n): AgentEventEnvelope | null {\n const timestamp = new Date(hepEvent.ts).toISOString();\n const baseMetadata = {\n agentType: agent as 'claude' | 'codex',\n transportType: 'hook' as const,\n sessionId: hepEvent.session_id,\n timestamp,\n rawEventType: hepTypeToRawEventType(hepEvent.type),\n };\n\n switch (hepEvent.type) {\n case 'agent:session:start':\n return {\n type: 'session:start',\n sessionId: hepEvent.session_id,\n timestamp,\n payload: { sessionId: hepEvent.session_id },\n metadata: baseMetadata,\n };\n\n case 'agent:session:end':\n return {\n type: 'session:end',\n sessionId: hepEvent.session_id,\n timestamp,\n payload: {\n sessionId: hepEvent.session_id,\n reason: hepEvent.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: hepEvent.session_id,\n timestamp,\n payload: {\n sessionId: hepEvent.session_id,\n toolName: hepEvent.payload.data.tool_name as string,\n toolInput: hepEvent.payload.data.args as Record<string, unknown>,\n requestId: hepEvent.payload.data.request_id as string,\n },\n metadata: {\n ...baseMetadata,\n permissionRequestId: hepEvent.payload.data.request_id as string,\n },\n };\n\n case 'agent:tool:end':\n return {\n type: hepEvent.payload.data.error ? 'tool:failure' : 'tool:end',\n sessionId: hepEvent.session_id,\n timestamp,\n payload: {\n sessionId: hepEvent.session_id,\n toolName: hepEvent.payload.data.tool_name as string,\n toolInput: hepEvent.payload.data.args as Record<string, unknown>,\n output: hepEvent.payload.data.output as string | undefined,\n error: hepEvent.payload.data.error as string | undefined,\n },\n metadata: baseMetadata,\n };\n\n case 'agent:turn:finished':\n return {\n type: 'finished',\n sessionId: hepEvent.session_id,\n timestamp,\n payload: {\n sessionId: hepEvent.session_id,\n reason: hepEvent.payload.data.reason as string | undefined,\n lastAssistantMessage: hepEvent.payload.data.last_assistant_message as string | undefined,\n transcriptPath: hepEvent.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 return {\n type: 'permission:request',\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 requestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n metadata: {\n ...baseMetadata,\n permissionRequestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n };\n\n case 'PermissionRequest':\n return {\n type: 'permission:request',\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 requestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\n },\n metadata: {\n ...baseMetadata,\n permissionRequestId: typeof payload.request_id === 'string' ? payload.request_id : sessionId,\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 HEP event type to raw Claude event type\n */\nfunction hepTypeToRawEventType(hepType: 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:tool:end': 'PostToolUse',\n 'agent:turn:finished': 'Stop',\n };\n return mapping[hepType] || hepType;\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): HandsoffEvent {\n return createHEPEvent(\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}","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 { SessionManager } from '../gateway/session.js';\nimport type { Gateway } from '../gateway/index.js';\nimport type { AgentHookAdapter } from '../core/agent-event.js';\n\nexport type RequestHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;\nexport type UpgradeHandler = (request: IncomingMessage, socket: import('stream').Duplex, head: Buffer) => void;\n\ninterface Route {\n method: string;\n path: string | RegExp;\n handler: RequestHandler;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * HTTP Server for the Gateway\n */\nexport class HttpServer {\n private server: Server | null = null;\n private routes: Route[] = [];\n private upgradeHandlers = new Map<string, UpgradeHandler>();\n\n constructor(private port: number) {}\n\n /**\n * Register a route handler\n */\n registerRoute(method: string, path: string | RegExp, handler: RequestHandler): void {\n this.routes.push({ method: method.toUpperCase(), path, handler });\n logger.debug(`Registered route: ${method} ${path}`);\n }\n\n /**\n * Register a WebSocket upgrade handler for a specific path\n */\n onUpgrade(path: string, handler: UpgradeHandler): void {\n this.upgradeHandlers.set(path, handler);\n logger.debug(`Registered upgrade handler: ${path}`);\n }\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 sessionManager: SessionManager,\n gateway: Gateway,\n adapter: AgentHookAdapter,\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 = sessionManager.listSessions();\n sendJson(res, 200, {\n running: true,\n sessions: sessions.map((s) => ({\n sessionId: s.id,\n agentType: s.agentType,\n startedAt: s.startedAt.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 = sessionManager.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 = sessionManager.listRegisteredAgents();\n const sessions = sessionManager.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 = sessionManager.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 sessionManager.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 PermissionQueue\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.behavior === 'string') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n // Preserve legacy PermissionRequest response format\n if (eventType === 'PermissionRequest') {\n const responseBody = JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: result.behavior,\n message: result.message,\n },\n },\n });\n logger.info({ eventType, response: responseBody }, 'Sending permission response');\n res.end(responseBody);\n } else {\n const responseBody = JSON.stringify({\n accepted: result.behavior === 'allow',\n message: result.message,\n });\n logger.info({ eventType, response: responseBody }, 'Sending permission response');\n res.end(responseBody);\n }\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 { SessionManager } from '../gateway/session.js';\nimport type { EventFrame, ResponseFrame } from '../gateway/events.js';\nimport type { PermissionQueue } from '../adapters/permissions/index.js';\nimport { ACKManager } from '../hep/ack.js';\nimport type { HandsoffEvent } from '../hep/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 HEP event with optional ACK waiting\n */\n async sendHEP(\n clientId: string,\n event: HandsoffEvent,\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 HEP ACK message\n */\n handleHEPACK(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 permissionQueue?: PermissionQueue;\n}\n\n/**\n * Setup WebSocket message handlers\n */\nexport function setupWebSocketHandlers(\n wsServer: WebSocketServer,\n sessionManager: SessionManager,\n options: WebSocketSetupOptions = {}\n): void {\n const { permissionQueue } = 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 = sessionManager.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 startedAt: s.startedAt.toISOString(),\n lastActivityAt: s.lastActivityAt.toISOString(),\n endedAt: s.endedAt?.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.handleHEPACK({\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' && permissionQueue) {\n const { requestId, allow, reason } = message as {\n requestId: string;\n allow: boolean;\n reason?: string;\n };\n\n const success = permissionQueue.decide(requestId, {\n behavior: 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' && permissionQueue) {\n const pending = permissionQueue.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 { HandsoffEvent } from './types.js';\nimport { createHEPEvent } 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: HandsoffEvent,\n status: ACKStatus,\n result?: unknown,\n error?: string\n ): HandsoffEvent {\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 createHEPEvent(\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 PermissionDecision,\n PermissionRequestResult,\n PendingPermission,\n PermissionRequestParams,\n PendingPermissionInfo,\n} from './types.js';\n\n// Logger is obtained inside functions to ensure file logging is setup\n\nexport interface PermissionQueueOptions {\n timeoutMs?: number;\n timeout_ms?: number;\n defaultOnTimeout?: 'allow' | 'deny';\n default_on_timeout?: 'allow' | 'deny';\n}\n\nexport class PermissionQueue {\n private pending = new Map<string, PendingPermission>();\n private timeout_ms: number;\n private default_on_timeout: 'allow' | 'deny';\n\n constructor(options: PermissionQueueOptions = {}) {\n this.timeout_ms = options.timeoutMs ?? options.timeout_ms ?? 300000; // 5 minutes\n this.default_on_timeout = options.defaultOnTimeout ?? options.default_on_timeout ?? 'deny';\n }\n\n request(params: PermissionRequestParams): PermissionRequestResult {\n const requestId = randomUUID();\n\n const decisionPromise = new Promise<PermissionDecision>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pending.delete(requestId);\n getLogger().info(`[Permission] Timeout: ${params.toolName} | requestId=${requestId} | default=${this.default_on_timeout} (${this.timeout_ms}ms)`);\n resolve({\n behavior: this.default_on_timeout,\n message: `Permission request timed out after ${this.timeout_ms}ms`,\n });\n }, this.timeout_ms);\n\n const pending: PendingPermission = {\n requestId,\n sessionId: params.sessionId,\n toolName: params.toolName,\n toolInput: params.toolInput,\n timestamp: Date.now(),\n timeoutId,\n resolve: (decision) => {\n clearTimeout(timeoutId);\n this.pending.delete(requestId);\n resolve(decision);\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, decisionPromise };\n }\n\n decide(requestId: string, decision: PermissionDecision): boolean {\n const pending = this.pending.get(requestId);\n if (!pending) {\n getLogger().warn(`[Permission] Decision failed: requestId=${requestId} not found or already decided`);\n return false;\n }\n const elapsed = Date.now() - pending.timestamp;\n getLogger().info(`[Permission] Decision: ${pending.toolName} | requestId=${requestId} | decision=${decision.behavior} | waited=${elapsed}ms`);\n pending.resolve(decision);\n return true;\n }\n\n get(requestId: string): PendingPermission | undefined {\n return this.pending.get(requestId);\n }\n\n listPending(): PendingPermissionInfo[] {\n const now = Date.now();\n return Array.from(this.pending.values()).map((p) => ({\n requestId: p.requestId,\n sessionId: p.sessionId,\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 getLogger().info(`[Permission] 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 PermissionRequestEvent,\n PermissionDecisionEvent,\n CommandEvent,\n SessionStartEvent,\n SessionEndEvent,\n ToolPostEvent,\n ToolFailureEvent,\n FinishedEvent,\n NotificationEvent,\n HandsoffEvent,\n HEPEvent,\n} from './events.js';\nimport type { HandsoffEvent as HEPHandsoffEvent, HEPEventType } from '../../hep/types.js';\nimport { createHEPEvent } from '../../hep/types.js';\nimport { validateHandsoffEventSafe } from '../../hep/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 HandsoffEvent>(event: T): void {\n this.logger.debug({ eventType: event.type }, 'Emitting event');\n this.emitter.emit(event.type, event);\n }\n\n /**\n * 通用事件订阅\n */\n on<T extends HandsoffEvent>(\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 * 发布权限申请事件\n */\n publishPermissionRequest(\n request: Omit<PermissionRequestEvent, 'type' | 'timestamp'>\n ): void {\n const event: PermissionRequestEvent = {\n ...request,\n type: 'permission:request',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限申请事件\n */\n onPermissionRequest(handler: EventHandler<PermissionRequestEvent>): () => void {\n return this.on('permission:request', handler);\n }\n\n /**\n * 发布权限决策事件\n */\n publishPermissionDecision(\n decision: Omit<PermissionDecisionEvent, 'type' | 'timestamp'>\n ): void {\n const event: PermissionDecisionEvent = {\n ...decision,\n type: 'permission:decision',\n timestamp: new Date(),\n };\n this.emit(event);\n }\n\n /**\n * 订阅权限决策事件\n */\n onPermissionDecision(handler: EventHandler<PermissionDecisionEvent>): () => void {\n return this.on('permission:decision', 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 /**\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: HandsoffEvent['type']): number {\n return this.emitter.listenerCount(eventType);\n }\n\n /**\n * Publish HEP event\n */\n publishHEP(event: HEPHandsoffEvent): void {\n const validation = validateHandsoffEventSafe(event);\n if (!validation.success) {\n this.logger.error('Invalid HEP event:', validation.error);\n return;\n }\n\n this.emit({\n type: 'hep:event',\n timestamp: new Date(),\n event,\n } as HEPEvent);\n }\n\n /**\n * Create and publish HEP event\n */\n emitHEP(\n type: HEPEventType,\n direction: 'agent' | 'user' | 'system',\n sessionId: string,\n agent: string,\n deviceId: string,\n payload: Parameters<typeof createHEPEvent>[5]\n ): void {\n const event = createHEPEvent(type, direction, sessionId, agent, deviceId, payload);\n this.publishHEP(event);\n }\n\n /**\n * Subscribe to HEP events\n */\n onHEP(handler: (event: HEPHandsoffEvent) => void): () => void {\n return this.on('hep:event', (evt: HEPEvent) => {\n handler(evt.event);\n });\n }\n\n /**\n * Subscribe to specific HEP event type\n */\n onHEPType(\n eventType: HEPEventType,\n handler: (event: HEPHandsoffEvent) => void\n ): () => void {\n return this.onHEP((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 HEP_VERSION = '1.0.0';\n\nexport const HEPButtonSchema = z.object({\n text: z.string(),\n action: z.string(),\n});\n\nexport const HEPPayloadSchema = z.object({\n title: z.string().optional(),\n description: z.string().optional(),\n text: z.string().optional(),\n buttons: z.array(HEPButtonSchema).optional(),\n data: z.record(z.unknown()),\n extensions: z.record(z.unknown()).optional(),\n});\n\nexport const HandsoffEventSchema = 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: HEPPayloadSchema,\n});\n\nexport type ValidatedHandsoffEvent = z.infer<typeof HandsoffEventSchema>;\n\n/**\n * Validate a HandsoffEvent. Throws ZodError if validation fails.\n * @throws {z.ZodError} When validation fails\n */\nexport function validateHandsoffEvent(data: unknown): ValidatedHandsoffEvent {\n return HandsoffEventSchema.parse(data);\n}\n\nexport function validateHandsoffEventSafe(data: unknown): { success: true; data: ValidatedHandsoffEvent } | { success: false; error: z.ZodError } {\n const result = HandsoffEventSchema.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 is 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, skipping'\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 from config');\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 'Starting all channels'\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('All channels 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 'Failed to start channel'\n );\n\n if (attempt === maxRetries) {\n this.logger.error({ channel: name }, 'Channel failed to start after all retries');\n return;\n }\n\n // 指数退避重试\n const delay = 1000 * Math.pow(2, attempt - 1);\n this.logger.debug({ channel: name, delay }, 'Retrying channel start');\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 'Stopping all channels'\n );\n\n // 停止健康检查\n this.stopHealthCheck();\n\n // 取消出站消息监听\n if (this.unsubscribeOutbound) {\n this.unsubscribeOutbound();\n this.unsubscribeOutbound = null;\n this.logger.debug('Outbound message 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 }, 'Failed to stop channel');\n }\n }\n );\n\n await Promise.all(stopPromises);\n this.logger.info('All channels 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 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\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 // 单 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 'Broadcasting message to all channels'\n );\n\n for (const [name, channel] of this.channels) {\n this.logger.debug({ channel: name, eventType }, 'Checking channel for broadcast');\n\n // Channel 自己决定是否处理\n if (!channel.shouldNotify(eventType)) {\n this.logger.debug({ channel: name, eventType }, 'Channel shouldNotify returned false, skipping');\n continue;\n }\n\n if (!channel.isRunning) {\n this.logger.debug({ channel: name }, 'Channel not running, skipping');\n continue;\n }\n\n this.logger.debug({ channel: name, eventType }, 'Sending to channel...');\n try {\n await channel.send(event);\n this.logger.debug({ channel: name, eventType }, 'Notification sent');\n } catch (error) {\n this.logger.error({ channel: name, error: error instanceof Error ? error.message : String(error) }, 'Failed to send notification');\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({ channel: channelName }, 'Message sent');\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","/**\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 (defaults subcommand to 'help')\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 = 'help';\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';\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 ).join(', ');\n return `Unknown subcommand \"${parsed.subcommand}\" for /${parsed.command}. Available: ${availableSubcommands}`;\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 { CommandContext, CommandGroup, CommandHandler } from '../types.js';\nimport { SessionScannerRegistry } from '../../../core/session-scanner/index.js';\nimport type { AgentType, SessionInfo } from '../../../core/adapter/types.js';\n\n/**\n * Format duration from milliseconds to human readable string\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) {\n return `${days}d ${hours % 24}h ${minutes % 60}m`;\n }\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m ${seconds % 60}s`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\n/**\n * List all sessions\n * Usage: /session list [--agent <type>] [--all]\n */\nconst listHandler: CommandHandler = {\n description: 'List all sessions',\n usage: '/session list [--agent <type>] [--all]',\n handler: async (args: string[], _context: CommandContext): Promise<string> => {\n // Parse arguments\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 // Call scanner to get sessions\n const registry = SessionScannerRegistry.getInstance();\n let sessions: SessionInfo[];\n\n if (agentFilter) {\n sessions = await registry.scanByAgent(agentFilter as AgentType);\n } else {\n sessions = await registry.scanAll();\n }\n\n // Filter ended sessions\n if (!includeEnded) {\n sessions = sessions.filter((s) => s.status === 'active');\n }\n\n if (sessions.length === 0) {\n const agentMsg = agentFilter ? ` for ${agentFilter}` : '';\n return includeEnded\n ? `**No sessions found${agentMsg}.**\\n\\nUse \\`/session\\` commands to manage sessions.`\n : `**No active sessions${agentMsg}.**\\n\\nUse \"/session list --all\" to see ended sessions.`;\n }\n\n // Group by agent for display\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 header = includeEnded ? '**All Sessions**\\n\\n' : '**Active Sessions**\\n\\n';\n const lines: string[] = [header];\n\n for (const [agentType, agentSessions] of byAgent) {\n lines.push(`**${agentType}** (${agentSessions.length})`);\n for (const s of agentSessions) {\n const status = s.status === 'active' ? 'active' : 'ended';\n const duration = formatDuration(s.startedAt);\n lines.push(` \\`${s.id}\\` - ${status} (${duration})`);\n }\n lines.push('');\n }\n\n return lines.join('\\n').trim();\n },\n};\n\n/**\n * Get detailed status of a specific session\n * Usage: /session status <session-id>\n */\nconst statusHandler: CommandHandler = {\n description: 'Get detailed status of a specific session',\n usage: '/session status <session-id>',\n handler: async (args: string[], _context: CommandContext): Promise<string> => {\n const sessionId = args[0];\n\n if (!sessionId) {\n return '**Error:** Session ID is required.\\n\\nUsage: `/session status <session-id>`';\n }\n\n // Search in all registered scanners\n const registry = SessionScannerRegistry.getInstance();\n const allSessions = await registry.scanAll();\n const session = allSessions.find((s) => s.id === sessionId);\n\n if (!session) {\n return `**Error:** Session \\`${sessionId}\\` not found.\\n\\nUse \\`/session list --all\\` to see all sessions.`;\n }\n\n const status = session.status === 'active' ? 'Active' : 'Ended';\n const duration = formatDuration(session.startedAt);\n\n let output = `**Session Status: \\`${session.id}\\`**\\n\\n`;\n output += `**Agent Type:** ${session.agentType}\\n`;\n output += `**Transport:** ${session.transportType}\\n`;\n output += `**Status:** ${status}\\n`;\n output += `**Duration:** ${duration}\\n`;\n output += `**Started:** ${session.startedAt.toISOString()}\\n`;\n\n if (session.cwd) {\n output += `**Work Directory:** \\`${session.cwd}\\`\\n`;\n }\n\n return output;\n },\n};\n\n/**\n * Get session statistics\n * Usage: /session count\n */\nconst countHandler: CommandHandler = {\n description: 'Get session statistics',\n usage: '/session count',\n handler: async (_args: string[], context: CommandContext): Promise<string> => {\n const allSessions = context.sessionManager.listSessions({ includeEnded: true });\n const activeSessions = allSessions.filter((s) => !s.isEnded());\n const endedSessions = allSessions.filter((s) => s.isEnded());\n\n let output = '**Session Statistics**\\n\\n';\n output += `**Active:** ${activeSessions.length}\\n`;\n output += `**Ended:** ${endedSessions.length}\\n`;\n output += `**Total:** ${allSessions.length}\\n\\n`;\n\n // Group by agent type\n const byAgentType = new Map<string, { active: number; ended: number }>();\n for (const session of allSessions) {\n const current = byAgentType.get(session.agentType) ?? { active: 0, ended: 0 };\n if (session.isEnded()) {\n current.ended++;\n } else {\n current.active++;\n }\n byAgentType.set(session.agentType, current);\n }\n\n if (byAgentType.size > 0) {\n output += '**By Agent Type:**\\n';\n for (const [agentType, counts] of byAgentType) {\n output += `- **${agentType}**: ${counts.active} active, ${counts.ended} ended\\n`;\n }\n }\n\n return output;\n },\n};\n\n/**\n * Session command group\n */\nexport const sessionCommands: CommandGroup = {\n list: listHandler,\n status: statusHandler,\n count: countHandler,\n};\n\n/**\n * Register session commands to the registry\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 { CommandContext, CommandGroup, CommandHandler } from '../types.js';\nimport process from 'process';\nimport os from 'os';\n\n// Track system start time\nconst systemStartTime = Date.now();\n\n/**\n * Format bytes to human readable string\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\n/**\n * Format milliseconds to human readable duration\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\n if (days > 0) {\n parts.push(`${days}d`);\n }\n if (hours > 0) {\n parts.push(`${hours % 24}h`);\n }\n if (minutes > 0) {\n parts.push(`${minutes % 60}m`);\n }\n if (seconds > 0 || parts.length === 0) {\n parts.push(`${seconds % 60}s`);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Get system status\n * Usage: /system status\n */\nconst statusHandler: CommandHandler = {\n description: 'Get system status',\n usage: '/system status',\n handler: async (): Promise<string> => {\n const uptime = Date.now() - systemStartTime;\n const memoryUsage = process.memoryUsage();\n\n let output = '**System Status**\\n\\n';\n\n // Uptime\n output += `**Uptime:** ${formatDuration(uptime)}\\n`;\n\n // Memory usage\n output += '\\n**Memory Usage:**\\n';\n output += `- **RSS:** ${formatBytes(memoryUsage.rss)}\\n`;\n output += `- **Heap Used:** ${formatBytes(memoryUsage.heapUsed)}\\n`;\n output += `- **Heap Total:** ${formatBytes(memoryUsage.heapTotal)}\\n`;\n output += `- **External:** ${formatBytes(memoryUsage.external)}\\n`;\n\n // System memory\n const totalMem = os.totalmem();\n const freeMem = os.freemem();\n const usedMem = totalMem - freeMem;\n const memPercent = ((usedMem / totalMem) * 100).toFixed(1);\n\n output += '\\n**System Memory:**\\n';\n output += `- **Total:** ${formatBytes(totalMem)}\\n`;\n output += `- **Used:** ${formatBytes(usedMem)} (${memPercent}%)\\n`;\n output += `- **Free:** ${formatBytes(freeMem)}\\n`;\n\n // Runtime info\n output += '\\n**Runtime:**\\n';\n output += `- **Node.js:** ${process.version}\\n`;\n output += `- **Platform:** ${process.platform}\\n`;\n output += `- **Architecture:** ${process.arch}\\n`;\n\n // CPU info\n const cpus = os.cpus();\n output += '\\n**CPU:**\\n';\n output += `- **Model:** ${cpus[0]?.model ?? 'Unknown'}\\n`;\n output += `- **Cores:** ${cpus.length}\\n`;\n output += `- **Load Average:** ${os.loadavg().map((l) => l.toFixed(2)).join(', ')}\\n`;\n\n return output;\n },\n};\n\n/**\n * Ping the system\n * Usage: /system ping\n */\nconst pingHandler: CommandHandler = {\n description: 'Check if system is alive',\n usage: '/system ping',\n handler: async (): Promise<string> => {\n return '**Pong!** 🏓\\n\\nSystem is running and responsive.';\n },\n};\n\n/**\n * System command group\n */\nexport const systemCommands: CommandGroup = {\n status: statusHandler,\n ping: pingHandler,\n};\n\n/**\n * Register system commands to the registry\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 { CommandContext, CommandHandler } from '../types.js';\nimport { CommandRegistry } from '../index.js';\n\n/**\n * Generate help text for all available commands\n */\nfunction generateHelpText(registry: CommandRegistry): string {\n const commands = registry.list();\n const groups = registry.getGroups();\n\n if (commands.length === 0) {\n return '**No commands available.**\\n\\nThe command registry is empty.';\n }\n\n let output = '**Handsoff Bot Commands**\\n\\n';\n output += 'Use `/help` to see this message.\\n';\n output += 'Use `/<group> <subcommand>` to execute a command.\\n\\n';\n\n // Group commands by their group name\n const grouped = new Map<string, Array<{ subcommand: string; description: string; usage?: string }>>();\n\n for (const cmd of commands) {\n const list = grouped.get(cmd.group) ?? [];\n list.push({\n subcommand: cmd.subcommand,\n description: cmd.description,\n usage: cmd.usage,\n });\n grouped.set(cmd.group, list);\n }\n\n // Output each group\n for (const group of groups.sort()) {\n const subcommands = grouped.get(group);\n if (!subcommands || subcommands.length === 0) continue;\n\n output += `**/${group}**\\n`;\n\n for (const cmd of subcommands.sort((a, b) => a.subcommand.localeCompare(b.subcommand))) {\n output += ` \\`${cmd.subcommand}\\` - ${cmd.description}\\n`;\n }\n\n output += '\\n';\n }\n\n // Usage tips\n output += '**Usage Tips:**\\n';\n output += '- Commands start with `/`\\n';\n output += '- Use `/help` anytime to see available commands\\n';\n output += '- Use `/<group> help` for group-specific help\\n';\n output += '- Alternative syntax: `/<group>:<subcommand>`\\n';\n\n return output;\n}\n\n/**\n * Help command handler\n * Usage: /help\n */\nexport const helpCommand: CommandHandler = {\n description: 'Show available commands and usage help',\n usage: '/help',\n handler: async (_args: string[], context: CommandContext): Promise<string> => {\n // Access the registry through the context\n // We need to get the registry from the executor or use a global reference\n // For now, we'll generate a static help message\n\n return generateStaticHelpText();\n },\n};\n\n/**\n * Generate static help text (fallback when registry is not directly accessible)\n */\nfunction generateStaticHelpText(): string {\n let output = '**Handsoff Bot Commands**\\n\\n';\n\n // Start command\n output += '**/start** - Show welcome message\\n\\n';\n\n // Session commands\n output += '**/session** - Session management\\n';\n output += ' `list` [--all] - List all sessions\\n';\n output += ' `status` <session-id> - Get session details\\n';\n output += ' `count` - Get session statistics\\n\\n';\n\n // System commands\n output += '**/system** - System information\\n';\n output += ' `status` - Get system status\\n';\n output += ' `ping` - Check if system is alive\\n\\n';\n\n // Help command\n output += '**/help** - Show this help message\\n\\n';\n\n // Usage tips\n output += '**Usage Tips:**\\n';\n output += '- Commands start with `/`\\n';\n output += '- Use `/help` anytime to see available commands\\n';\n output += '- Use `/<group> help` for group-specific help\\n';\n output += '- Alternative syntax: `/<group>:<subcommand>`\\n';\n\n return output;\n}\n\n/**\n * Register help command to the registry\n */\nexport function registerHelpCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('help', 'help', helpCommand);\n}\n","import { CommandHandler } from '../types.js';\n\n/**\n * Start command handler - Welcome message for new users\n * Usage: /start\n */\nexport const startCommand: CommandHandler = {\n description: 'Start the bot and show welcome message',\n usage: '/start',\n handler: async (): Promise<string> => {\n return `👋 **Welcome to Handsoff!**\n\nI'm your Claude Code monitoring assistant. I'll notify you about:\n- 🔐 Permission requests that need your approval\n- ✅ Task completions\n- 🟢 Session starts\n- ❌ Errors\n\n**Available Commands:**\n/help - Show all available commands\n/session list - List active sessions\n/system status - Check system status\n/system ping - Test connectivity\n\nUse the buttons on notifications to approve or deny permission requests.`;\n },\n};\n\n/**\n * Register start command to the registry\n */\nexport function registerStartCommand(\n registerFn: (group: string, subcommand: string, handler: CommandHandler) => void\n): void {\n registerFn('start', 'start', startCommand);\n}\n","import { CommandRegistry } from '../index.js';\nimport { CommandHandler } from '../types.js';\nimport { sessionCommands, registerSessionCommands } from './session.js';\nimport { systemCommands, registerSystemCommands } from './system.js';\nimport { helpCommand, registerHelpCommand } from './help.js';\nimport { startCommand, registerStartCommand } from './start.js';\n\nexport { sessionCommands, registerSessionCommands } from './session.js';\nexport { systemCommands, registerSystemCommands } from './system.js';\nexport { helpCommand, registerHelpCommand } from './help.js';\nexport { startCommand, registerStartCommand } from './start.js';\n\n/**\n * Register all builtin commands to the registry\n * @param registry - The command registry to register commands to\n */\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n // Register start command (welcome message)\n registry.register('start', 'start', startCommand);\n\n // Register session commands\n registry.registerGroup('session', sessionCommands);\n\n // Register system commands\n registry.registerGroup('system', systemCommands);\n\n // Register help command (as a single command in 'help' group)\n registry.register('help', 'help', helpCommand);\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 { SessionManager } from '../session.js';\nimport {\n registerBuiltinCommands,\n commandRegistry,\n CommandExecutor,\n} from '../../core/command/index.js';\nimport { InboundMessage } from '../../core/bus/events.js';\n\n/**\n * Setup command handler to process /commands from channels\n * @param bus - EventBus instance\n * @param sessionManager - Session manager for command context\n * @param logger - Logger instance\n * @returns Cleanup function to remove event listeners\n */\nexport function setupCommandHandler(\n bus: EventBus,\n sessionManager: SessionManager,\n logger: Logger\n): () => void {\n // Register all builtin commands\n registerBuiltinCommands(commandRegistry);\n logger.debug('Builtin commands registered');\n\n // Create command executor\n const executor = new CommandExecutor(commandRegistry, logger);\n\n // Subscribe to inbound messages\n const unsubscribe = bus.onInbound(async (message: InboundMessage) => {\n const { text, chatId, messageId } = message;\n\n // Check if message is a command\n if (!executor.isCommand(text)) {\n return;\n }\n\n logger.debug(\n { chatId, messageId, text: text.slice(0, 50) },\n 'Processing command'\n );\n\n // Create command context\n const context = {\n source: message,\n bus,\n sessionManager,\n };\n\n // Execute command\n const result = await executor.execute(text, context);\n\n // Send response back to channel if there's a result\n if (result !== null) {\n bus.publishOutbound({\n channel: message.channel, // Response goes back to the same channel\n chatId,\n text: result,\n replyToMessageId: messageId,\n });\n\n logger.debug(\n { chatId, messageId },\n 'Command response sent'\n );\n }\n });\n\n logger.debug('Command handler setup complete');\n\n // Return cleanup function\n return unsubscribe;\n}\n","import type { Logger } from 'pino';\nimport { EventBus } from '../../core/bus/index.js';\nimport { PermissionQueue } from '../../adapters/permissions/queue.js';\nimport { PermissionDecisionEvent } from '../../core/bus/events.js';\n\n/**\n * Setup permission handler to route decisions to PermissionQueue\n * @param bus - EventBus instance\n * @param permissionQueue - Permission 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 permissionQueue: PermissionQueue,\n logger: Logger\n): () => void {\n // Subscribe to permission decision events\n const unsubscribe = bus.onPermissionDecision((event: PermissionDecisionEvent) => {\n const { requestId, decision, reason } = event;\n\n logger.debug(\n { requestId, decision, reason },\n 'Processing permission decision'\n );\n\n // Convert decision to PermissionDecision format and apply\n const success = permissionQueue.decide(requestId, {\n behavior: decision === 'always_allow' ? 'allow' : decision,\n message: reason,\n });\n\n if (success) {\n logger.debug(\n { requestId, decision },\n 'Permission decision applied'\n );\n } else {\n logger.warn(\n { requestId },\n 'Permission decision failed: request not found or already decided'\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 '../session.js';\nimport type { PermissionQueue } from '../../adapters/permissions/index.js';\n\n/**\n * Setup all gateway handlers\n */\nexport function setupAllHandlers(\n bus: EventBus,\n sessionManager: SessionManager,\n permissionQueue: PermissionQueue,\n logger: Logger\n): () => void {\n const cleanupFns: Array<() => void> = [];\n\n cleanupFns.push(setupCommandHandler(bus, sessionManager, logger));\n cleanupFns.push(setupPermissionHandler(bus, permissionQueue, 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 type {\n SessionStartEvent,\n SessionEndEvent,\n PermissionRequestEvent,\n FinishedEvent,\n OutboundMessage,\n ToolFailureEvent,\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\n constructor(\n private bus: EventBus,\n private logger: Logger,\n private provider?: SessionContextProvider\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.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.onPermissionRequest(this.handlePermissionRequest.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\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 await this.publishContext({\n eventType: 'session_start',\n sessionId: event.sessionId,\n userId: event.userId,\n });\n }\n\n private async handleSessionEnd(event: SessionEndEvent): Promise<void> {\n await this.publishContext({\n eventType: 'session_end',\n sessionId: event.sessionId,\n userId: event.userId,\n reason: event.reason,\n });\n }\n\n private async handlePermissionRequest(event: PermissionRequestEvent): Promise<void> {\n await this.publishContext({\n eventType: 'permission_request',\n sessionId: event.sessionId,\n requestId: event.requestId,\n toolName: event.toolName,\n toolInput: event.args,\n cwd: event.cwd,\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 lastAssistantMessage: event.lastAssistantMessage,\n summary,\n });\n }\n\n private async publishContext(ctx: NotificationContext): Promise<void> {\n await this.publishNotification(ctx);\n }\n\n /**\n * 发布通知到所有 Channel\n *\n * 注意:Channel 自己会检查 shouldNotify() 决定是否处理\n * 现在广播原始 NotificationContext,各 Channel 自行格式化\n */\n private async publishNotification(context: NotificationContext): Promise<void> {\n this.logger.debug({ eventType: context.eventType }, 'Publishing notification');\n\n const message: OutboundMessage = {\n type: 'outbound:message',\n timestamp: new Date(),\n channel: 'broadcast', // 广播到所有 Channel\n chatId: 'broadcast',\n context, // 广播原始上下文\n metadata: { eventType: context.eventType },\n };\n\n await this.bus.publishOutbound(message);\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 /**\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 { channel: this.name, chatId, senderId: sender.id },\n 'Receiving message and forwarding to bus'\n );\n\n // 转发到 EventBus\n this.bus.publishInbound({\n channel: this.name,\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 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 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, '&').replace(/</g, '<').replace(/>/g, '>');\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 * 根据 NotificationContext 格式化消息\n * @param ctx - 通知上下文\n * @returns 格式化后的消息文本 (HTML)\n */\n format(ctx: NotificationContext): string {\n let result = '';\n switch (ctx.eventType) {\n case 'session_start':\n result = this._formatSessionStart(ctx);\n break;\n case 'session_end':\n result = this._formatSessionEnd(ctx);\n break;\n case 'permission_request':\n result = this._formatPermissionRequest(ctx);\n break;\n case 'tool_failure':\n result = this._formatToolFailure(ctx);\n break;\n case 'finished':\n result = this._formatFinished(ctx);\n break;\n default:\n result = '';\n }\n return this.truncate(result);\n }\n\n /**\n * 格式化 Session 开始消息\n */\n private _formatSessionStart(ctx: NotificationContext): string {\n const lines = [\n '🟢 <b>Session Started</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(ctx.sessionId)}`,\n ];\n if (ctx.userId) {\n lines.push(`<b>User ID:</b> ${this.inlineCode(ctx.userId.slice(0, 16))}`);\n }\n return lines.join('\\n');\n }\n\n /**\n * 格式化 Session 结束消息\n */\n private _formatSessionEnd(ctx: NotificationContext): string {\n const lines = [\n '🔴 <b>Session Ended</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(ctx.sessionId)}`,\n ];\n if (ctx.reason) {\n lines.push(`<b>Reason:</b> ${this.escape(ctx.reason)}`);\n }\n if (ctx.userId) {\n lines.push(`<b>User ID:</b> ${this.inlineCode(ctx.userId.slice(0, 16))}`);\n }\n return lines.join('\\n');\n }\n\n /**\n * 格式化权限申请消息\n */\n private _formatPermissionRequest(ctx: NotificationContext): string {\n const lines = [\n '🔐 <b>Permission Request</b>',\n '',\n `<b>Request ID:</b> ${this.inlineCode(ctx.requestId ?? '')}`,\n `<b>Tool:</b> ${this.escape(ctx.toolName ?? '')}`,\n ];\n if (ctx.cwd) {\n lines.push(`<b>Working Dir:</b> ${this.inlineCode(ctx.cwd)}`);\n }\n if (ctx.toolInput && Object.keys(ctx.toolInput).length > 0) {\n lines.push(\n '',\n '<b>Args:</b>',\n this.code(JSON.stringify(ctx.toolInput, null, 2), 'json')\n );\n }\n return lines.join('\\n');\n }\n\n /**\n * 格式化工具失败消息\n */\n private _formatToolFailure(ctx: NotificationContext): string {\n const lines = [\n '⚠️ <b>Tool Failed</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(ctx.sessionId)}`,\n ];\n if (ctx.toolName) lines.push(`<b>Tool:</b> ${this.escape(ctx.toolName)}`);\n if (ctx.reason) lines.push(`<b>Error:</b> ${this.escape(ctx.reason)}`);\n return lines.join('\\n');\n }\n\n /**\n * 格式化任务完成消息\n */\n private _formatFinished(ctx: NotificationContext): string {\n const lines = [\n '🏁 <b>Task Finished</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(ctx.sessionId)}`,\n ];\n\n if (ctx.summary?.durationMs !== undefined) {\n const seconds = (ctx.summary.durationMs / 1000).toFixed(1);\n lines.push(`<b>Duration:</b> ${this.escape(seconds)}s`);\n }\n\n if (\n ctx.summary?.inputTokens !== undefined &&\n ctx.summary?.outputTokens !== undefined\n ) {\n const input = ctx.summary?.inputTokens ?? 0;\n const output = ctx.summary?.outputTokens ?? 0;\n lines.push(`<b>Tokens:</b> in ${input} / out ${output}`);\n }\n\n const message =\n ctx.summary?.lastAssistantMessage ??\n ctx.lastAssistantMessage ??\n '任务结束(无回复内容)';\n\n lines.push('', '<b>Result:</b>', this.escape(message));\n\n return lines.join('\\n');\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(event: {\n requestId: string;\n toolName: string;\n chatId: string;\n args: Record<string, unknown>;\n }): string {\n const lines = [\n '🔐 <b>Permission Request</b>',\n '',\n `<b>Request ID:</b> ${this.inlineCode(event.requestId)}`,\n `<b>Tool:</b> ${this.escape(event.toolName)}`,\n `<b>Chat ID:</b> ${this.inlineCode(event.chatId)}`,\n '',\n '<b>Arguments:</b>',\n this.code(JSON.stringify(event.args, null, 2), 'json'),\n ];\n return lines.join('\\n');\n }\n\n /**\n * 格式化 Session 开始消息(兼容保留)\n */\n formatSessionStart(sessionId: string, agentType?: string): string {\n const lines = [\n '🟢 <b>Session Started</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(sessionId)}`,\n ];\n if (agentType) {\n lines.push(`<b>Agent:</b> ${this.escape(agentType)}`);\n }\n return lines.join('\\n');\n }\n\n /**\n * 格式化 Session 结束消息(兼容保留)\n */\n formatSessionEnd(sessionId: string, reason?: string): string {\n const lines = [\n '🔴 <b>Session Ended</b>',\n '',\n `<b>Session ID:</b> ${this.inlineCode(sessionId)}`,\n ];\n if (reason) {\n lines.push(`<b>Reason:</b> ${this.escape(reason)}`);\n }\n return lines.join('\\n');\n }\n\n /**\n * 格式化通知消息\n * @param title - 通知标题\n * @param message - 通知内容\n * @param level - 通知级别\n * @returns 格式化后的消息文本\n */\n formatNotification(title: string, message: string, level: 'info' | 'warn' | 'error' | 'success'): string {\n const icons = {\n info: 'ℹ️',\n warn: '⚠️',\n error: '❌',\n success: '✅',\n };\n const icon = icons[level];\n return `${icon} <b>${this.escape(title)}</b>\\n\\n${this.escape(message)}`;\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 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, PermissionRequestEvent, PermissionDecisionEvent } 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';\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 formatter: TelegramFormatter;\n private allowedUsers: Set<string>;\n private pendingRequests: Map<string, Map<string, number>> = new Map();\n private unsubscribePermissionRequest?: () => void;\n private unsubscribePermissionDecision?: () => 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 const telegramConfig = config as TelegramChannelConfig;\n if (!telegramConfig.bot_token) {\n throw new Error('TelegramChannel requires bot_token in config');\n }\n\n this.bot = new TelegramBot(telegramConfig.bot_token, logger);\n this.formatter = new TelegramFormatter();\n this.allowedUsers = new Set(telegramConfig.allowed_users || []);\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\n // 启动 Bot\n await this.bot.start();\n\n // 上报连接状态\n this.updateConnectionState('connected');\n\n // 订阅权限申请事件\n this.unsubscribePermissionRequest = this.bus.onPermissionRequest(\n this.handlePermissionRequest.bind(this)\n );\n\n // 订阅权限决策事件\n this.unsubscribePermissionDecision = this.bus.onPermissionDecision(\n this.handlePermissionDecision.bind(this)\n );\n\n this.logger.info({ channel: this.name }, 'Telegram channel started');\n }\n\n /**\n * 停止 Channel\n * 停止 Bot 并取消事件订阅\n */\n async stop(): Promise<void> {\n // 取消事件订阅\n this.unsubscribePermissionRequest?.();\n this.unsubscribePermissionDecision?.();\n\n // 停止 Bot\n await this.bot.stop();\n\n // 清理未决请求,避免内存泄漏\n this.pendingRequests.clear();\n\n // 上报连接状态\n this.updateConnectionState('disconnected');\n\n await super.stop();\n this.logger.info({ channel: this.name }, 'Telegram channel stopped');\n }\n\n /**\n * 发送消息给所有允许的用户\n * @param message - 出站消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission requests - we handle these directly via onPermissionRequest\n if (message.metadata?.eventType === 'permission_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 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 for (const userId of this.allowedUsers) {\n if (userId === '*') continue;\n\n try {\n await this.bot.sendMessage(userId, text, {\n parseMode: 'HTML',\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n });\n } catch (error) {\n this.logger.warn({ userId, error, eventType: message.metadata?.eventType, textLength: text.length }, 'Failed to send HTML message to user, falling back to plain text');\n try {\n await this.bot.sendMessage(userId, TelegramFormatter.stripHtml(text), {\n replyToMessageId: message.replyToMessageId\n ? parseInt(message.replyToMessageId, 10)\n : undefined,\n });\n } catch (fallbackError) {\n this.logger.warn({ userId, error: fallbackError }, 'Failed to send plain text message to user');\n }\n }\n }\n }\n\n /**\n * 发送带按钮的消息\n * @param message - 出站消息\n * @param buttons - 按钮二维数组\n */\n async sendWithButtons(message: OutboundMessage, buttons: Button[][]): Promise<void> {\n // Skip broadcast permission requests - we handle these directly via onPermissionRequest\n if (message.metadata?.eventType === 'permission_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 isPermissionRequest = buttons.some((row) =>\n row.some((btn) => btn.data.startsWith('allow:') || btn.data.startsWith('deny:'))\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({ userId, error, eventType: message.metadata?.eventType, textLength: text.length }, 'Failed to send HTML message with buttons to user, falling back to plain text');\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({ userId, error: fallbackError }, 'Failed to send plain text message with buttons to user');\n }\n }\n\n if (messageId !== undefined) {\n sentMessageIds.set(userId, messageId);\n }\n }\n\n // 跟踪权限申请相关的消息 ID(用于后续移除按钮)\n if (isPermissionRequest) {\n for (const row of buttons) {\n for (const btn of row) {\n if (btn.data.startsWith('allow:') || btn.data.startsWith('deny:')) {\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 handlePermissionRequest(event: PermissionRequestEvent): Promise<void> {\n if (!this.shouldNotify('permission_request')) {\n return;\n }\n\n this.logger.debug(\n { requestId: event.requestId, toolName: event.toolName },\n 'Handling permission request'\n );\n\n const text = this.formatter.formatPermissionRequest(event);\n const buttons: Button[][] = [\n [\n { text: '✅ Allow', data: `allow:${event.requestId}` },\n { text: '❌ Deny', data: `deny:${event.requestId}` },\n ],\n ];\n\n // 创建出站消息\n const outboundMessage: OutboundMessage = {\n type: 'outbound:message',\n channel: this.name,\n chatId: event.chatId,\n text,\n timestamp: new Date(),\n };\n\n await this.sendWithButtons(outboundMessage, buttons);\n }\n\n /**\n * 处理权限决策事件\n * @param event - 权限决策事件\n */\n private async handlePermissionDecision(event: PermissionDecisionEvent): 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 permission buttons'\n );\n }\n }\n }\n // 清理已处理的请求记录\n this.pendingRequests.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 requestId = data.slice(colonIndex + 1);\n\n if (!requestId || !['allow', 'deny', 'always_allow'].includes(action)) {\n await ctx.answerCallbackQuery({ text: 'Invalid action' });\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 // 发布权限决策事件\n this.bus.publishPermissionDecision({\n requestId,\n decision: action as 'allow' | 'deny' | 'always_allow',\n reason: `User clicked ${action} button 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 // 忽略失败,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, action, userId }, 'Permission decided via Telegram');\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.debug({ userId, username, text }, 'Received text message');\n\n // 检查用户权限\n if (!this.isAllowed(userId)) {\n this.logger.warn({ userId }, 'Message from unauthorized user ignored');\n await ctx.reply('⛔ You are not authorized to use this bot.');\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 * 注册消息处理器\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';\nimport { getLogger } from '../../../shared/logger.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 = getLogger().child({ channel: '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 onDebug?: (message: string) => void;\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 }\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 return;\n }\n\n this.isRunning = true;\n this.messageHandler = messageHandler;\n this.cardActionHandler = cardActionHandler || null;\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 await this.messageHandler?.(data);\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.warn,\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.onStateChange?.('connected');\n })\n .catch((error: Error) => {\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 };\n\n await this.cardActionHandler(cardAction);\n } catch (error) {\n this.options.onDebug?.(`handleCardAction error: ${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 { NotificationContext } from '../../../gateway/notification-context.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 static 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 * 直接从 NotificationContext 生成飞书 PostContent\n * 无 HTML 中间层,直接构建 Post 格式\n */\n static formatContext(context: NotificationContext): PostContent {\n const paragraphs: PostElement[][] = [];\n\n switch (context.eventType) {\n case 'permission_request':\n paragraphs.push([\n { tag: 'text', text: '🔐 ' },\n { tag: 'text', text: 'Permission Request', style: ['bold'] }\n ]);\n paragraphs.push([]);\n\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n\n if (context.toolName) {\n paragraphs.push([\n { tag: 'text', text: 'Tool: ', style: ['bold'] },\n { tag: 'text', text: context.toolName }\n ]);\n }\n\n if (context.cwd) {\n paragraphs.push([\n { tag: 'text', text: 'Working Dir: ', style: ['bold'] },\n { tag: 'text', text: context.cwd }\n ]);\n }\n\n if (context.toolInput && Object.keys(context.toolInput).length > 0) {\n paragraphs.push([]);\n paragraphs.push([{ tag: 'text', text: 'Args:', style: ['bold'] }]);\n paragraphs.push([{\n tag: 'text',\n text: JSON.stringify(context.toolInput, null, 2)\n }]);\n }\n break;\n\n case 'finished':\n // 标题行:✅ Task Completed\n paragraphs.push([\n { tag: 'text', text: '✅ ' },\n { tag: 'text', text: 'Task Completed', style: ['bold'] }\n ]);\n paragraphs.push([]); // 空行\n\n // Session ID\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n\n // Duration\n if (context.summary?.durationMs !== undefined) {\n const seconds = (context.summary.durationMs / 1000).toFixed(1);\n paragraphs.push([\n { tag: 'text', text: 'Duration: ', style: ['bold'] },\n { tag: 'text', text: `${seconds}s` }\n ]);\n }\n\n // Tokens\n if (context.summary?.inputTokens !== undefined && context.summary?.outputTokens !== undefined) {\n paragraphs.push([\n { tag: 'text', text: 'Tokens: ', style: ['bold'] },\n { tag: 'text', text: `in ${context.summary.inputTokens} / out ${context.summary.outputTokens}` }\n ]);\n }\n\n // Result\n {\n const message = context.summary?.lastAssistantMessage ?? context.lastAssistantMessage;\n if (message) {\n paragraphs.push([]); // 空行\n paragraphs.push([{ tag: 'text', text: 'Result:', style: ['bold'] }]);\n paragraphs.push([{ tag: 'text', text: message }]);\n }\n }\n break;\n\n case 'session_start':\n paragraphs.push([\n { tag: 'text', text: '🟢 ' },\n { tag: 'text', text: 'Session Started', style: ['bold'] }\n ]);\n paragraphs.push([]);\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n if (context.userId) {\n paragraphs.push([\n { tag: 'text', text: 'User: ', style: ['bold'] },\n { tag: 'text', text: context.userId.slice(0, 16) }\n ]);\n }\n break;\n\n case 'session_end':\n paragraphs.push([\n { tag: 'text', text: '🔴 ' },\n { tag: 'text', text: 'Session Ended', style: ['bold'] }\n ]);\n paragraphs.push([]);\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n if (context.reason) {\n paragraphs.push([\n { tag: 'text', text: 'Reason: ', style: ['bold'] },\n { tag: 'text', text: context.reason }\n ]);\n }\n break;\n\n case 'tool_failure':\n paragraphs.push([\n { tag: 'text', text: '⚠️ ' },\n { tag: 'text', text: 'Tool Failed', style: ['bold'] }\n ]);\n paragraphs.push([]);\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n if (context.toolName) {\n paragraphs.push([\n { tag: 'text', text: 'Tool: ', style: ['bold'] },\n { tag: 'text', text: context.toolName }\n ]);\n }\n if (context.reason) {\n paragraphs.push([\n { tag: 'text', text: 'Error: ', style: ['bold'] },\n { tag: 'text', text: context.reason }\n ]);\n }\n break;\n\n default:\n paragraphs.push([\n { tag: 'text', text: `Event: ${(context as NotificationContext).eventType}`, style: ['bold'] }\n ]);\n paragraphs.push([\n { tag: 'text', text: 'Session: ', style: ['bold'] },\n { tag: 'text', text: context.sessionId }\n ]);\n }\n\n return { zh_cn: { content: paragraphs } };\n }\n\n /**\n * 将 HTML 标签规范化,提取纯文本和格式信息\n * 飞书 post 格式不支持 HTML,需要转换\n */\n private static 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 static 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 static 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 static 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, PermissionRequestEvent, PermissionDecisionEvent } 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';\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 /** 群聊策略:open=允许所有,mention=仅响应@提及 */\n group_policy?: 'open' | 'mention';\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 unsubscribePermissionRequest?: () => void;\n private unsubscribePermissionDecision?: () => void;\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, groupPolicy: this.feishuConfig.group_policy },\n 'FeishuChannel initialized'\n );\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 group_policy: 'mention',\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 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.unsubscribePermissionRequest = this.bus.onPermissionRequest(\n this.handlePermissionRequest.bind(this)\n );\n\n this.unsubscribePermissionDecision = this.bus.onPermissionDecision(\n this.handlePermissionDecision.bind(this)\n );\n\n this.logger.info('Feishu channel started');\n }\n\n /**\n * 停止 Channel\n */\n async stop(): Promise<void> {\n this.unsubscribePermissionRequest?.();\n this.unsubscribePermissionDecision?.();\n this.pendingRequests.clear();\n this.client?.stopWebSocket();\n await super.stop();\n this.logger.info('Feishu channel stopped');\n }\n\n /**\n * 格式化通知上下文为飞书 PostContent\n * 覆写 BaseChannel.format() 以支持富文本格式\n */\n format(context: NotificationContext): PostContent {\n return FeishuFormatter.formatContext(context);\n }\n\n /**\n * 发送消息\n */\n async send(message: OutboundMessage): Promise<void> {\n // Skip broadcast permission requests - handled via onPermissionRequest\n if (message.metadata?.eventType === 'permission_request' && message.chatId === 'broadcast') {\n return;\n }\n\n if (!this.client) {\n throw new Error('Feishu client not initialized');\n }\n\n const content = message.context \n ? this.formatContextToMarkdown(message.context)\n : message.text;\n\n if (!content) {\n this.logger.warn('No content to send in Feishu message');\n return;\n }\n\n const title = message.context ? this.getTitleForContext(message.context) : 'Notification';\n const cardContent = FeishuFormatter.formatCard({ title, content, buttons: [] });\n\n await this.broadcastCard(cardContent);\n }\n\n /**\n * 广播卡片消息到所有目标用户\n */\n private async broadcastCard(cardContent: string): Promise<void> {\n const targetUsers = this.feishuConfig.allowed_users || [];\n if (targetUsers.length === 0) {\n this.logger.warn('No allowed_users configured for Feishu channel');\n return;\n }\n\n await Promise.allSettled(\n targetUsers\n .filter((userId) => userId !== '*')\n .map(async (userId) => {\n const receiveIdType = userId.startsWith('oc_') ? 'chat_id' : 'open_id';\n await this.client!.sendCard(userId, receiveIdType, cardContent);\n })\n );\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 }\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 return null;\n }\n\n const content = this.extractContent(message);\n if (!content) {\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.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 * 处理权限申请事件\n */\n private async handlePermissionRequest(event: PermissionRequestEvent): Promise<void> {\n if (!this.shouldNotify('permission_request')) {\n return;\n }\n\n const content = this.formatPermissionRequestContent(event);\n const buttons: CardButton[] = [\n {\n text: '✅ Allow',\n type: 'primary_filled',\n callbackValue: { action: 'agree', requestId: event.requestId },\n },\n {\n text: '❌ Deny',\n type: 'default',\n callbackValue: { action: 'reject', requestId: event.requestId },\n },\n ];\n\n const cardContent = FeishuFormatter.formatCard({\n title: 'Permission Request',\n content,\n buttons,\n });\n\n const targetUsers = this.feishuConfig.allowed_users || [];\n const validUsers = targetUsers.filter((id) => id !== '*');\n\n if (validUsers.length > 0) {\n const results = await Promise.allSettled(\n validUsers.map(async (userId) => {\n const receiveIdType = userId.startsWith('oc_') ? 'chat_id' : 'open_id';\n return this.client!.sendCard(userId, receiveIdType, cardContent);\n })\n );\n\n // Track which users received the permission request\n const sentUsers = new Set<string>();\n results.forEach((result, index) => {\n if (result.status === 'fulfilled' && result.value) {\n sentUsers.add(validUsers[index]);\n }\n });\n\n if (sentUsers.size > 0) {\n this.pendingRequests.set(event.requestId, sentUsers);\n }\n }\n }\n\n /**\n * 处理权限决策事件\n */\n private async handlePermissionDecision(event: PermissionDecisionEvent): Promise<void> {\n const userMessages = this.pendingRequests.get(event.requestId);\n if (userMessages) {\n const decisionText = event.decision === 'allow' ? '✅ Approved' : '❌ Denied';\n this.logger.info(\n { requestId: event.requestId, decision: event.decision },\n `Permission ${decisionText}`\n );\n }\n this.pendingRequests.delete(event.requestId);\n }\n\n /**\n * 处理卡片按钮回调\n */\n private async handleCardAction(data: CardActionData): Promise<void> {\n const { action, requestId, userId } = 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'].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 const decision = action === 'agree' ? 'allow' : 'deny';\n\n this.bus.publishPermissionDecision({\n requestId,\n decision,\n reason: `User clicked ${action} button via Feishu`,\n });\n\n this.logger.info({ requestId, decision, userId }, 'Permission decided via Feishu');\n }\n\n /**\n * 格式化权限申请内容\n */\n private formatPermissionRequestContent(event: PermissionRequestEvent): string {\n let content = `**Session:** ${event.sessionId}\\n`;\n content += `**Tool:** ${event.toolName}\\n`;\n content += `**Working Dir:** ${event.cwd || 'N/A'}\\n\\n`;\n content += `**Arguments:**\\n\\`\\`\\`\\n${JSON.stringify(event.args, null, 2)}\\n\\`\\`\\``;\n return content;\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 = FeishuFormatter.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 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 default:\n return 'Notification';\n }\n }\n\n private shouldProcessGroupMessage(message: {\n chat_type: string;\n mentions?: Array<{ id: { union_id: string } }>;\n }): boolean {\n const policy = this.feishuConfig.group_policy || 'mention';\n\n // 私聊直接处理\n if (message.chat_type === 'p2p') {\n return true;\n }\n\n // open 策略:允许所有群消息\n if (policy === 'open') {\n return true;\n }\n\n // mention 策略:仅处理@提及\n // TODO(V3): 检查消息中是否 @了机器人\n return false;\n }\n}\n\n// 消息类型定义\ninterface FeishuMessage {\n messageId: string;\n chatId: string;\n senderId: string;\n senderName: string;\n content: string;\n}\n","#!/usr/bin/env node\n\nimport { writePidFile, removePidFile } from '../shared/pidfile.js';\nimport { setupFileLogging, createChannelLogger, getLogger, LogLevel } from '../shared/logger.js';\nimport { SessionManager, type EventFrame, Gateway, EventBus as GatewayEventBus } from '../gateway/index.js';\nimport { PermissionService } from '../gateway/permission-service.js';\nimport { EventPublisher } from '../gateway/publisher.js';\nimport { ClaudeHookAdapter } from '../adapters/agent/claude/hook/index.js';\nimport { AgentAdapterRegistry } from '../core/adapter/AgentAdapterRegistry.js';\nimport { Persistence } from '../shared/persistence.js';\nimport { HttpServer, setupRoutes } from '../server/http.js';\nimport { WebSocketServer, setupWebSocketHandlers, broadcastEvent } from '../server/websocket.js';\nimport { getHookToken } from '../shared/credentials.js';\n// Note: Old adapters removed - using new core/channel architecture via ChannelManager\nimport { PermissionQueue } from '../adapters/permissions/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 { setupAllHandlers } from '../gateway/handlers/index.js';\nimport { NotificationHandler } from '../gateway/notification-handler.js';\nimport { ClaudeSessionContextProvider } from '../adapters/agent/claude/session-context.js';\nimport '../adapters/channels/index.js'; // Auto-register Channels\n\nconst VERSION = '0.1.0';\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 logFile = `${homedir}/.handsoff/logs/gateway.log`;\n setupFileLogging(logFile);\n\n const logger = getLogger(LogLevel.DEBUG);\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 sessionManager = new SessionManager();\n const persistence = new Persistence(`${homedir}/.handsoff/sessions`);\n\n // Create PermissionQueue with config\n const permissionQueue = new PermissionQueue({\n timeout_ms: config.channel.permission?.timeout_ms,\n default_on_timeout: config.channel.permission?.default_on_timeout,\n });\n logger.info(`PermissionQueue 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 // 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', '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', 'finished', 'session_start', 'error'],\n };\n }\n channelManager.initializeFromConfig(channelsConfig);\n logger.info(`ChannelManager initialized with ${channelManager.count} channels`);\n\n // Setup handlers\n const cleanupHandlers = setupAllHandlers(bus, sessionManager, permissionQueue, logger);\n logger.info('Command and permission handlers setup complete');\n\n // Start Channels\n await channelManager.startAll();\n logger.info('All channels started');\n\n // Start NotificationHandler\n const sessionContextProvider = new ClaudeSessionContextProvider();\n const notificationHandler = new NotificationHandler(bus, logger, sessionContextProvider);\n notificationHandler.start();\n logger.info('NotificationHandler started');\n // Expose for shutdown\n\n // Create PermissionService\n const permissionService = new PermissionService(permissionQueue, bus);\n\n // Create EventPublisher\n const eventPublisher = new EventPublisher(\n bus,\n (frame: EventFrame) => {\n broadcastEvent(wsServer, frame);\n },\n undefined,\n persistence\n );\n\n // Create Gateway\n const gatewayEventBus = new GatewayEventBus();\n const gateway = new Gateway(\n sessionManager,\n gatewayEventBus,\n permissionService,\n eventPublisher\n );\n\n // Register claude agent with persistent token\n sessionManager.registerAgent('claude', hookToken);\n logger.info('Registered claude agent with persistent token');\n\n const adapter = new ClaudeHookAdapter();\n await adapter.initialize();\n // Adapter is now registered in AgentAdapterRegistry for discovery by other components\n setupRoutes(httpServer, sessionManager, gateway, adapter, () => wsServer.getClientCount());\n setupWebSocketHandlers(wsServer, sessionManager, { permissionQueue });\n\n // Setup signal handlers for graceful shutdown\n const shutdown = async (signal: string) => {\n logger.info(`Received ${signal}, shutting down gracefully...`);\n notificationHandler.stop();\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 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","filter","ext","filter","readFileSync","existsSync","z","i","acc","ext","start","final","ext","qmark","star","regExpEscape","i","match","existsSync","readFileSync","readFileSync","existsSync","join","logger","hostname","resolve","join","resolve","readdir","readFile","join","existsSync","match","createServer","URL","logger","path","createServer","URL","resolve","match","URL","resolve","VERSION","logger","path","resolve","URL","filter","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","homedir","join","homedir","path","existsSync","readFileSync","randomUUID","randomUUID","resolve","EventBus","logger","resolve","logger","process","formatDuration","statusHandler","logger","logger","logger","logger","readFile","resolve","readFile","logger","logger","resolve","_a","logger","_init","_a","logger","match","REQUEST_ID_REGEX","_init","_a","logger","VERSION","homedir","logger","EventBus"]}
|