tabclaw 0.1.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 +113 -0
- package/config.example.toml +29 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +1858 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/daemon/process.js +5712 -0
- package/dist/daemon/process.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../node_modules/balanced-match/index.js","../../node_modules/brace-expansion/index.js","../../src/daemon/process.ts","../../src/shared/pidfile.ts","../../src/shared/logger.ts","../../src/gateway/index.ts","../../src/gateway/session.ts","../../src/gateway/events.ts","../../src/gateway/plugins.ts","../../src/gateway/permission-service.ts","../../src/shared/permissions.ts","../../node_modules/minimatch/src/index.ts","../../node_modules/minimatch/src/assert-valid-pattern.ts","../../node_modules/minimatch/src/ast.ts","../../node_modules/minimatch/src/brace-expressions.ts","../../node_modules/minimatch/src/unescape.ts","../../node_modules/minimatch/src/escape.ts","../../src/config.ts","../../src/gateway/publisher.ts","../../src/adapters/agent/claude/index.ts","../../src/shared/persistence.ts","../../src/server/http.ts","../../src/server/websocket.ts","../../src/shared/credentials.ts","../../src/adapters/permissions/index.ts","../../src/adapters/permissions/types.ts","../../src/adapters/permissions/queue.ts","../../src/core/bus/index.ts","../../src/core/bus/types.ts","../../src/core/bus/events.ts","../../src/core/channel/manager.ts","../../src/core/channel/registry.ts","../../src/gateway/handlers/command.ts","../../src/core/command/index.ts","../../src/core/command/types.ts","../../src/core/command/executor.ts","../../src/core/command/parser.ts","../../src/core/command/builtin/index.ts","../../src/core/command/builtin/session.ts","../../src/core/command/builtin/system.ts","../../src/core/command/builtin/help.ts","../../src/gateway/handlers/permission.ts","../../src/gateway/notification-handler.ts","../../src/adapters/channels/telegram/formatter.ts","../../src/adapters/agent/claude/session-context.ts","../../src/adapters/channels/index.ts","../../src/adapters/channels/telegram/index.ts","../../src/core/channel/base.ts","../../src/adapters/channels/telegram/bot.ts","../../src/adapters/channels/logger/index.ts","../../src/adapters/channels/feishu/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","'use strict';\nmodule.exports = balanced;\nfunction balanced(a, b, str) {\n if (a instanceof RegExp) a = maybeMatch(a, str);\n if (b instanceof RegExp) b = maybeMatch(b, str);\n\n var r = range(a, b, str);\n\n return r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + a.length, r[1]),\n post: str.slice(r[1] + b.length)\n };\n}\n\nfunction maybeMatch(reg, str) {\n var m = str.match(reg);\n return m ? m[0] : null;\n}\n\nbalanced.range = range;\nfunction range(a, b, str) {\n var begs, beg, left, right, result;\n var ai = str.indexOf(a);\n var bi = str.indexOf(b, ai + 1);\n var 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 result = [ begs.pop(), bi ];\n } else {\n beg = begs.pop();\n if (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) {\n result = [ left, right ];\n }\n }\n\n return result;\n}\n","var balanced = require('balanced-match');\n\nmodule.exports = expandTop;\n\nvar escSlash = '\\0SLASH'+Math.random()+'\\0';\nvar escOpen = '\\0OPEN'+Math.random()+'\\0';\nvar escClose = '\\0CLOSE'+Math.random()+'\\0';\nvar escComma = '\\0COMMA'+Math.random()+'\\0';\nvar escPeriod = '\\0PERIOD'+Math.random()+'\\0';\n\nfunction numeric(str) {\n return parseInt(str, 10) == str\n ? parseInt(str, 10)\n : str.charCodeAt(0);\n}\n\nfunction escapeBraces(str) {\n return str.split('\\\\\\\\').join(escSlash)\n .split('\\\\{').join(escOpen)\n .split('\\\\}').join(escClose)\n .split('\\\\,').join(escComma)\n .split('\\\\.').join(escPeriod);\n}\n\nfunction unescapeBraces(str) {\n return str.split(escSlash).join('\\\\')\n .split(escOpen).join('{')\n .split(escClose).join('}')\n .split(escComma).join(',')\n .split(escPeriod).join('.');\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}\nfunction parseCommaParts(str) {\n if (!str)\n return [''];\n\n var parts = [];\n var m = balanced('{', '}', str);\n\n if (!m)\n return str.split(',');\n\n var pre = m.pre;\n var body = m.body;\n var post = m.post;\n var p = pre.split(',');\n\n p[p.length-1] += '{' + body + '}';\n var postParts = parseCommaParts(post);\n if (post.length) {\n p[p.length-1] += postParts.shift();\n p.push.apply(p, postParts);\n }\n\n parts.push.apply(parts, p);\n\n return parts;\n}\n\nfunction expandTop(str) {\n if (!str)\n return [];\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.substr(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.substr(2);\n }\n\n return expand(escapeBraces(str), true).map(unescapeBraces);\n}\n\nfunction embrace(str) {\n return '{' + str + '}';\n}\nfunction isPadded(el) {\n return /^-?0\\d/.test(el);\n}\n\nfunction lte(i, y) {\n return i <= y;\n}\nfunction gte(i, y) {\n return i >= y;\n}\n\nfunction expand(str, isTop) {\n var expansions = [];\n\n var 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 var pre = m.pre;\n var post = m.post.length\n ? expand(m.post, false)\n : [''];\n\n if (/\\$$/.test(m.pre)) { \n for (var k = 0; k < post.length; k++) {\n var expansion = pre+ '{' + m.body + '}' + post[k];\n expansions.push(expansion);\n }\n } else {\n var isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body);\n var isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(m.body);\n var isSequence = isNumericSequence || isAlphaSequence;\n var 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);\n }\n return [str];\n }\n\n var n;\n if (isSequence) {\n n = m.body.split(/\\.\\./);\n } else {\n n = parseCommaParts(m.body);\n if (n.length === 1) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand(n[0], false).map(embrace);\n if (n.length === 1) {\n return post.map(function(p) {\n return m.pre + n[0] + p;\n });\n }\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 var N;\n\n if (isSequence) {\n var x = numeric(n[0]);\n var y = numeric(n[1]);\n var width = Math.max(n[0].length, n[1].length)\n var incr = n.length == 3\n ? Math.abs(numeric(n[2]))\n : 1;\n var test = lte;\n var reverse = y < x;\n if (reverse) {\n incr *= -1;\n test = gte;\n }\n var pad = n.some(isPadded);\n\n N = [];\n\n for (var i = x; test(i, y); i += incr) {\n var c;\n if (isAlphaSequence) {\n c = String.fromCharCode(i);\n if (c === '\\\\')\n c = '';\n } else {\n c = String(i);\n if (pad) {\n var need = width - c.length;\n if (need > 0) {\n var 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.push(c);\n }\n } else {\n N = [];\n\n for (var j = 0; j < n.length; j++) {\n N.push.apply(N, expand(n[j], false));\n }\n }\n\n for (var j = 0; j < N.length; j++) {\n for (var k = 0; k < post.length; k++) {\n var expansion = pre + N[j] + post[k];\n if (!isTop || isSequence || expansion)\n expansions.push(expansion);\n }\n }\n }\n\n return expansions;\n}\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/index.js';\nimport { Persistence } from '../shared/persistence.js';\nimport { HttpServer, setupRoutes } from '../server/http.js';\nimport { WebSocketServer, setupWebSocketHandlers, broadcastEvent } from '../server/websocket.js';\nimport { getHookToken } from '../shared/credentials.js';\n// Note: Old adapters removed - using new core/channel architecture via ChannelManager\nimport { 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 { setupCommandHandler } from '../gateway/handlers/command.js';\nimport { setupPermissionHandler } from '../gateway/handlers/permission.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.TABCLAW_PORT || String(config.general.hook_server_port), 10);\n const pidFilePath = process.env.TABCLAW_PID_FILE || '';\n\n // Setup gateway file logging FIRST (before any other component initializes logger)\n const logFile = `${homedir}/.tabclaw/logs/gateway.log`;\n setupFileLogging(logFile);\n\n const logger = getLogger(LogLevel.DEBUG);\n logger.info('Starting TabClaw 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 \"tabclaw init\" first.');\n process.exit(1);\n }\n logger.info(`Loaded hook token: ${hookToken.substring(0, 8)}...`);\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}/.tabclaw/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,\n app_id: config.channel.feishu.app_id,\n app_secret: config.channel.feishu.app_secret,\n };\n }\n channelManager.initializeFromConfig(channelsConfig);\n logger.info(`ChannelManager initialized with ${channelManager.count} channels`);\n\n // Setup handlers\n setupCommandHandler(bus, sessionManager, logger);\n setupPermissionHandler(bus, 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 setupRoutes(httpServer, sessionManager, gateway, adapter, () => wsServer.getClientCount());\n setupWebSocketHandlers(wsServer, sessionManager, { permissionQueue });\n\n // Write PID file if path is provided\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 // 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 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(`TabClaw Gateway running on port ${port}`);\n\n // Handle unhandled rejections to prevent silent crashes\n process.on('unhandledRejection', (reason, promise) => {\n // Ignore pino worker thread errors - they're benign\n const reasonStr = String(reason);\n if (reasonStr.includes('worker has exited') || reasonStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${reasonStr}`);\n return;\n }\n logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`);\n });\n\n // Handle uncaught exceptions\n process.on('uncaughtException', (error) => {\n // Ignore pino worker thread errors\n const errorStr = error.message || String(error);\n if (errorStr.includes('worker has exited') || errorStr.includes('thread-stream')) {\n console.error(`[WARN] Pino worker thread error (ignoring): ${errorStr}`);\n return;\n }\n logger.error(`Uncaught Exception: ${error.message}`);\n if (error.stack) {\n logger.error(error.stack);\n }\n });\n\n // Keep process alive using setTimeout loop (not unref'd to keep event loop active)\n const keepProcessAlive = () => {\n setTimeout(keepProcessAlive, 60000);\n };\n keepProcessAlive();\n } catch (error) {\n logger.error({ error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }, 'Failed to start Gateway');\n process.exit(1);\n }\n}\n\nmain();\n","import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { mkdirSync } from 'fs';\n\nexport interface PidFileData {\n pid: number;\n port: number;\n startedAt: string;\n version?: string;\n agents?: string[];\n channels?: string[];\n token?: string;\n}\n\nexport function writePidFile(pidFilePath: string, data: PidFileData): void {\n // Validate pid is a positive integer\n if (!Number.isInteger(data.pid) || data.pid <= 0) {\n throw new TypeError(`Invalid pid: ${data.pid}. Must be a positive integer.`);\n }\n\n // Validate port is a positive integer between 1-65535\n if (!Number.isInteger(data.port) || data.port < 1 || data.port > 65535) {\n throw new TypeError(`Invalid port: ${data.port}. Must be an integer between 1 and 65535.`);\n }\n\n mkdirSync(dirname(pidFilePath), { recursive: true });\n writeFileSync(pidFilePath, JSON.stringify(data, null, 2));\n}\n\nexport function readPidFile(pidFilePath: string): PidFileData | null {\n if (!existsSync(pidFilePath)) {\n return null;\n }\n try {\n const content = readFileSync(pidFilePath, 'utf-8');\n return JSON.parse(content) as PidFileData;\n } catch {\n return null;\n }\n}\n\nexport function removePidFile(pidFilePath: string): void {\n if (existsSync(pidFilePath)) {\n unlinkSync(pidFilePath);\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import pino from 'pino';\nimport { mkdirSync, existsSync, appendFileSync } from 'fs';\nimport { dirname } from 'path';\nimport { hostname } from 'os';\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\nlet fileLogger: pino.Logger | null = null;\nlet consoleLogger: pino.Logger | null = null;\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}/.tabclaw/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 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 { randomBytes } from 'crypto';\n\n/**\n * Session interface representing an agent session\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 * SessionManager handles agent registration and session lifecycle\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 */\nexport class SessionManager {\n // Maps token to agent type (registration before session starts)\n private agentRegistrations = new Map<string, string>();\n\n // Maps sessionId to Session (primary index)\n private sessionsById = new Map<string, Session>();\n\n /**\n * Register an agent and generate a token for it\n */\n registerAgent(agentType: string, customToken?: string): string {\n const token = customToken ?? this.generateToken();\n this.agentRegistrations.set(token, agentType);\n return token;\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.agentRegistrations.get(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.agentRegistrations.delete(token);\n }\n\n /**\n * List all registered agents\n */\n listRegisteredAgents(): { token: string; agentType: string }[] {\n return Array.from(this.agentRegistrations.entries()).map(([token, agentType]) => ({\n token,\n agentType,\n }));\n }\n\n /**\n * Check if a token is registered\n */\n isTokenRegistered(token: string): boolean {\n return this.agentRegistrations.has(token);\n }\n\n /**\n * Get agent type for a token\n */\n getAgentType(token: string): string | undefined {\n return this.agentRegistrations.get(token);\n }\n\n private generateToken(): string {\n return randomBytes(16).toString('hex');\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","// 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 { 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","import expand from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport { AST, ExtglobType } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\ntype 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 nobrace?: boolean\n nocomment?: boolean\n nonegate?: boolean\n debug?: boolean\n noglobstar?: boolean\n noext?: boolean\n nonull?: boolean\n windowsPathsNoEscape?: boolean\n allowWindowsEscape?: boolean\n partial?: boolean\n dot?: boolean\n nocase?: boolean\n nocaseMagicOnly?: boolean\n magicalBraces?: boolean\n matchBase?: boolean\n flipNegate?: boolean\n preserveMultipleSlashes?: boolean\n optimizationLevel?: number\n platform?: Platform\n windowsNoMagicRoot?: boolean\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) => !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) => f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) => 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'\n) as Platform\ntype Sep = '\\\\' | '/'\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep = 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<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\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) => 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: (list: string[], pattern: string, 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)\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\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options.allowWindowsEscape === 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(..._: any[]) {}\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 this.debug = (...args: any[]) => 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 [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))]\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 all ** into *\n if (this.options.noglobstar) {\n for (let i = 0; i < globParts.length; i++) {\n for (let j = 0; j < globParts[i].length; j++) {\n if (globParts[i][j] === '**') {\n globParts[i][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 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 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 (p && p !== '.' && p !== '..' && p !== '**') {\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) continue\n globParts[i] = matched\n globParts[j] = []\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(file: string[], pattern: ParseReturn[], partial: boolean = false) {\n const options = this.options\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 = 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 = fileUNC ? 3 : fileDrive ? 0 : undefined\n const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [file[fdi], pattern[pdi] as string]\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n if (pdi > fdi) {\n pattern = pattern.slice( pdi)\n } else if (fdi > pdi) {\n file = file.slice(fdi)\n }\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // dont' 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 this.debug('matchOne', this, { file, pattern })\n this.debug('matchOne', file.length, pattern.length)\n\n for (\n var fi = 0, pi = 0, fl = file.length, pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n var p = pattern[pi]\n var 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) {\n return false\n }\n /* c8 ignore stop */\n\n if (p === GLOBSTAR) {\n this.debug('GLOBSTAR', [pattern, p, f])\n\n // \"**\"\n // a/**/b/**/c would match the following:\n // a/b/x/y/z/c\n // a/x/y/z/b/c\n // a/b/x/b/x/c\n // a/b/c\n // To do this, take the rest of the pattern after\n // the **, and see if it would match the file remainder.\n // If so, return success.\n // If not, the ** \"swallows\" a segment, and try again.\n // This is recursively awful.\n //\n // a/**/b/**/c matching a/b/x/y/z/c\n // - a matches a\n // - doublestar\n // - matchOne(b/x/y/z/c, b/**/c)\n // - b matches b\n // - doublestar\n // - matchOne(x/y/z/c, c) -> no\n // - matchOne(y/z/c, c) -> no\n // - matchOne(z/c, c) -> no\n // - matchOne(c, c) yes, hit\n var fr = fi\n var pr = pi + 1\n if (pr === pl) {\n this.debug('** at the end')\n // a ** at the end will just swallow the rest.\n // We have found a match.\n // however, it will not swallow /.x, unless\n // options.dot is set.\n // . and .. are *never* matched by **, for explosively\n // exponential reasons.\n for (; fi < fl; fi++) {\n if (\n file[fi] === '.' ||\n file[fi] === '..' ||\n (!options.dot && file[fi].charAt(0) === '.')\n )\n return false\n }\n return true\n }\n\n // ok, let's see if we can swallow whatever we can.\n while (fr < fl) {\n var swallowee = file[fr]\n\n this.debug('\\nglobstar while', file, fr, pattern, pr, swallowee)\n\n // XXX remove this slice. Just pass the start index.\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n this.debug('globstar found match!', fr, fl, swallowee)\n // found a match.\n return true\n } else {\n // can't swallow \".\" or \"..\" ever.\n // can only swallow \".foo\" when explicitly asked.\n if (\n swallowee === '.' ||\n swallowee === '..' ||\n (!options.dot && swallowee.charAt(0) === '.')\n ) {\n this.debug('dot detected!', file, fr, pattern, pr)\n break\n }\n\n // ** swallows a segment, and continue.\n this.debug('globstar swallow a segment, and continue')\n fr++\n }\n }\n\n // no match was found.\n // However, in partial mode, we can't say this is necessarily over.\n /* c8 ignore start */\n if (partial) {\n // ran out of file\n this.debug('\\n>>> no match, partial?', file, fr, pattern, pr)\n if (fr === fl) {\n return true\n }\n }\n /* c8 ignore stop */\n return false\n }\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\n ? starDotExtTestDot\n : starDotExtTest\n )(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase\n ? options.dot\n ? qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot\n ? qmarksTestDot\n : qmarksTest\n )(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 return fastTest ? Object.assign(re, { test: fastTest }) : 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 = options.noglobstar\n ? star\n : options.dot\n ? 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 typeof p === 'string'\n ? regExpEscape(p)\n : p === GLOBSTAR\n ? GLOBSTAR\n : p._src\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 return pp.filter(p => p !== GLOBSTAR).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 // 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 (ex) {\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 (let i = 0; i < set.length; i++) {\n const pattern = set[i]\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","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: any) => void = (\n pattern: any\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport { 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): c is ExtglobType =>\n types.has(c as ExtglobType)\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\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n readonly #parent?: AST\n readonly #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\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 if (this.#toString !== undefined) return this.#toString\n if (!this.type) {\n return (this.#toString = this.#parts.map(p => String(p)).join(''))\n } else {\n return (this.#toString =\n this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')')\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 (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {\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: any[] =\n this.type === null\n ? this.#parts.slice().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 ): number {\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 if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt)\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 if (isExtglobType(c) && str.charAt(i) === '(') {\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)\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 static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options)\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 // 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) this.#fillNegs()\n if (!this.type) {\n const noEmpty = this.isStart() && this.isEnd()\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 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : ''\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.#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 this.#parts = [s]\n this.type = null\n this.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n // XXX abstract out this map method\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 ? ')'\n : this.type === '?'\n ? ')?'\n : this.type === '+' && bodyDotAllowed\n ? ')'\n : this.type === '*' && bodyDotAllowed\n ? `)?`\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 #partsToRegExp(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 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 (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 if (noEmpty && glob === '*') re += starNoEmpty\n else re += star\n hasMagic = true\n continue\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } = {\n '[: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\n ? '(' + sranges + '|' + snegs + ')'\n : ranges.length\n ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import { MinimatchOptions } from './index.js'\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link windowsPathsNoEscape} option is used, then square-brace\n * escapes are removed, but not backslash escapes. For example, it will turn\n * the string `'[*]'` into `*`, but it will not turn `'\\\\*'` into `'*'`,\n * becuase `\\` is a path separator in `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both brace escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n */\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n return windowsPathsNoEscape\n ? s.replace(/\\[([^\\/\\\\])\\]/g, '$1')\n : s.replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g, '$1$2').replace(/\\\\([^\\/])/g, '$1')\n}\n","import { MinimatchOptions } from './index.js'\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link windowsPathsNoEscape | GlobOptions.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 */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\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 return windowsPathsNoEscape\n ? s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport dotenv from 'dotenv';\n// Note: Notification types removed - using EventBus architecture now\n\n// Load .env file if exists\ndotenv.config();\n\nexport interface GeneralConfig {\n 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}\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 },\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(), '.tabclaw', '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.TABCLAW_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.TABCLAW_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 app_id:\n process.env.TABCLAW_FEISHU_APP_ID || raw.channel?.feishu?.app_id || '',\n app_secret:\n process.env.TABCLAW_FEISHU_APP_SECRET ||\n raw.channel?.feishu?.app_secret ||\n '',\n },\n permission: {\n ...DEFAULT_CONFIG.channel.permission,\n ...(raw.channel?.permission || {}),\n // Support env var override\n timeout_ms: parseInt(\n process.env.TABCLAW_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.TABCLAW_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","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","import type { AgentHookAdapter, AgentEventEnvelope } from '../../../core/agent-event.js';\n\nexport class ClaudeHookAdapter implements AgentHookAdapter {\n readonly agentType = 'claude';\n\n private supportedEvents = new Set([\n 'SessionStart',\n 'SessionEnd',\n 'PreToolUse',\n 'PermissionRequest',\n 'PostToolUse',\n 'PostToolUseFailure',\n 'Stop',\n ]);\n\n canHandle(rawEventType: string): boolean {\n return this.supportedEvents.has(rawEventType);\n }\n\n translate(rawEventType: string, payload: unknown): AgentEventEnvelope | null {\n if (!payload || typeof payload !== 'object') {\n return null;\n }\n const p = payload as Record<string, unknown>;\n const sessionId = typeof p.session_id === 'string' ? p.session_id : '';\n const timestamp = new Date().toISOString();\n const metadata: AgentEventEnvelope['metadata'] = {\n agentType: this.agentType,\n sessionId,\n timestamp,\n rawEventType,\n };\n\n const rest = Object.fromEntries(\n Object.entries(p).filter(([k]) => !['session_id', 'tool_name', 'tool_input', 'reason', 'output', 'error', 'last_assistant_message', 'transcript_path'].includes(k))\n );\n metadata.permission_mode = typeof rest.permission_mode === 'string' ? rest.permission_mode : 'auto';\n metadata.cwd = typeof rest.cwd === 'string' ? rest.cwd : '';\n\n switch (rawEventType) {\n case 'SessionStart':\n return {\n type: 'session:start',\n payload: { sessionId },\n metadata,\n };\n case 'SessionEnd':\n return {\n type: 'session:end',\n payload: { sessionId, reason: typeof p.reason === 'string' ? p.reason : undefined },\n metadata,\n };\n case 'PreToolUse':\n case 'PermissionRequest':\n return {\n type: 'permission:request',\n payload: {\n sessionId,\n toolName: typeof p.tool_name === 'string' ? p.tool_name : '',\n toolInput: (p.tool_input as Record<string, unknown>) || {},\n },\n metadata,\n };\n case 'PostToolUse':\n return {\n type: 'tool:post',\n payload: {\n sessionId,\n toolName: typeof p.tool_name === 'string' ? p.tool_name : '',\n toolInput: (p.tool_input as Record<string, unknown>) || {},\n output: typeof p.output === 'string' ? p.output : undefined,\n },\n metadata,\n };\n case 'PostToolUseFailure':\n return {\n type: 'tool:failure',\n payload: {\n sessionId,\n toolName: typeof p.tool_name === 'string' ? p.tool_name : '',\n toolInput: (p.tool_input as Record<string, unknown>) || {},\n error: typeof p.error === 'string' ? p.error : undefined,\n },\n metadata,\n };\n case 'Stop':\n return {\n type: 'finished',\n payload: {\n sessionId,\n reason: typeof p.reason === 'string' ? p.reason : undefined,\n lastAssistantMessage: typeof p.last_assistant_message === 'string' ? p.last_assistant_message : undefined,\n transcriptPath: typeof p.transcript_path === 'string' ? p.transcript_path : undefined,\n },\n metadata,\n };\n default:\n return null;\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 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, eventType] = match;\n\n try {\n const registeredAgents = sessionManager.listRegisteredAgents();\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 const body = await parseJsonBody(req);\n logger.info({ eventType, token: token.substring(0, 8), body }, 'Hook payload received');\n\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 res.end(JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PermissionRequest',\n decision: {\n behavior: result.behavior,\n message: result.message,\n },\n },\n }));\n } else {\n res.end(JSON.stringify({\n accepted: result.behavior === 'allow',\n message: result.message,\n }));\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';\n\nexport interface Client {\n id: string;\n ws: WebSocket;\n isAlive: boolean;\n filters?: ClientFilters;\n}\n\nexport interface ClientFilters {\n agentTypes?: string[];\n sessionIds?: string[];\n}\n\nexport type MessageHandler = (clientId: string, message: WebSocketMessage) => void;\nexport type ConnectionHandler = (clientId: string) => void;\n\nexport interface WebSocketMessage {\n type: string;\n id?: string;\n requestId?: string;\n allow?: boolean;\n reason?: string;\n filters?: ClientFilters;\n [key: string]: unknown;\n}\n\nconst VERSION = '0.1.0';\nconst logger = getLogger();\n\n/**\n * WebSocket Server for the Gateway\n */\nexport class WebSocketServer {\n private wss: WSWebSocketServer | null = null;\n private clients = new Map<string, Client>();\n private messageHandlers: MessageHandler[] = [];\n private connectionHandlers: ConnectionHandler[] = [];\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private clientIdCounter = 0;\n\n constructor(\n private httpServer: HttpServer,\n private options: { heartbeatIntervalMs?: number; path?: string } = {}\n ) {}\n\n /**\n * Start the WebSocket server\n */\n async start(): Promise<void> {\n const httpSvr = this.httpServer.getServer();\n if (!httpSvr) {\n throw new Error('HTTP server must be started before WebSocket server');\n }\n\n this.wss = new WSWebSocketServer({ noServer: true });\n this.setupConnectionHandlers();\n this.startHeartbeat();\n\n // Register upgrade handler with HTTP server\n const path = this.options.path || '/ws';\n this.httpServer.onUpgrade(path, (request, socket, head) => {\n this.wss?.handleUpgrade(request, socket, head, (ws) => {\n this.wss?.emit('connection', ws, request);\n });\n });\n\n logger.info(`WebSocket server registered on path: ${path}`);\n }\n\n /**\n * Stop the WebSocket server\n */\n async stop(): Promise<void> {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n\n this.closeAll();\n\n return new Promise((resolve) => {\n this.wss?.close(() => {\n logger.info('WebSocket server stopped');\n resolve();\n });\n });\n }\n\n /**\n * Add a message handler\n */\n onMessage(handler: MessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Add a connection handler\n */\n onConnection(handler: ConnectionHandler): void {\n this.connectionHandlers.push(handler);\n }\n\n /**\n * Add a new client connection\n */\n add(ws: WebSocket, req?: IncomingMessage): string {\n const clientId = `client-${++this.clientIdCounter}`;\n const client: Client = {\n id: clientId,\n ws,\n isAlive: true,\n };\n this.clients.set(clientId, client);\n\n // Parse query parameters for pre-filters\n if (req?.url) {\n const url = new URL(req.url, 'http://localhost');\n const agentType = url.searchParams.get('agentType');\n const sessionId = url.searchParams.get('sessionId');\n\n if (agentType || sessionId) {\n client.filters = {\n agentTypes: agentType ? [agentType] : undefined,\n sessionIds: sessionId ? [sessionId] : undefined,\n };\n }\n }\n\n ws.on('pong', () => {\n client.isAlive = true;\n });\n\n ws.on('message', (data: Buffer) => {\n try {\n const message = JSON.parse(data.toString()) as WebSocketMessage;\n this.handleMessage(clientId, message);\n } catch (error) {\n logger.error('Invalid WebSocket message:', error);\n this.send(clientId, {\n type: 'res',\n id: 'error',\n error: { code: 400, message: 'Invalid JSON message' },\n });\n }\n });\n\n ws.on('close', () => {\n this.remove(clientId);\n });\n\n ws.on('error', (error) => {\n logger.error(`WebSocket error for client ${clientId}:`, error);\n this.remove(clientId);\n });\n\n logger.info(`WebSocket client connected: ${clientId}`);\n\n for (const handler of this.connectionHandlers) {\n try {\n handler(clientId);\n } catch (error) {\n logger.error('Error in connection handler:', error);\n }\n }\n\n return clientId;\n }\n\n /**\n * Remove a client connection\n */\n remove(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n this.clients.delete(clientId);\n logger.info(`WebSocket client disconnected: ${clientId}`);\n }\n }\n\n /**\n * Get a client by ID\n */\n get(clientId: string): Client | undefined {\n return this.clients.get(clientId);\n }\n\n /**\n * Get count of connected clients\n */\n getClientCount(): number {\n return this.clients.size;\n }\n\n /**\n * Send a message to a specific client\n */\n send(clientId: string, message: unknown): boolean {\n const client = this.clients.get(clientId);\n if (client && client.ws.readyState === WebSocket.OPEN) {\n client.ws.send(JSON.stringify(message));\n return true;\n }\n return false;\n }\n\n /**\n * Broadcast a message to all connected clients\n */\n broadcast(message: unknown, filter?: (client: Client) => boolean): void {\n const messageStr = JSON.stringify(message);\n for (const [, client] of this.clients) {\n if (client.ws.readyState === WebSocket.OPEN) {\n if (!filter || filter(client)) {\n client.ws.send(messageStr);\n }\n }\n }\n }\n\n /**\n * Close all client connections\n */\n closeAll(): void {\n for (const [, client] of this.clients) {\n client.ws.close();\n }\n this.clients.clear();\n }\n\n /**\n * Set client filters\n */\n setFilters(clientId: string, filters: ClientFilters): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = filters;\n }\n }\n\n /**\n * Clear client filters\n */\n clearFilters(clientId: string): void {\n const client = this.clients.get(clientId);\n if (client) {\n client.filters = undefined;\n }\n }\n\n private setupConnectionHandlers(): void {\n this.wss?.on('connection', (ws: WebSocket, req: IncomingMessage) => {\n this.add(ws, req);\n });\n }\n\n private handleMessage(clientId: string, message: WebSocketMessage): void {\n for (const handler of this.messageHandlers) {\n try {\n handler(clientId, message);\n } catch (error) {\n logger.error('Error in WebSocket message handler:', error);\n }\n }\n }\n\n private startHeartbeat(): void {\n const intervalMs = this.options.heartbeatIntervalMs || 30000;\n this.heartbeatInterval = setInterval(() => {\n for (const [, client] of this.clients) {\n if (!client.isAlive) {\n client.ws.terminate();\n this.remove(client.id);\n continue;\n }\n client.isAlive = false;\n client.ws.ping();\n }\n }, intervalMs);\n }\n}\n\nexport interface WebSocketSetupOptions {\n 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 TabClaw 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 unknown message types\n wsServer.onMessage((clientId, message) => {\n const knownTypes = ['subscribe', 'unsubscribe', 'list_sessions', 'welcome', 'permission_decision', 'list_pending_permissions'];\n if (!knownTypes.includes(message.type)) {\n wsServer.send(clientId, {\n type: 'res',\n id: message.id || 'unknown',\n error: { code: 400, message: `Unknown message type: ${message.type}` },\n });\n }\n });\n\n // Handle permission_decision message\n wsServer.onMessage((clientId, message) => {\n if (message.type === 'permission_decision' && 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 { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } 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 = 32;\n\nfunction getCredentialsPath(): string {\n return join(homedir(), '.tabclaw', '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 writeFileSync(path, JSON.stringify(credentials, null, 2), { mode: 0o600 });\n}\n\nexport function getOrCreateHookToken(): string {\n const existing = loadCredentials();\n\n if (existing?.hookToken) {\n return existing.hookToken;\n }\n\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n\nexport function getHookToken(): string | null {\n return loadCredentials()?.hookToken ?? null;\n}\n\nexport function resetCredentials(): string {\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n","export * from './types.js';\nexport * from './queue.js';\n","/**\n * Permission decision for tool use\n */\nexport interface PermissionDecision {\n behavior: 'allow' | 'deny';\n message?: string;\n}\n\n/**\n * Result of a synchronous permission request call.\n * Provides the requestId immediately (synchronously) and a promise\n * that resolves when a decision is made.\n */\nexport interface PermissionRequestResult {\n requestId: string;\n decisionPromise: Promise<PermissionDecision>;\n}\n\n/**\n * Pending permission request\n */\nexport interface PendingPermission {\n requestId: string;\n sessionId: string;\n toolName: string;\n toolInput: Record<string, unknown>;\n timestamp: number;\n resolve: (decision: PermissionDecision) => void;\n reject: (error: Error) => void;\n timeoutId: NodeJS.Timeout;\n}\n\n/**\n * Permission request parameters\n */\nexport interface PermissionRequestParams {\n sessionId: string;\n toolName: string;\n toolInput: Record<string, unknown>;\n}\n\n/**\n * Pending permission info (for listing)\n */\nexport interface PendingPermissionInfo {\n requestId: string;\n sessionId: string;\n toolName: string;\n elapsedMs: number;\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 TabClawEvent,\n} from './events.js';\n\n/**\n * 类型安全的事件总线\n * 支持 Inbound/Outbound 双向事件流\n */\nexport class EventBus {\n private emitter: EventEmitter;\n private logger: ReturnType<typeof getLogger>;\n\n constructor() {\n this.emitter = new EventEmitter();\n this.logger = getLogger();\n this.logger.debug('EventBus initialized');\n }\n\n /**\n * 通用事件发布\n */\n emit<T extends TabClawEvent>(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 TabClawEvent>(\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: TabClawEvent['type']): number {\n return this.emitter.listenerCount(eventType);\n }\n}\n\n/**\n * 创建 EventBus 实例\n */\nexport function createEventBus(): EventBus {\n return new EventBus();\n}\n\n// 导出所有类型\nexport * from './types.js';\nexport * from './events.js';\n","/**\n * 基础事件接口,所有事件必须实现\n */\nexport interface BusEvent {\n type: string;\n timestamp: Date;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * 事件处理器类型\n */\nexport type EventHandler<T extends BusEvent> = (event: T) => void | Promise<void>;\n\n/**\n * 按钮结构(用于内联键盘)\n */\nexport interface Button {\n text: string;\n data: string;\n}\n","import { BusEvent, Button } from './types.js';\n\n/**\n * 从聊天平台收到的消息\n */\nexport interface InboundMessage extends BusEvent {\n type: 'inbound:message';\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}\n\n/**\n * 发送到聊天平台的消息\n */\nexport interface OutboundMessage extends BusEvent {\n type: 'outbound:message';\n /** Channel 名称 (telegram, logger, feishu) 或 'broadcast' */\n channel: string;\n chatId: string;\n text: string;\n replyToMessageId?: string;\n buttons?: Button[];\n metadata?: Record<string, unknown>;\n}\n\n/**\n * 权限申请事件\n */\nexport interface PermissionRequestEvent extends BusEvent {\n type: 'permission:request';\n sessionId: string;\n requestId: string;\n toolName: string;\n args: Record<string, unknown>;\n chatId: string;\n messageId: string;\n cwd?: string;\n}\n\n/**\n * 权限决策事件\n */\nexport interface PermissionDecisionEvent extends BusEvent {\n type: 'permission:decision';\n requestId: string;\n decision: 'allow' | 'deny' | 'always_allow';\n reason?: string;\n}\n\n/**\n * 命令事件\n */\nexport interface CommandEvent extends BusEvent {\n type: 'command';\n command: string;\n args: string[];\n chatId: string;\n messageId: string;\n sender: {\n id: string;\n username?: string;\n };\n}\n\n/**\n * Session 开始事件\n */\nexport interface SessionStartEvent extends BusEvent {\n type: 'session:start';\n sessionId: string;\n chatId: string;\n userId: string;\n}\n\n/**\n * Session 结束事件\n */\nexport interface SessionEndEvent extends BusEvent {\n type: 'session:end';\n sessionId: string;\n chatId: string;\n userId: string;\n reason?: string;\n}\n\n/**\n * Tool 执行成功事件\n */\nexport interface ToolPostEvent extends BusEvent {\n type: 'tool:post';\n sessionId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n output?: string;\n}\n\n/**\n * Tool 执行失败事件\n */\nexport interface ToolFailureEvent extends BusEvent {\n type: 'tool:failure';\n sessionId: string;\n toolName: string;\n toolInput?: Record<string, unknown>;\n error?: string;\n}\n\n/**\n * Finished 事件(一轮任务结束)\n */\nexport interface FinishedEvent extends BusEvent {\n type: 'finished';\n sessionId: string;\n chatId: string;\n userId: string;\n reason?: string;\n lastAssistantMessage?: string;\n transcriptPath?: string;\n}\n\n/**\n * 通知事件\n */\nexport interface NotificationEvent extends BusEvent {\n type: 'notification';\n level: 'info' | 'warn' | 'error' | 'success';\n title: string;\n message: string;\n chatId?: string;\n}\n\n/**\n * 所有 TabClaw 事件的联合类型\n */\nexport type TabClawEvent =\n | InboundMessage\n | OutboundMessage\n | PermissionRequestEvent\n | PermissionDecisionEvent\n | CommandEvent\n | SessionStartEvent\n | SessionEndEvent\n | ToolPostEvent\n | ToolFailureEvent\n | FinishedEvent\n | NotificationEvent;\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 } 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 * 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 * 构造函数\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 * 设置 Outbound 消息路由\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 try {\n await channel.start();\n this.logger.debug({ channel: name }, 'Channel started');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error({ channel: name, error: errorMessage }, 'Failed to start channel');\n }\n }\n\n // 设置出站消息路由\n this.setupOutboundRouting();\n\n this.logger.info('All channels started');\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 if (this.unsubscribeOutbound) {\n this.unsubscribeOutbound();\n this.unsubscribeOutbound = null;\n this.logger.debug('Outbound message routing stopped');\n }\n\n // 停止所有 Channel\n for (const [name, channel] of this.channels) {\n try {\n await channel.stop();\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 this.logger.info('All channels stopped');\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 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 // Channel 自己决定是否处理\n if (!channel.shouldNotify(eventType)) {\n continue;\n }\n\n if (!channel.isRunning) {\n this.logger.debug({ channel: name }, 'Channel not running, skipping');\n continue;\n }\n\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 }, 'Failed to send notification');\n }\n }\n }\n\n /**\n * 路由消息到指定 Channel\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 // 检查消息是否包含按钮且 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","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 { 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: 'telegram', // Response goes back to Telegram\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 { getLogger } from '../../shared/logger.js';\nimport {\n CommandContext,\n CommandHandler,\n CommandGroup,\n CommandHandlerFunction,\n} from './types.js';\n\n/**\n * 命令注册表\n * 管理所有可用命令的注册和检索\n */\nexport class CommandRegistry {\n private commands = new Map<string, Map<string, CommandHandler>>();\n private logger = getLogger();\n\n /**\n * 注册单个命令\n * @param group - 命令组名称(如 'session')\n * @param subcommand - 子命令名称(如 'list')\n * @param handler - 命令处理器\n */\n register(\n group: string,\n subcommand: string,\n handler: CommandHandler\n ): void {\n if (!this.commands.has(group)) {\n this.commands.set(group, new Map());\n }\n const groupMap = this.commands.get(group)!;\n groupMap.set(subcommand, handler);\n this.logger.debug(\n { group, subcommand },\n 'Command registered'\n );\n }\n\n /**\n * 批量注册命令组\n * @param group - 命令组名称\n * @param handlers - 命令组(包含多个子命令)\n */\n registerGroup(group: string, handlers: CommandGroup): void {\n for (const [subcommand, handler] of Object.entries(handlers)) {\n this.register(group, subcommand, handler);\n }\n }\n\n /**\n * 获取命令处理器\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理器,如果不存在则返回 undefined\n */\n get(group: string, subcommand: string): CommandHandler | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n return groupMap.get(subcommand);\n }\n\n /**\n * 获取命令处理函数(便捷方法)\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 命令处理函数,如果不存在则返回 undefined\n */\n getHandler(group: string, subcommand: string): CommandHandlerFunction | undefined {\n return this.get(group, subcommand)?.handler;\n }\n\n /**\n * 检查命令是否存在\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否存在\n */\n has(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n return groupMap.has(subcommand);\n }\n\n /**\n * 检查命令组是否存在\n * @param group - 命令组名称\n * @returns 是否存在\n */\n hasGroup(group: string): boolean {\n return this.commands.has(group);\n }\n\n /**\n * 列出所有命令\n * @returns 所有命令的列表,格式为 { group, subcommand, description, usage }\n */\n list(): Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> {\n const result: Array<{\n group: string;\n subcommand: string;\n description: string;\n usage?: string;\n }> = [];\n\n for (const [group, groupMap] of this.commands.entries()) {\n for (const [subcommand, handler] of groupMap.entries()) {\n result.push({\n group,\n subcommand,\n description: handler.description,\n usage: handler.usage,\n });\n }\n }\n\n // 按组名和子命令名排序\n result.sort((a, b) => {\n if (a.group !== b.group) {\n return a.group.localeCompare(b.group);\n }\n return a.subcommand.localeCompare(b.subcommand);\n });\n\n return result;\n }\n\n /**\n * 获取命令组中的所有子命令\n * @param group - 命令组名称\n * @returns 命令组,如果不存在则返回 undefined\n */\n getGroup(group: string): CommandGroup | undefined {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return undefined;\n }\n const result: CommandGroup = {};\n for (const [subcommand, handler] of groupMap.entries()) {\n result[subcommand] = handler;\n }\n return result;\n }\n\n /**\n * 获取所有命令组名称\n * @returns 命令组名称列表\n */\n getGroups(): string[] {\n return Array.from(this.commands.keys()).sort();\n }\n\n /**\n * 注销单个命令\n * @param group - 命令组名称\n * @param subcommand - 子命令名称\n * @returns 是否成功注销\n */\n unregister(group: string, subcommand: string): boolean {\n const groupMap = this.commands.get(group);\n if (!groupMap) {\n return false;\n }\n const result = groupMap.delete(subcommand);\n if (result) {\n this.logger.debug({ group, subcommand }, 'Command unregistered');\n }\n // 如果组为空,删除组\n if (groupMap.size === 0) {\n this.commands.delete(group);\n }\n return result;\n }\n\n /**\n * 清空所有命令\n */\n clear(): void {\n this.commands.clear();\n this.logger.debug('All commands cleared');\n }\n}\n\n/**\n * 全局命令注册表单例\n */\nexport const commandRegistry = new CommandRegistry();\n\n// 导出类型\nexport * from './types.js';\n\n// 导出命令执行器\nexport { CommandExecutor } from './executor.js';\n\n// 导出内置命令注册函数\nexport { registerBuiltinCommands } from './builtin/index.js';\n","import { InboundMessage } from '../bus/events.js';\nimport { EventBus } from '../bus/index.js';\nimport { SessionManager } from '../../gateway/session.js';\n\n/**\n * 命令上下文\n * 提供给命令处理器的执行环境\n */\nexport interface CommandContext {\n /** 原始入站消息 */\n source: InboundMessage;\n /** 事件总线 */\n bus: EventBus;\n /** 会话管理器 */\n sessionManager: SessionManager;\n}\n\n/**\n * 命令处理器函数类型\n */\nexport type CommandHandlerFunction = (\n args: string[],\n context: CommandContext\n) => Promise<string>;\n\n/**\n * 命令处理器\n * 定义一个命令的处理逻辑和元数据\n */\nexport interface CommandHandler {\n /** 命令描述 */\n description: string;\n /** 使用示例 */\n usage?: string;\n /** 处理函数 */\n handler: CommandHandlerFunction;\n}\n\n/**\n * 命令组\n * 包含一组相关的子命令(如 session list, session status)\n * key 是子命令名称,value 是命令处理器\n */\nexport type CommandGroup = Record<string, CommandHandler>;\n","import type { Logger } from 'pino';\nimport { CommandRegistry } from './index.js';\nimport { CommandParser, ParsedCommand } from './parser.js';\nimport { CommandContext } from './types.js';\nimport { getLogger } from '../../shared/logger.js';\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","/**\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 { 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';\n\nexport { sessionCommands, registerSessionCommands } from './session.js';\nexport { systemCommands, registerSystemCommands } from './system.js';\nexport { helpCommand, registerHelpCommand } from './help.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 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 { CommandContext, CommandGroup, CommandHandler } from '../types.js';\nimport { Session } from '../../../gateway/session.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 * Format a single session for display\n */\nfunction formatSession(session: Session, includeStatus: boolean): string {\n const status = session.isEnded() ? 'ended' : 'active';\n const duration = formatDuration(session.startedAt, session.endedAt);\n\n let output = `\\`${session.id}\\` - **${session.agentType}** (${duration})`;\n\n if (includeStatus) {\n output += ` - ${status}`;\n }\n\n return output;\n}\n\n/**\n * List all sessions\n * Usage: /session list [--all]\n */\nconst listHandler: CommandHandler = {\n description: 'List all sessions',\n usage: '/session list [--all]',\n handler: async (args: string[], context: CommandContext): Promise<string> => {\n const includeEnded = args.includes('--all');\n const sessions = context.sessionManager.listSessions({ includeEnded });\n\n if (sessions.length === 0) {\n return includeEnded\n ? '**No sessions found.**\\n\\nUse `/session` commands to manage sessions.'\n : '**No active sessions.**\\n\\nUse `/session list --all` to see ended sessions.';\n }\n\n const header = includeEnded\n ? '**All Sessions**\\n\\n'\n : '**Active Sessions**\\n\\n';\n\n const sessionList = sessions\n .map((s) => formatSession(s, includeEnded))\n .join('\\n');\n\n const footer = includeEnded\n ? `\\n\\nTotal: ${sessions.length} session(s)`\n : `\\n\\nActive: ${sessions.length} | Use \"/session list --all\" for ended sessions`;\n\n return header + sessionList + footer;\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 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 const session = context.sessionManager.getSessionById(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.isEnded() ? 'Ended' : 'Active';\n const duration = formatDuration(session.startedAt, session.endedAt);\n\n let output = `**Session Status: \\`${session.id}\\`**\\n\\n`;\n output += `**Agent Type:** ${session.agentType}\\n`;\n output += `**Status:** ${status}\\n`;\n output += `**Duration:** ${duration}\\n`;\n output += `**Started:** ${session.startedAt.toISOString()}\\n`;\n\n if (session.endedAt) {\n output += `**Ended:** ${session.endedAt.toISOString()}\\n`;\n } else {\n output += `**Last Activity:** ${session.lastActivityAt.toISOString()}\\n`;\n }\n\n if (session.workDir) {\n output += `**Work Directory:** \\`${session.workDir}\\`\\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 = '**TabClaw 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 = '**TabClaw Bot Commands**\\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 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 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';\nimport { TelegramFormatter } from '../adapters/channels/telegram/formatter.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. 使用 TelegramFormatter 格式化消息\n * 4. 发布到 EventBus 作为 outbound:message\n */\nexport class NotificationHandler {\n private unsubscribeFns: Array<() => void> = [];\n private formatter = new TelegramFormatter();\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 const summary = this.provider\n ? await this.provider.getSessionSummary(event.sessionId, event.transcriptPath)\n : undefined;\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 const text = this.formatter.format(ctx);\n await this.publishNotification(ctx.eventType, text);\n }\n\n /**\n * 发布通知到所有 Channel\n *\n * 注意:Channel 自己会检查 shouldNotify() 决定是否处理\n */\n private async publishNotification(eventType: string, text: string): Promise<void> {\n this.logger.debug({ eventType }, 'Publishing notification');\n\n const message: OutboundMessage = {\n type: 'outbound:message',\n timestamp: new Date(),\n channel: 'broadcast', // 广播到所有 Channel\n chatId: 'broadcast',\n text,\n metadata: { eventType },\n };\n\n await this.bus.publishOutbound(message);\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 { 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 = 3, delayMs = 100): 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 if (summary) return summary;\n } catch (error) {\n lastError = error;\n if (attempt < maxAttempts) {\n await sleep(delayMs);\n }\n }\n }\n getLogger().warn({ error: lastError instanceof Error ? lastError.message : String(lastError), transcriptPath }, 'Failed to read transcript');\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","/**\n * Channel 适配器导出\n *\n * 导入此文件会自动注册所有 Channel 到 Registry。\n */\n\n// Telegram\nexport { TelegramChannel } from './telegram/index.js';\n\n// Logger\nexport { LoggerChannel } from './logger/index.js';\n\n// Feishu\nexport { FeishuChannel } from './feishu/index.js';\n","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 { 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 * 启动 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.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 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 const text = message.text;\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 const text = message.text;\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 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 } from './types.js';\n\n/**\n * Channel 配置扩展接口,包含权限控制\n */\nexport interface ExtendedChannelConfig extends ChannelConfig {\n /** 允许发送消息的用户ID列表,[\"*\"] 表示允许所有 */\n allowFrom?: string[];\n}\n\n/**\n * Channel 抽象基类\n * 封装通用逻辑,具体 Channel 实现需要继承此类\n */\nexport abstract class BaseChannel implements Channel {\n /** Channel 唯一标识名 */\n abstract readonly name: string;\n\n /** Channel 显示名称 */\n abstract readonly displayName: string;\n\n /** Channel 能力声明 */\n abstract readonly capabilities: ChannelCapabilities;\n\n /** Channel 运行状态 */\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 * 获取 Channel 运行状态\n */\n get isRunning(): boolean {\n return this._isRunning;\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 chatId,\n messageId,\n text,\n sender,\n });\n }\n\n /**\n * 检查发送者是否有权限\n * 权限检查逻辑:\n * - 如果 allowFrom 为空或未配置,拒绝所有\n * - 如果 allowFrom 包含 \"*\",允许所有\n * - 否则检查 senderId 是否在 allowFrom 列表中\n * @param senderId - 发送者ID\n * @returns 是否有权限\n */\n protected isAllowed(senderId: string): boolean {\n const allowList = this.config.allowFrom;\n\n // 如果 allowFrom 为空或未配置,拒绝所有\n if (!allowList || allowList.length === 0) {\n return false;\n }\n\n // 如果 allowFrom 包含 \"*\",允许所有\n if (allowList.includes('*')) {\n return true;\n }\n\n // 检查 senderId 是否在 allowFrom 列表中\n return allowList.includes(senderId);\n }\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","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 { 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 async start(): Promise<void> {\n await super.start();\n this.logger.info('Logger channel started');\n }\n\n async stop(): Promise<void> {\n await super.stop();\n this.logger.info('Logger channel stopped');\n }\n\n async send(message: OutboundMessage): Promise<void> {\n this.messageLogger.info({\n chatId: message.chatId,\n text: message.text,\n }, '[Logger] Message');\n }\n}\n","import type { Logger } from 'pino';\nimport { BaseChannel } from '../../../core/channel/base.js';\nimport type { EventBus } from '../../../core/bus/index.js';\nimport type { ChannelConfig, ChannelCapabilities } from '../../../core/channel/types.js';\nimport type { OutboundMessage } from '../../../core/bus/events.js';\nimport { Channel } from '../../../core/channel/registry.js';\n\n/**\n * Feishu Channel 实现\n *\n * 飞书机器人集成(骨架实现)。\n */\n@Channel('feishu')\nexport class FeishuChannel extends BaseChannel {\n readonly name = 'feishu';\n readonly displayName = 'Feishu';\n readonly capabilities: ChannelCapabilities = {\n supportsButtons: true,\n supportsMarkdown: true,\n supportsImages: false,\n supportsStreaming: false,\n };\n\n constructor(config: ChannelConfig, bus: EventBus, logger: Logger) {\n super(config, bus, logger);\n // TODO: 实现飞书 Bot 初始化\n }\n\n async start(): Promise<void> {\n await super.start();\n this.logger.info('Feishu channel started (skeleton)');\n }\n\n async stop(): Promise<void> {\n await super.stop();\n this.logger.info('Feishu channel stopped');\n }\n\n async send(_message: OutboundMessage): Promise<void> {\n // TODO: 实现飞书消息发送\n this.logger.debug('Feishu send (not implemented)');\n }\n}\n"],"mappings":"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","names":["expand","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","homedir","filter","ext","filter","readFileSync","existsSync","i","acc","ext","start","final","ext","path","qmark","star","expand","regExpEscape","match","existsSync","readFileSync","readFileSync","existsSync","join","logger","join","existsSync","match","logger","path","match","URL","VERSION","logger","path","URL","filter","readFileSync","writeFileSync","existsSync","join","homedir","join","homedir","path","existsSync","readFileSync","EventBus","logger","logger","process","formatDuration","statusHandler","logger","logger","logger","readFile","readFile","logger","logger","logger","_init","_a","logger","_init","_a","logger","VERSION","homedir","logger","EventBus"]}
|