@openacp/cli 0.6.10 → 2026.41.1
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 +34 -16
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +27787 -467
- package/dist/cli.js.map +1 -1
- package/dist/data/registry-snapshot.json +1 -1
- package/dist/index.d.ts +1944 -463
- package/dist/index.js +17365 -102
- package/dist/index.js.map +1 -1
- package/package.json +13 -7
- package/dist/action-detect-P7ZE4NEM.js +0 -16
- package/dist/action-detect-P7ZE4NEM.js.map +0 -1
- package/dist/adapter-ZOANORGM.js +0 -799
- package/dist/adapter-ZOANORGM.js.map +0 -1
- package/dist/admin-6SYB6XCZ.js +0 -23
- package/dist/admin-6SYB6XCZ.js.map +0 -1
- package/dist/agent-catalog-FC3HGDEQ.js +0 -11
- package/dist/agent-catalog-FC3HGDEQ.js.map +0 -1
- package/dist/agent-dependencies-4OWBMZWZ.js +0 -24
- package/dist/agent-dependencies-4OWBMZWZ.js.map +0 -1
- package/dist/agent-registry-WT4NXPYG.js +0 -9
- package/dist/agent-registry-WT4NXPYG.js.map +0 -1
- package/dist/agent-store-VZLFPTZU.js +0 -9
- package/dist/agent-store-VZLFPTZU.js.map +0 -1
- package/dist/agents-QO7DKARJ.js +0 -15
- package/dist/agents-QO7DKARJ.js.map +0 -1
- package/dist/api-client-CFQT5U7D.js +0 -14
- package/dist/api-client-CFQT5U7D.js.map +0 -1
- package/dist/autostart-X33OGMX6.js +0 -23
- package/dist/autostart-X33OGMX6.js.map +0 -1
- package/dist/chunk-2CJ46J3C.js +0 -154
- package/dist/chunk-2CJ46J3C.js.map +0 -1
- package/dist/chunk-2HMQOC7N.js +0 -134
- package/dist/chunk-2HMQOC7N.js.map +0 -1
- package/dist/chunk-33RP6K2O.js +0 -435
- package/dist/chunk-33RP6K2O.js.map +0 -1
- package/dist/chunk-34M4OS5P.js +0 -83
- package/dist/chunk-34M4OS5P.js.map +0 -1
- package/dist/chunk-4CTX774K.js +0 -265
- package/dist/chunk-4CTX774K.js.map +0 -1
- package/dist/chunk-7QJS2XBD.js +0 -92
- package/dist/chunk-7QJS2XBD.js.map +0 -1
- package/dist/chunk-BNLGTZ34.js +0 -122
- package/dist/chunk-BNLGTZ34.js.map +0 -1
- package/dist/chunk-CS3KCJ5D.js +0 -4788
- package/dist/chunk-CS3KCJ5D.js.map +0 -1
- package/dist/chunk-GAK6PIBW.js +0 -224
- package/dist/chunk-GAK6PIBW.js.map +0 -1
- package/dist/chunk-I7WC6E5S.js +0 -71
- package/dist/chunk-I7WC6E5S.js.map +0 -1
- package/dist/chunk-J4SJTKIK.js +0 -203
- package/dist/chunk-J4SJTKIK.js.map +0 -1
- package/dist/chunk-JHYXKVV2.js +0 -183
- package/dist/chunk-JHYXKVV2.js.map +0 -1
- package/dist/chunk-JKBFUAJK.js +0 -282
- package/dist/chunk-JKBFUAJK.js.map +0 -1
- package/dist/chunk-KIRH7TUJ.js +0 -219
- package/dist/chunk-KIRH7TUJ.js.map +0 -1
- package/dist/chunk-LBIKITQT.js +0 -22
- package/dist/chunk-LBIKITQT.js.map +0 -1
- package/dist/chunk-LCRLAV4G.js +0 -1085
- package/dist/chunk-LCRLAV4G.js.map +0 -1
- package/dist/chunk-LGP2YGRL.js +0 -4880
- package/dist/chunk-LGP2YGRL.js.map +0 -1
- package/dist/chunk-MKHUZLII.js +0 -738
- package/dist/chunk-MKHUZLII.js.map +0 -1
- package/dist/chunk-NAMYZIS5.js +0 -1
- package/dist/chunk-NAMYZIS5.js.map +0 -1
- package/dist/chunk-NVPG6JCL.js +0 -724
- package/dist/chunk-NVPG6JCL.js.map +0 -1
- package/dist/chunk-O7CPGUAI.js +0 -298
- package/dist/chunk-O7CPGUAI.js.map +0 -1
- package/dist/chunk-OWP7RZ62.js +0 -697
- package/dist/chunk-OWP7RZ62.js.map +0 -1
- package/dist/chunk-S64CB6J3.js +0 -98
- package/dist/chunk-S64CB6J3.js.map +0 -1
- package/dist/chunk-UKT3G5IA.js +0 -484
- package/dist/chunk-UKT3G5IA.js.map +0 -1
- package/dist/chunk-V5GZQEIY.js +0 -101
- package/dist/chunk-V5GZQEIY.js.map +0 -1
- package/dist/chunk-VOIJ6OY4.js +0 -63
- package/dist/chunk-VOIJ6OY4.js.map +0 -1
- package/dist/chunk-VUNV25KB.js +0 -16
- package/dist/chunk-VUNV25KB.js.map +0 -1
- package/dist/chunk-W3EYKZNQ.js +0 -45
- package/dist/chunk-W3EYKZNQ.js.map +0 -1
- package/dist/chunk-WTZDAYZX.js +0 -172
- package/dist/chunk-WTZDAYZX.js.map +0 -1
- package/dist/chunk-XANPHG7W.js +0 -145
- package/dist/chunk-XANPHG7W.js.map +0 -1
- package/dist/config-6S355X75.js +0 -15
- package/dist/config-6S355X75.js.map +0 -1
- package/dist/config-editor-QQTZMWGD.js +0 -13
- package/dist/config-editor-QQTZMWGD.js.map +0 -1
- package/dist/config-registry-AHYI4MYL.js +0 -18
- package/dist/config-registry-AHYI4MYL.js.map +0 -1
- package/dist/daemon-4CS6HMB5.js +0 -30
- package/dist/daemon-4CS6HMB5.js.map +0 -1
- package/dist/discord-OMC52Y54.js +0 -2239
- package/dist/discord-OMC52Y54.js.map +0 -1
- package/dist/dist-UHQK5CXN.js +0 -21151
- package/dist/dist-UHQK5CXN.js.map +0 -1
- package/dist/doctor-HZZ5BSHB.js +0 -10
- package/dist/doctor-HZZ5BSHB.js.map +0 -1
- package/dist/doctor-OLYBO3V3.js +0 -15
- package/dist/doctor-OLYBO3V3.js.map +0 -1
- package/dist/install-cloudflared-Z7VCGOVG.js +0 -33
- package/dist/install-cloudflared-Z7VCGOVG.js.map +0 -1
- package/dist/install-jq-HUYSQWKR.js +0 -32
- package/dist/install-jq-HUYSQWKR.js.map +0 -1
- package/dist/integrate-PNEHRY2I.js +0 -373
- package/dist/integrate-PNEHRY2I.js.map +0 -1
- package/dist/log-NXABYJTT.js +0 -24
- package/dist/log-NXABYJTT.js.map +0 -1
- package/dist/main-XOZCLFUK.js +0 -238
- package/dist/main-XOZCLFUK.js.map +0 -1
- package/dist/menu-YY5MKHEK.js +0 -16
- package/dist/menu-YY5MKHEK.js.map +0 -1
- package/dist/new-session-FEO4J4VU.js +0 -17
- package/dist/new-session-FEO4J4VU.js.map +0 -1
- package/dist/post-upgrade-CJG5I7M2.js +0 -80
- package/dist/post-upgrade-CJG5I7M2.js.map +0 -1
- package/dist/session-IUSI7P5S.js +0 -20
- package/dist/session-IUSI7P5S.js.map +0 -1
- package/dist/settings-RQPAM4KC.js +0 -14
- package/dist/settings-RQPAM4KC.js.map +0 -1
- package/dist/setup-XHS4OMPM.js +0 -37
- package/dist/setup-XHS4OMPM.js.map +0 -1
- package/dist/suggest-7D6B542M.js +0 -38
- package/dist/suggest-7D6B542M.js.map +0 -1
- package/dist/tunnel-service-CJLUH6SZ.js +0 -1174
- package/dist/tunnel-service-CJLUH6SZ.js.map +0 -1
- package/dist/version-NQZBM5M7.js +0 -16
- package/dist/version-NQZBM5M7.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/utils/log.ts","../../src/core/instance/instance-context.ts","../../src/core/config/config-migrations.ts","../../src/core/config/config-registry.ts","../../src/core/config/config.ts","../../src/core/utils/read-text-file.ts","../../src/core/agents/agent-dependencies.ts","../../src/core/agents/agent-registry.ts","../../src/core/utils/install-binary.ts","../../src/plugins/tunnel/providers/install-cloudflared.ts","../../src/plugins/telegram/validators.ts","../../src/core/plugin/plugin-installer.ts","../../src/core/plugin/settings-manager.ts","../../src/core/plugin/terminal-io.ts","../../src/core/plugin/install-context.ts","../../src/cli/api-client.ts","../../src/plugins/api-server/middleware/error-handler.ts","../../src/plugins/api-server/auth/jwt.ts","../../src/plugins/api-server/auth/roles.ts","../../src/plugins/api-server/middleware/auth.ts","../../src/plugins/api-server/server.ts","../../src/plugins/api-server/service.ts","../../src/plugins/api-server/sse-manager.ts","../../src/plugins/api-server/static-server.ts","../../src/cli/version.ts","../../src/plugins/telegram/commands/menu.ts","../../src/cli/integrate.ts","../../src/core/index.ts","../../src/core/channel.ts","../../src/core/utils/streams.ts","../../src/core/utils/stderr-capture.ts","../../src/core/agents/agent-instance.ts","../../src/core/utils/typed-emitter.ts","../../src/core/sessions/terminal-manager.ts","../../src/core/agents/mcp-manager.ts","../../src/core/utils/debug-tracer.ts","../../src/core/agents/agent-manager.ts","../../src/core/sessions/session.ts","../../src/core/sessions/prompt-queue.ts","../../src/core/sessions/permission-gate.ts","../../src/core/utils/extract-file-info.ts","../../src/core/message-transformer.ts","../../src/core/sessions/session-manager.ts","../../src/core/sessions/session-bridge.ts","../../src/core/sessions/session-factory.ts","../../src/core/core.ts","../../src/core/sessions/session-store.ts","../../src/core/agent-switch-handler.ts","../../src/core/agents/agent-catalog.ts","../../src/core/agents/agent-store.ts","../../src/core/agents/agent-installer.ts","../../src/core/event-bus.ts","../../src/core/plugin/plugin-loader.ts","../../src/core/plugin/service-registry.ts","../../src/core/plugin/middleware-chain.ts","../../src/core/plugin/error-tracker.ts","../../src/core/plugin/plugin-context.ts","../../src/core/plugin/plugin-storage.ts","../../src/core/plugin/lifecycle-manager.ts","../../src/core/command-registry.ts","../../src/core/doctor/index.ts","../../src/core/doctor/checks/config.ts","../../src/core/doctor/checks/agents.ts","../../src/core/doctor/checks/telegram.ts","../../src/core/doctor/checks/storage.ts","../../src/core/doctor/checks/workspace.ts","../../src/core/doctor/checks/plugins.ts","../../src/core/doctor/checks/daemon.ts","../../src/core/doctor/checks/tunnel.ts","../../src/core/config/config-editor.ts","../../src/cli/autostart.ts","../../src/cli/daemon.ts","../../src/plugins/notifications/notification.ts","../../src/plugins/file-service/file-service.ts","../../src/plugins/security/security-guard.ts","../../src/plugins/telegram/topic-manager.ts","../../src/plugins/speech/speech-service.ts","../../src/plugins/speech/providers/groq.ts","../../src/plugins/context/context-manager.ts","../../src/plugins/context/context-cache.ts","../../src/plugins/context/context-provider.ts","../../src/plugins/context/entire/checkpoint-reader.ts","../../src/plugins/context/entire/message-cleaner.ts","../../src/plugins/context/entire/conversation-builder.ts","../../src/plugins/context/entire/entire-provider.ts","../../src/core/adapter-primitives/format-types.ts","../../src/core/adapter-primitives/message-formatter.ts","../../src/core/adapter-primitives/messaging-adapter.ts","../../src/core/adapter-primitives/stream-adapter.ts","../../src/core/adapter-primitives/format-utils.ts","../../src/core/adapter-primitives/rendering/renderer.ts","../../src/core/adapter-primitives/primitives/send-queue.ts","../../src/core/adapter-primitives/primitives/draft-manager.ts","../../src/core/adapter-primitives/primitives/tool-call-tracker.ts","../../src/core/adapter-primitives/primitives/activity-tracker.ts","../../src/core/adapter-primitives/primitives/tool-card-state.ts","../../src/core/adapter-primitives/stream-accumulator.ts","../../src/core/adapter-primitives/display-spec-builder.ts","../../src/core/adapter-primitives/output-mode-resolver.ts","../../src/data/product-guide.ts","../../src/plugins/telegram/adapter.ts","../../src/plugins/telegram/topics.ts","../../src/plugins/telegram/commands/new-session.ts","../../src/plugins/telegram/formatting.ts","../../src/plugins/telegram/commands/admin.ts","../../src/plugins/telegram/commands/session.ts","../../src/plugins/telegram/commands/index.ts","../../src/plugins/telegram/commands/agents.ts","../../src/plugins/telegram/commands/integrate.ts","../../src/plugins/telegram/commands/resume.ts","../../src/plugins/telegram/commands/settings.ts","../../src/plugins/telegram/commands/doctor.ts","../../src/plugins/telegram/commands/tunnel.ts","../../src/plugins/telegram/commands/switch.ts","../../src/plugins/telegram/permissions.ts","../../src/plugins/telegram/assistant.ts","../../src/plugins/telegram/activity.ts","../../src/plugins/telegram/action-detect.ts","../../src/plugins/telegram/streaming.ts","../../src/plugins/telegram/draft-manager.ts","../../src/plugins/telegram/skill-command-manager.ts","../../src/plugins/telegram/renderer.ts"],"sourcesContent":["import pino from 'pino'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { LoggingConfig } from '../config/config.js'\n\nexport type Logger = pino.Logger\n\n// --- Default console-only logger (pre-init) ---\nlet rootLogger: pino.Logger = pino({\n level: 'debug',\n transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard' } },\n})\nlet initialized = false\nlet logDir: string | undefined\nlet currentTransport: ReturnType<typeof pino.transport> | undefined\n\nfunction expandHome(p: string): string {\n return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p\n}\n\n// --- Variadic wrapper for backward compatibility ---\nfunction wrapVariadic(logger: pino.Logger) {\n return {\n info: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.info(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.info(args.map(String).join(' '))\n }\n },\n warn: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.warn(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.warn(args.map(String).join(' '))\n }\n },\n error: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.error(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.error(args.map(String).join(' '))\n }\n },\n debug: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.debug(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.debug(args.map(String).join(' '))\n }\n },\n fatal: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.fatal(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.fatal(args.map(String).join(' '))\n }\n },\n child: (bindings: pino.Bindings) => logger.child(bindings),\n }\n}\n\nexport const log = wrapVariadic(rootLogger)\n\n// --- Mute/unmute (suppress pino output during interactive prompts) ---\n\nlet muteCount = 0\nlet savedLevel = 'info'\n\nexport function muteLogger(): void {\n if (muteCount === 0) {\n savedLevel = rootLogger.level\n rootLogger.level = 'silent'\n }\n muteCount++\n}\n\nexport function unmuteLogger(): void {\n muteCount--\n if (muteCount <= 0) {\n muteCount = 0\n rootLogger.level = savedLevel\n }\n}\n\n// --- Public API ---\n\nexport function initLogger(config: LoggingConfig): Logger {\n if (initialized) return rootLogger\n\n const resolvedLogDir = expandHome(config.logDir)\n logDir = resolvedLogDir\n\n try {\n fs.mkdirSync(resolvedLogDir, { recursive: true })\n fs.mkdirSync(path.join(resolvedLogDir, 'sessions'), { recursive: true })\n } catch (err) {\n console.error(`[WARN] Failed to create log directory ${resolvedLogDir}, falling back to console-only:`, err)\n return rootLogger\n }\n\n const transports = pino.transport({\n targets: [\n {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:HH:MM:ss',\n ignore: 'pid,hostname',\n singleLine: true,\n },\n level: config.level,\n },\n {\n target: 'pino-roll',\n options: {\n file: path.join(resolvedLogDir, 'openacp.log'),\n size: config.maxFileSize,\n limit: { count: config.maxFiles },\n },\n level: config.level,\n },\n ],\n })\n\n currentTransport = transports\n rootLogger = pino({ level: config.level }, transports)\n initialized = true\n\n // Update the default log wrapper to use the new root logger\n Object.assign(log, wrapVariadic(rootLogger))\n\n return rootLogger\n}\n\n/** Change log level at runtime. Pino transport targets respect parent level changes automatically. */\nexport function setLogLevel(level: string): void {\n rootLogger.level = level\n}\n\nexport function createChildLogger(context: { module: string; [key: string]: unknown }): Logger {\n // Return a proxy that always delegates to the current rootLogger.\n // This ensures child loggers created at module-level (before initLogger)\n // pick up the initialized logger with pino-pretty transport.\n return new Proxy({} as Logger, {\n get(_target, prop, receiver) {\n const child = rootLogger.child(context)\n const value = Reflect.get(child, prop, receiver)\n return typeof value === 'function' ? value.bind(child) : value\n },\n })\n}\n\nexport function createSessionLogger(sessionId: string, parentLogger: Logger): Logger {\n const sessionLogDir = logDir ? path.join(logDir, 'sessions') : undefined\n if (!sessionLogDir) {\n return parentLogger.child({ sessionId })\n }\n\n try {\n const sessionLogPath = path.join(sessionLogDir, `${sessionId}.log`)\n const dest = pino.destination(sessionLogPath)\n const sessionFileLogger = pino({ level: parentLogger.level }, dest).child({ sessionId })\n\n // Create a logger that writes to both parent (combined) and session file\n const combinedChild = parentLogger.child({ sessionId })\n const originalInfo = combinedChild.info.bind(combinedChild)\n const originalWarn = combinedChild.warn.bind(combinedChild)\n const originalError = combinedChild.error.bind(combinedChild)\n const originalDebug = combinedChild.debug.bind(combinedChild)\n const originalFatal = combinedChild.fatal.bind(combinedChild)\n\n // Proxy log methods to write to both destinations\n combinedChild.info = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.info(objOrMsg, ...rest)\n return originalInfo(objOrMsg, ...rest)\n }) as any\n combinedChild.warn = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.warn(objOrMsg, ...rest)\n return originalWarn(objOrMsg, ...rest)\n }) as any\n combinedChild.error = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.error(objOrMsg, ...rest)\n return originalError(objOrMsg, ...rest)\n }) as any\n combinedChild.debug = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.debug(objOrMsg, ...rest)\n return originalDebug(objOrMsg, ...rest)\n }) as any\n combinedChild.fatal = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.fatal(objOrMsg, ...rest)\n return originalFatal(objOrMsg, ...rest)\n }) as any\n\n // Store dest for cleanup\n ;(combinedChild as any).__sessionDest = dest\n\n return combinedChild\n } catch (err) {\n // Graceful degradation: session file failed, just use combined log\n parentLogger.warn({ sessionId, err }, 'Failed to create session log file, using combined log only')\n return parentLogger.child({ sessionId })\n }\n}\n\nexport function closeSessionLogger(logger: Logger): void {\n const dest = (logger as any).__sessionDest\n if (dest && typeof dest.destroy === 'function') {\n dest.destroy()\n }\n}\n\nexport async function shutdownLogger(): Promise<void> {\n if (!initialized) return\n\n const transport = currentTransport\n\n // Reset state immediately so re-init is possible\n rootLogger = pino({ level: 'debug' })\n Object.assign(log, wrapVariadic(rootLogger))\n currentTransport = undefined\n logDir = undefined\n initialized = false\n\n if (transport) {\n await new Promise<void>((resolve) => {\n const timeout = setTimeout(resolve, 3000)\n transport.on('close', () => {\n clearTimeout(timeout)\n resolve()\n })\n transport.end()\n })\n }\n}\n\nexport async function cleanupOldSessionLogs(retentionDays: number): Promise<void> {\n if (!logDir) return\n\n const sessionsDir = path.join(logDir, 'sessions')\n try {\n const files = await fs.promises.readdir(sessionsDir)\n const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n\n for (const file of files) {\n try {\n const filePath = path.join(sessionsDir, file)\n const stat = await fs.promises.stat(filePath)\n if (stat.mtimeMs < cutoff) {\n await fs.promises.unlink(filePath)\n rootLogger.debug({ file }, 'Deleted old session log')\n }\n } catch (err) {\n rootLogger.warn({ file, err }, 'Failed to delete old session log')\n }\n }\n } catch {\n // Sessions directory doesn't exist — no-op\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport os from 'node:os'\n\nexport interface InstanceContext {\n id: string\n root: string\n isGlobal: boolean\n paths: {\n config: string\n sessions: string\n agents: string\n registryCache: string\n plugins: string\n pluginsData: string\n pluginRegistry: string\n logs: string\n pid: string\n running: string\n apiPort: string\n apiSecret: string\n bin: string\n cache: string\n tunnels: string\n agentsDir: string\n }\n}\n\nexport interface CreateInstanceContextOpts {\n id: string\n root: string\n isGlobal: boolean\n}\n\nexport function createInstanceContext(opts: CreateInstanceContextOpts): InstanceContext {\n const { id, root, isGlobal } = opts\n return {\n id, root, isGlobal,\n paths: {\n config: path.join(root, 'config.json'),\n sessions: path.join(root, 'sessions.json'),\n agents: path.join(root, 'agents.json'),\n registryCache: path.join(root, 'registry-cache.json'),\n plugins: path.join(root, 'plugins'),\n pluginsData: path.join(root, 'plugins', 'data'),\n pluginRegistry: path.join(root, 'plugins.json'),\n logs: path.join(root, 'logs'),\n pid: path.join(root, 'openacp.pid'),\n running: path.join(root, 'running'),\n apiPort: path.join(root, 'api.port'),\n apiSecret: path.join(root, 'api-secret'),\n bin: path.join(root, 'bin'),\n cache: path.join(root, 'cache'),\n tunnels: path.join(root, 'tunnels.json'),\n agentsDir: path.join(root, 'agents'),\n },\n }\n}\n\nexport function generateSlug(name: string): string {\n const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '')\n return slug || 'openacp'\n}\n\nfunction expandHome(p: string): string {\n if (p.startsWith('~')) return path.join(os.homedir(), p.slice(1))\n return p\n}\n\nexport interface ResolveOpts {\n dir?: string\n local?: boolean\n global?: boolean\n cwd?: string\n}\n\nexport function resolveInstanceRoot(opts: ResolveOpts): string | null {\n const cwd = opts.cwd ?? process.cwd()\n if (opts.dir) return path.join(expandHome(opts.dir), '.openacp')\n if (opts.local) return path.join(cwd, '.openacp')\n if (opts.global) return path.join(os.homedir(), '.openacp')\n const localRoot = path.join(cwd, '.openacp')\n if (fs.existsSync(localRoot)) return localRoot\n return null\n}\n\nexport function getGlobalRoot(): string {\n return path.join(os.homedir(), '.openacp')\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createChildLogger } from \"../utils/log.js\";\nimport { getGlobalRoot } from \"../instance/instance-context.js\";\nconst log = createChildLogger({ module: \"config-migrations\" });\n\ntype RawConfig = Record<string, unknown>;\n\nexport interface MigrationContext {\n configDir: string;\n}\n\nexport interface Migration {\n name: string;\n apply: (raw: RawConfig, ctx?: MigrationContext) => boolean; // returns true if config was modified\n}\n\nexport const migrations: Migration[] = [\n {\n name: \"add-tunnel-section\",\n apply(raw) {\n if (raw.tunnel) return false;\n raw.tunnel = {\n enabled: true,\n port: 3100,\n provider: \"cloudflare\",\n options: {},\n storeTtlMinutes: 60,\n auth: { enabled: false },\n };\n log.info(\"Added tunnel section to config (enabled by default with cloudflare)\");\n return true;\n },\n },\n {\n name: \"fix-agent-commands\",\n apply(raw) {\n const COMMAND_MIGRATIONS: Record<string, string[]> = {\n \"claude-agent-acp\": [\"claude\", \"claude-code\"],\n };\n\n const agents = raw.agents;\n if (!agents || typeof agents !== \"object\") return false;\n\n let changed = false;\n for (const [agentName, agentDef] of Object.entries(agents as Record<string, unknown>)) {\n if (!agentDef || typeof agentDef !== \"object\" || !(\"command\" in agentDef)) continue;\n const def = agentDef as Record<string, unknown>;\n if (typeof def.command !== \"string\") continue;\n for (const [correctCmd, legacyCmds] of Object.entries(COMMAND_MIGRATIONS)) {\n if (legacyCmds.includes(def.command as string)) {\n log.warn(\n { agent: agentName, oldCommand: def.command, newCommand: correctCmd },\n `Auto-migrating agent command: \"${def.command}\" → \"${correctCmd}\"`,\n );\n def.command = correctCmd;\n changed = true;\n }\n }\n }\n return changed;\n },\n },\n {\n name: \"migrate-agents-to-store\",\n apply(raw, ctx?) {\n const agentsJsonPath = path.join(ctx?.configDir ?? getGlobalRoot(), \"agents.json\");\n if (fs.existsSync(agentsJsonPath)) return false;\n\n const agents = raw.agents as Record<string, unknown> | undefined;\n if (!agents || Object.keys(agents).length === 0) return false;\n\n const COMMAND_TO_REGISTRY: Record<string, string> = {\n \"claude-agent-acp\": \"claude-acp\",\n \"codex\": \"codex-acp\",\n };\n\n const installed: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(agents)) {\n const cfg = val as Record<string, unknown>;\n const command = typeof cfg.command === \"string\" ? cfg.command : \"\";\n const registryId = COMMAND_TO_REGISTRY[command] ?? null;\n installed[key] = {\n registryId,\n name: key.charAt(0).toUpperCase() + key.slice(1),\n version: \"unknown\",\n distribution: \"custom\",\n command: cfg.command,\n args: cfg.args ?? [],\n env: cfg.env ?? {},\n workingDirectory: cfg.workingDirectory ?? undefined,\n installedAt: new Date().toISOString(),\n binaryPath: null,\n };\n }\n\n fs.mkdirSync(path.dirname(agentsJsonPath), { recursive: true });\n fs.writeFileSync(agentsJsonPath, JSON.stringify({ version: 1, installed }, null, 2));\n\n raw.agents = {};\n return true;\n },\n },\n {\n name: \"add-instance-name\",\n apply(raw) {\n if (raw.instanceName) return false;\n raw.instanceName = \"Main\";\n log.info(\"Added instanceName to config\");\n return true;\n },\n },\n {\n name: \"migrate-display-verbosity-to-output-mode\",\n apply(raw) {\n const channels = raw.channels as Record<string, unknown> | undefined;\n if (!channels) return false;\n let changed = false;\n for (const [, channelCfg] of Object.entries(channels)) {\n if (!channelCfg || typeof channelCfg !== \"object\") continue;\n const cfg = channelCfg as Record<string, unknown>;\n if (cfg.displayVerbosity && !cfg.outputMode) {\n cfg.outputMode = cfg.displayVerbosity;\n changed = true;\n }\n }\n return changed;\n },\n },\n];\n\n/**\n * Apply all migrations to raw config (mutates in place).\n * Returns whether any changes were made.\n */\nexport function applyMigrations(\n raw: RawConfig,\n migrationList: Migration[] = migrations,\n ctx?: MigrationContext,\n): { changed: boolean } {\n let changed = false;\n for (const migration of migrationList) {\n if (migration.apply(raw, ctx)) {\n changed = true;\n }\n }\n return { changed };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Config } from \"./config.js\";\nimport { getGlobalRoot } from \"../instance/instance-context.js\";\n\nexport interface ConfigFieldDef {\n path: string;\n displayName: string;\n group: string;\n type: \"toggle\" | \"select\" | \"number\" | \"string\";\n options?: string[] | ((config: Config) => string[]);\n scope: \"safe\" | \"sensitive\";\n hotReload: boolean;\n}\n\nexport const CONFIG_REGISTRY: ConfigFieldDef[] = [\n {\n path: \"defaultAgent\",\n displayName: \"Default Agent\",\n group: \"agent\",\n type: \"select\",\n options: (config) => {\n try {\n const agentsPath = path.join(getGlobalRoot(), \"agents.json\");\n if (fs.existsSync(agentsPath)) {\n const data = JSON.parse(fs.readFileSync(agentsPath, \"utf-8\"));\n return Object.keys(data.installed ?? {});\n }\n } catch {\n /* fallback */\n }\n return Object.keys(config.agents ?? {});\n },\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"channels.telegram.outputMode\",\n displayName: \"Telegram Output Mode\",\n group: \"display\",\n type: \"select\",\n options: [\"low\", \"medium\", \"high\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"channels.discord.outputMode\",\n displayName: \"Discord Output Mode\",\n group: \"display\",\n type: \"select\",\n options: [\"low\", \"medium\", \"high\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"logging.level\",\n displayName: \"Log Level\",\n group: \"logging\",\n type: \"select\",\n options: [\"silent\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"tunnel.enabled\",\n displayName: \"Tunnel\",\n group: \"tunnel\",\n type: \"toggle\",\n scope: \"safe\",\n hotReload: false,\n },\n {\n path: \"security.maxConcurrentSessions\",\n displayName: \"Max Concurrent Sessions\",\n group: \"security\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"security.sessionTimeoutMinutes\",\n displayName: \"Session Timeout (min)\",\n group: \"security\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"workspace.baseDir\",\n displayName: \"Workspace Directory\",\n group: \"workspace\",\n type: \"string\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"sessionStore.ttlDays\",\n displayName: \"Session Store TTL (days)\",\n group: \"storage\",\n type: \"number\",\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"speech.stt.provider\",\n displayName: \"Speech to Text\",\n group: \"speech\",\n type: \"select\",\n options: [\"groq\"],\n scope: \"safe\",\n hotReload: true,\n },\n {\n path: \"speech.stt.apiKey\",\n displayName: \"STT API Key\",\n group: \"speech\",\n type: \"string\",\n scope: \"sensitive\",\n hotReload: true,\n },\n {\n path: \"agentSwitch.labelHistory\",\n displayName: \"Label Agent in History\",\n group: \"agent\",\n type: \"toggle\",\n scope: \"safe\",\n hotReload: true,\n },\n];\n\nexport function getFieldDef(path: string): ConfigFieldDef | undefined {\n return CONFIG_REGISTRY.find((f) => f.path === path);\n}\n\nexport function getSafeFields(): ConfigFieldDef[] {\n return CONFIG_REGISTRY.filter((f) => f.scope === \"safe\");\n}\n\nexport function isHotReloadable(path: string): boolean {\n const def = getFieldDef(path);\n return def?.hotReload ?? false;\n}\n\nexport function resolveOptions(\n def: ConfigFieldDef,\n config: Config,\n): string[] | undefined {\n if (!def.options) return undefined;\n return typeof def.options === \"function\" ? def.options(config) : def.options;\n}\n\nexport function getConfigValue(config: Config, path: string): unknown {\n const parts = path.split(\".\");\n let current: unknown = config;\n for (const part of parts) {\n if (current && typeof current === \"object\" && part in current) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return current;\n}\n","import { z } from \"zod\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { EventEmitter } from \"node:events\";\nimport { applyMigrations } from \"./config-migrations.js\";\nimport { createChildLogger } from \"../utils/log.js\";\nconst log = createChildLogger({ module: \"config\" });\n\nconst BaseChannelSchema = z\n .object({\n enabled: z.boolean().default(false),\n adapter: z.string().optional(), // package name for plugin adapters\n displayVerbosity: z\n .enum([\"low\", \"medium\", \"high\"])\n .optional(),\n outputMode: z.enum([\"low\", \"medium\", \"high\"]).optional(),\n })\n .passthrough();\n\nconst AgentSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).default([]),\n workingDirectory: z.string().optional(),\n env: z.record(z.string(), z.string()).default({}),\n});\n\nconst LoggingSchema = z\n .object({\n level: z\n .enum([\"silent\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"])\n .default(\"info\"),\n logDir: z.string().default(\"~/.openacp/logs\"),\n maxFileSize: z.union([z.string(), z.number()]).default(\"10m\"),\n maxFiles: z.number().default(7),\n sessionLogRetentionDays: z.number().default(30),\n })\n .default({});\n\nexport type LoggingConfig = z.infer<typeof LoggingSchema>;\n\nconst TunnelAuthSchema = z\n .object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n })\n .default({});\n\nconst TunnelSchema = z\n .object({\n enabled: z.boolean().default(false),\n port: z.number().default(3100),\n provider: z\n .enum([\"cloudflare\", \"ngrok\", \"bore\", \"tailscale\"])\n .default(\"cloudflare\"),\n options: z.record(z.string(), z.unknown()).default({}),\n maxUserTunnels: z.number().default(5),\n storeTtlMinutes: z.number().default(60),\n auth: TunnelAuthSchema,\n })\n .default({});\n\nexport type TunnelConfig = z.infer<typeof TunnelSchema>;\n\n\nconst UsageSchema = z\n .object({\n enabled: z.boolean().default(true),\n monthlyBudget: z.number().optional(),\n warningThreshold: z.number().default(0.8),\n currency: z.string().default(\"USD\"),\n retentionDays: z.number().default(90),\n })\n .default({});\n\nexport type UsageConfig = z.infer<typeof UsageSchema>;\n\nconst SpeechProviderSchema = z\n .object({\n apiKey: z.string().min(1).optional(),\n model: z.string().optional(),\n })\n .passthrough();\n\nconst SpeechSchema = z\n .object({\n stt: z\n .object({\n provider: z.string().nullable().default(null),\n providers: z.record(SpeechProviderSchema).default({}),\n })\n .default({}),\n tts: z\n .object({\n provider: z.string().nullable().default(null),\n providers: z.record(SpeechProviderSchema).default({}),\n })\n .default({}),\n })\n .optional()\n .default({});\n\nexport const ConfigSchema = z.object({\n instanceName: z.string().optional(),\n channels: z\n .object({})\n .catchall(BaseChannelSchema),\n agents: z.record(z.string(), AgentSchema).optional().default({}),\n defaultAgent: z.string(),\n workspace: z\n .object({\n baseDir: z.string().default(\"~/openacp-workspace\"),\n })\n .default({}),\n security: z\n .object({\n allowedUserIds: z.array(z.string()).default([]),\n maxConcurrentSessions: z.number().default(20),\n sessionTimeoutMinutes: z.number().default(60),\n })\n .default({}),\n logging: LoggingSchema,\n runMode: z.enum([\"foreground\", \"daemon\"]).default(\"foreground\"),\n autoStart: z.boolean().default(false),\n api: z\n .object({\n port: z.number().default(21420),\n host: z.string().default(\"127.0.0.1\"),\n })\n .default({}),\n sessionStore: z\n .object({\n ttlDays: z.number().default(30),\n })\n .default({}),\n tunnel: TunnelSchema,\n usage: UsageSchema,\n integrations: z\n .record(\n z.string(),\n z.object({\n installed: z.boolean(),\n installedAt: z.string().optional(),\n }),\n )\n .default({}),\n speech: SpeechSchema,\n outputMode: z.enum([\"low\", \"medium\", \"high\"]).default(\"medium\").optional(),\n agentSwitch: z.object({\n labelHistory: z.boolean().default(true),\n }).default({}),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function expandHome(p: string): string {\n if (p.startsWith(\"~\")) {\n return path.join(os.homedir(), p.slice(1));\n }\n return p;\n}\n\nconst DEFAULT_CONFIG = {\n channels: {\n telegram: {\n enabled: false,\n botToken: \"YOUR_BOT_TOKEN_HERE\",\n chatId: 0,\n notificationTopicId: null,\n assistantTopicId: null,\n },\n discord: {\n enabled: false,\n botToken: \"YOUR_DISCORD_BOT_TOKEN_HERE\",\n guildId: \"\",\n forumChannelId: null,\n notificationChannelId: null,\n assistantThreadId: null,\n },\n },\n agents: {\n claude: { command: \"claude-agent-acp\", args: [], env: {} },\n codex: { command: \"codex\", args: [\"--acp\"], env: {} },\n },\n defaultAgent: \"claude\",\n workspace: { baseDir: \"~/openacp-workspace\" },\n security: {\n allowedUserIds: [],\n maxConcurrentSessions: 20,\n sessionTimeoutMinutes: 60,\n },\n sessionStore: { ttlDays: 30 },\n tunnel: {\n enabled: true,\n port: 3100,\n provider: \"cloudflare\",\n options: {},\n storeTtlMinutes: 60,\n auth: { enabled: false },\n },\n usage: {},\n};\n\nexport class ConfigManager extends EventEmitter {\n private config!: Config;\n private configPath: string;\n\n constructor(configPath?: string) {\n super();\n this.configPath =\n process.env.OPENACP_CONFIG_PATH || configPath || expandHome(\"~/.openacp/config.json\");\n }\n\n async load(): Promise<void> {\n // 1. Ensure directory exists\n const dir = path.dirname(this.configPath);\n fs.mkdirSync(dir, { recursive: true });\n\n // 2. If config file doesn't exist, create default\n if (!fs.existsSync(this.configPath)) {\n fs.writeFileSync(\n this.configPath,\n JSON.stringify(DEFAULT_CONFIG, null, 2),\n );\n log.info({ configPath: this.configPath }, \"Config created\");\n log.info(\n \"Please edit it with your channel credentials (Telegram bot token, Discord bot token, etc.), then restart.\",\n );\n process.exit(1);\n }\n\n // 3. Read and parse\n const raw = JSON.parse(fs.readFileSync(this.configPath, \"utf-8\"));\n\n // 3.5. Auto-migrate config\n const { changed: configUpdated } = applyMigrations(raw, undefined, { configDir: path.dirname(this.configPath) });\n if (configUpdated) {\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));\n }\n\n // 4. Apply env var overrides\n this.applyEnvOverrides(raw);\n\n // 5. Validate with Zod\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n log.error(\"Config validation failed\");\n for (const issue of result.error.issues) {\n log.error(\n { path: issue.path.join(\".\"), message: issue.message },\n \"Validation error\",\n );\n }\n process.exit(1);\n }\n this.config = result.data;\n }\n\n get(): Config {\n return structuredClone(this.config);\n }\n\n async save(\n updates: Record<string, unknown>,\n changePath?: string,\n ): Promise<void> {\n const oldConfig = this.config ? structuredClone(this.config) : undefined;\n // Read current file, merge updates\n const raw = JSON.parse(fs.readFileSync(this.configPath, \"utf-8\"));\n this.deepMerge(raw, updates);\n // Validate BEFORE writing to disk\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n log.error({ errors: result.error.issues }, \"Config validation failed, not saving\");\n return;\n }\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));\n this.config = result.data;\n // Emit change event if path provided\n if (changePath) {\n const { getConfigValue } = await import(\"./config-registry.js\");\n const value = getConfigValue(this.config, changePath);\n const oldValue = oldConfig\n ? getConfigValue(oldConfig, changePath)\n : undefined;\n this.emit(\"config:changed\", { path: changePath, value, oldValue });\n }\n }\n\n resolveWorkspace(input?: string): string {\n if (!input) {\n const resolved = expandHome(this.config.workspace.baseDir);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n if (input.startsWith(\"/\") || input.startsWith(\"~\")) {\n const resolved = expandHome(input);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n // Named workspace → lowercase, under baseDir\n const name = input.toLowerCase();\n const resolved = path.join(expandHome(this.config.workspace.baseDir), name);\n fs.mkdirSync(resolved, { recursive: true });\n return resolved;\n }\n\n async exists(): Promise<boolean> {\n return fs.existsSync(this.configPath);\n }\n\n getConfigPath(): string {\n return this.configPath;\n }\n\n async writeNew(config: Config): Promise<void> {\n const dir = path.dirname(this.configPath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));\n }\n\n private applyEnvOverrides(raw: Record<string, unknown>): void {\n const overrides: [string, string[]][] = [\n [\"OPENACP_TELEGRAM_BOT_TOKEN\", [\"channels\", \"telegram\", \"botToken\"]],\n [\"OPENACP_TELEGRAM_CHAT_ID\", [\"channels\", \"telegram\", \"chatId\"]],\n [\"OPENACP_DISCORD_BOT_TOKEN\", [\"channels\", \"discord\", \"botToken\"]],\n [\"OPENACP_DISCORD_GUILD_ID\", [\"channels\", \"discord\", \"guildId\"]],\n [\"OPENACP_SLACK_BOT_TOKEN\", [\"channels\", \"slack\", \"botToken\"]],\n [\"OPENACP_SLACK_APP_TOKEN\", [\"channels\", \"slack\", \"appToken\"]],\n [\"OPENACP_SLACK_SIGNING_SECRET\", [\"channels\", \"slack\", \"signingSecret\"]],\n [\"OPENACP_DEFAULT_AGENT\", [\"defaultAgent\"]],\n [\"OPENACP_RUN_MODE\", [\"runMode\"]],\n [\"OPENACP_API_PORT\", [\"api\", \"port\"]],\n ];\n for (const [envVar, configPath] of overrides) {\n const value = process.env[envVar];\n if (value !== undefined) {\n let target: Record<string, unknown> = raw;\n for (let i = 0; i < configPath.length - 1; i++) {\n if (!target[configPath[i]]) target[configPath[i]] = {};\n target = target[configPath[i]] as Record<string, unknown>;\n }\n const key = configPath[configPath.length - 1];\n // Convert numeric fields to number\n target[key] =\n key === \"chatId\" || key === \"port\" ? Number(value) : value;\n }\n }\n\n // Logging env var overrides\n if (process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).level =\n process.env.OPENACP_LOG_LEVEL;\n }\n if (process.env.OPENACP_LOG_DIR) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).logDir =\n process.env.OPENACP_LOG_DIR;\n }\n if (process.env.OPENACP_DEBUG && !process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {};\n (raw.logging as Record<string, unknown>).level = \"debug\";\n }\n\n // Tunnel env var overrides\n if (process.env.OPENACP_TUNNEL_ENABLED) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).enabled =\n process.env.OPENACP_TUNNEL_ENABLED === \"true\";\n }\n if (process.env.OPENACP_TUNNEL_PORT) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).port = Number(\n process.env.OPENACP_TUNNEL_PORT,\n );\n }\n if (process.env.OPENACP_TUNNEL_PROVIDER) {\n raw.tunnel = raw.tunnel || {};\n (raw.tunnel as Record<string, unknown>).provider =\n process.env.OPENACP_TUNNEL_PROVIDER;\n }\n\n // Speech env var overrides\n if (process.env.OPENACP_SPEECH_STT_PROVIDER) {\n raw.speech = raw.speech || {};\n const speech = raw.speech as Record<string, unknown>;\n speech.stt = speech.stt || {};\n (speech.stt as Record<string, unknown>).provider =\n process.env.OPENACP_SPEECH_STT_PROVIDER;\n }\n if (process.env.OPENACP_SPEECH_GROQ_API_KEY) {\n raw.speech = raw.speech || {};\n const speech = raw.speech as Record<string, unknown>;\n speech.stt = speech.stt || {};\n const stt = speech.stt as Record<string, unknown>;\n stt.providers = stt.providers || {};\n const providers = stt.providers as Record<string, unknown>;\n providers.groq = providers.groq || {};\n (providers.groq as Record<string, unknown>).apiKey =\n process.env.OPENACP_SPEECH_GROQ_API_KEY;\n }\n }\n\n private deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n ): void {\n for (const key of Object.keys(source)) {\n const val = source[key];\n if (val && typeof val === \"object\" && !Array.isArray(val)) {\n if (!target[key]) target[key] = {};\n this.deepMerge(\n target[key] as Record<string, unknown>,\n val as Record<string, unknown>,\n );\n } else {\n target[key] = val;\n }\n }\n }\n}\n","import fs from \"node:fs\";\n\n/**\n * Read a text file, optionally returning only a range of lines.\n * Pure utility — no dependencies on plugin code.\n */\nexport async function readTextFileWithRange(\n filePath: string,\n options?: { line?: number; limit?: number },\n): Promise<string> {\n const content = await fs.promises.readFile(filePath, \"utf-8\");\n if (!options?.line && !options?.limit) return content;\n const lines = content.split(\"\\n\");\n const start = Math.max(0, (options.line ?? 1) - 1);\n const end = options.limit ? start + options.limit : lines.length;\n return lines.slice(start, end).join(\"\\n\");\n}\n","import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AvailabilityResult } from \"../types.js\";\n\nexport interface AgentDependency {\n command: string;\n label: string;\n installHint: string;\n}\n\nexport interface AgentSetupInfo {\n setupSteps: string[];\n loginCommand?: string;\n}\n\nexport interface AgentIntegrationSpec {\n hookEvent: string;\n settingsPath: string;\n settingsFormat: \"settings_json\" | \"hooks_json\";\n hooksDirPath: string;\n outputFormat: \"plaintext\" | \"json\";\n sessionIdField: string;\n commandsPath?: string;\n handoffCommandName?: string;\n commandFormat?: \"markdown\" | \"skill\";\n sessionIdVar?: string;\n workingDirVar?: string;\n}\n\nexport interface AgentCapability {\n supportsResume: boolean;\n resumeCommand?: (sessionId: string) => string;\n integration?: AgentIntegrationSpec;\n}\n\nconst AGENT_DEPENDENCIES: Record<string, AgentDependency[]> = {\n \"claude-acp\": [\n {\n command: \"claude\",\n label: \"Claude CLI\",\n installHint: \"npm install -g @anthropic-ai/claude-code\",\n },\n ],\n \"codex-acp\": [\n {\n command: \"codex\",\n label: \"Codex CLI\",\n installHint: \"npm install -g @openai/codex\",\n },\n ],\n};\n\nconst AGENT_SETUP: Record<string, AgentSetupInfo> = {\n // --- Agents requiring their own CLI installed first ---\n \"claude-acp\": {\n setupSteps: [\n \"Install Claude CLI: npm install -g @anthropic-ai/claude-code\",\n \"Login: claude login (opens browser for Anthropic account)\",\n ],\n loginCommand: \"claude login\",\n },\n \"codex-acp\": {\n setupSteps: [\n \"Install Codex CLI: npm install -g @openai/codex\",\n \"Login: codex (select 'Sign in with ChatGPT')\",\n \"Or set API key: export OPENAI_API_KEY=<your-key>\",\n ],\n loginCommand: \"codex\",\n },\n\n // --- Agents with built-in auth (npx handles download) ---\n \"gemini\": {\n setupSteps: [\n \"Login with Google: openacp agents run gemini (select 'Sign in with Google')\",\n \"Or set API key: export GEMINI_API_KEY=<key> (get from aistudio.google.com/apikey)\",\n \"Free tier: 60 requests/min, 1000 requests/day\",\n ],\n loginCommand: \"openacp agents run gemini\",\n },\n \"github-copilot-cli\": {\n setupSteps: [\n \"Requires active GitHub Copilot subscription\",\n \"Login: openacp agents run copilot (use /login command inside CLI)\",\n \"Or set token: export GITHUB_TOKEN=<personal-access-token>\",\n ],\n loginCommand: \"openacp agents run copilot\",\n },\n \"cline\": {\n setupSteps: [\n \"Setup: openacp agents run cline (guided API key setup on first run)\",\n \"Supports: Anthropic, OpenAI, Gemini, AWS Bedrock, Azure, Ollama, and more\",\n \"Or set env: export ANTHROPIC_API_KEY=<key> (or OPENAI_API_KEY, etc.)\",\n ],\n loginCommand: \"openacp agents run cline\",\n },\n \"auggie\": {\n setupSteps: [\n \"Login: openacp agents run auggie (opens browser for Augment account on first run)\",\n ],\n loginCommand: \"openacp agents run auggie\",\n },\n \"qwen-code\": {\n setupSteps: [\n \"Login: openacp agents run qwen (use /auth command, select 'Qwen OAuth')\",\n \"Free: 1000 requests/day with Qwen OAuth\",\n \"Or set API key: export OPENAI_API_KEY=<key> in ~/.qwen/settings.json\",\n ],\n loginCommand: \"openacp agents run qwen\",\n },\n\n // --- Agents requiring API keys via env vars ---\n \"kimi\": {\n setupSteps: [\n \"Login: openacp agents run kimi (use /login command inside CLI)\",\n \"Recommended: select 'Kimi Code' for browser-based OAuth\",\n \"Or select another provider and enter API key manually\",\n ],\n loginCommand: \"openacp agents run kimi\",\n },\n \"cursor\": {\n setupSteps: [\n \"Requires active Cursor subscription\",\n \"Login: openacp agents run cursor (opens browser for Cursor account)\",\n ],\n loginCommand: \"openacp agents run cursor\",\n },\n\n // --- Agents with provider selection on first run ---\n \"goose\": {\n setupSteps: [\n \"First run auto-enters setup mode — choose your LLM provider\",\n \"Options: OpenAI, Anthropic, Google Gemini, OpenRouter, or local models\",\n \"Set provider API key: export OPENAI_API_KEY=<key> (or other provider)\",\n \"Reconfigure anytime: goose configure\",\n ],\n },\n \"junie\": {\n setupSteps: [\n \"Bring Your Own Key (BYOK) — provide API key from any supported provider\",\n \"Supports: OpenAI, Anthropic, Gemini, xAI, OpenRouter\",\n \"Free tier: up to $50 with Gemini 3 Flash included\",\n \"Set key via env or first-run setup prompt\",\n ],\n },\n \"kilo\": {\n setupSteps: [\n \"Options: bring your own API keys (Anthropic, OpenAI, Google) or use Kilo Gateway\",\n \"Kilo Gateway: pay-as-you-go, includes free models — no API key needed\",\n \"BYOK: set provider key, e.g. export ANTHROPIC_API_KEY=<key>\",\n ],\n },\n \"mistral-vibe\": {\n setupSteps: [\n \"Get API key from console.mistral.ai/codestral/cli\",\n \"Or sign up for Free/Pro/Team plan at mistral.ai\",\n \"Set key when prompted on first run\",\n ],\n },\n \"deepagents\": {\n setupSteps: [\n \"Powered by LangChain — set your LLM provider API key\",\n \"Example: export OPENAI_API_KEY=<key> or export ANTHROPIC_API_KEY=<key>\",\n ],\n },\n\n // --- Agents that work out of the box (no setup / minimal setup) ---\n \"crow-cli\": {\n setupSteps: [\n \"Requires uvx (Python package runner): pip install uv\",\n \"Bring your own API key for your chosen LLM provider\",\n ],\n },\n \"fast-agent\": {\n setupSteps: [\n \"Requires uvx (Python package runner): pip install uv\",\n \"Configure LLM provider in agent config file\",\n ],\n },\n};\n\nexport function getAgentSetup(registryId: string): AgentSetupInfo | undefined {\n return AGENT_SETUP[registryId];\n}\n\nconst AGENT_CAPABILITIES: Record<string, AgentCapability> = {\n claude: {\n supportsResume: true,\n resumeCommand: (sid) => `claude --resume ${sid}`,\n integration: {\n hookEvent: \"UserPromptSubmit\",\n settingsPath: \"~/.claude/settings.json\",\n settingsFormat: \"settings_json\",\n hooksDirPath: \"~/.claude/hooks/\",\n outputFormat: \"plaintext\",\n sessionIdField: \".session_id\",\n commandsPath: \"~/.claude/commands/\",\n handoffCommandName: \"openacp:handoff\",\n commandFormat: \"markdown\",\n sessionIdVar: \"CLAUDE_SESSION_ID\",\n workingDirVar: \"CLAUDE_WORKING_DIR\",\n },\n },\n cursor: {\n supportsResume: true,\n resumeCommand: (sid) => `cursor --resume ${sid}`,\n integration: {\n hookEvent: \"beforeSubmitPrompt\",\n settingsPath: \"~/.cursor/hooks.json\",\n settingsFormat: \"hooks_json\",\n hooksDirPath: \"~/.cursor/hooks/\",\n outputFormat: \"json\",\n sessionIdField: \".conversation_id\",\n commandsPath: \"~/.cursor/skills/\",\n handoffCommandName: \"openacp-handoff\",\n commandFormat: \"skill\",\n },\n },\n gemini: {\n supportsResume: true,\n resumeCommand: (sid) => `gemini --resume ${sid}`,\n integration: {\n hookEvent: \"BeforeAgent\",\n settingsPath: \"~/.gemini/settings.json\",\n settingsFormat: \"settings_json\",\n hooksDirPath: \"~/.gemini/hooks/\",\n outputFormat: \"json\",\n sessionIdField: \".session_id\",\n },\n },\n cline: {\n supportsResume: true,\n resumeCommand: () => `cline --continue`,\n integration: {\n hookEvent: \"TaskStart\",\n settingsPath: \"~/.cline/settings.json\",\n settingsFormat: \"settings_json\",\n hooksDirPath: \"~/.cline/hooks/\",\n outputFormat: \"json\",\n sessionIdField: \".session_id\",\n },\n },\n codex: {\n supportsResume: true,\n resumeCommand: (sid) => `codex resume ${sid}`,\n },\n kilo: {\n supportsResume: true,\n resumeCommand: () => `kilo --continue`,\n },\n amp: {\n supportsResume: true,\n resumeCommand: (sid) => `amp threads continue ${sid}`,\n },\n};\n\nexport const REGISTRY_AGENT_ALIASES: Record<string, string> = {\n \"claude-acp\": \"claude\",\n \"codex-acp\": \"codex\",\n \"gemini\": \"gemini\",\n \"cursor\": \"cursor\",\n \"github-copilot-cli\": \"copilot\",\n \"cline\": \"cline\",\n \"goose\": \"goose\",\n \"kilo\": \"kilo\",\n \"qwen-code\": \"qwen\",\n};\n\nexport function getAgentAlias(registryId: string): string {\n return REGISTRY_AGENT_ALIASES[registryId] ?? registryId;\n}\n\nexport function getAgentDependencies(registryId: string): AgentDependency[] {\n return AGENT_DEPENDENCIES[registryId] ?? [];\n}\n\nexport function getAgentCapabilities(agentName: string): AgentCapability {\n return AGENT_CAPABILITIES[agentName] ?? { supportsResume: false };\n}\n\nexport function listAgentsWithIntegration(): string[] {\n return Object.entries(AGENT_CAPABILITIES)\n .filter(([, cap]) => cap.integration != null)\n .map(([key]) => key);\n}\n\nexport function commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n // Check node_modules/.bin (walks up from cwd)\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nexport function checkDependencies(registryId: string): AvailabilityResult {\n const deps = getAgentDependencies(registryId);\n if (deps.length === 0) return { available: true };\n\n const missing = deps.filter((d) => !commandExists(d.command));\n if (missing.length === 0) return { available: true };\n\n return {\n available: false,\n reason: `Requires: ${missing.map((m) => m.label).join(\", \")}`,\n missing: missing.map((m) => ({ label: m.label, installHint: m.installHint })),\n };\n}\n\nexport function checkRuntimeAvailable(runtime: \"npx\" | \"uvx\"): boolean {\n return commandExists(runtime);\n}\n","// Re-export from new consolidated module for backward compatibility\nexport { getAgentCapabilities } from \"./agent-dependencies.js\";\nexport type { AgentCapability } from \"./agent-dependencies.js\";\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport https from 'node:https'\nimport os from 'node:os'\nimport { execSync } from 'node:child_process'\nimport { createChildLogger } from './log.js'\nimport { commandExists } from '../agents/agent-dependencies.js'\n\nconst log = createChildLogger({ module: 'binary-installer' })\n\nconst DEFAULT_BIN_DIR = path.join(os.homedir(), '.openacp', 'bin')\nconst IS_WINDOWS = os.platform() === 'win32'\n\nexport interface BinarySpec {\n name: string\n /** GitHub base URL for releases, e.g. \"https://github.com/jqlang/jq/releases/latest/download\" */\n githubBaseUrl: string\n /** Platform → arch → filename mapping */\n platforms: Record<string, Record<string, string>>\n /** If true, downloaded file is a .tgz archive that needs extraction */\n isArchive?: (url: string) => boolean\n}\n\nfunction downloadFile(url: string, dest: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const file = fs.createWriteStream(dest)\n\n const cleanup = () => {\n try { if (fs.existsSync(dest)) fs.unlinkSync(dest) } catch { /* ignore */ }\n }\n\n https.get(url, (response) => {\n if (response.statusCode === 301 || response.statusCode === 302) {\n file.close(() => {\n cleanup()\n downloadFile(response.headers.location!, dest).then(resolve).catch(reject)\n })\n return\n }\n\n if (response.statusCode !== 200) {\n file.close(() => {\n cleanup()\n reject(new Error(`Download failed with status ${response.statusCode}`))\n })\n return\n }\n\n response.pipe(file)\n file.on('finish', () => file.close(() => resolve(dest)))\n file.on('error', (err) => {\n file.close(() => {\n cleanup()\n reject(err)\n })\n })\n }).on('error', (err) => {\n file.close(() => {\n cleanup()\n reject(err)\n })\n })\n })\n}\n\nfunction getDownloadUrl(spec: BinarySpec): string {\n const platform = os.platform()\n const arch = os.arch()\n const mapping = spec.platforms[platform]\n if (!mapping) throw new Error(`${spec.name}: unsupported platform ${platform}`)\n const binary = mapping[arch]\n if (!binary) throw new Error(`${spec.name}: unsupported architecture ${arch} for ${platform}`)\n return `${spec.githubBaseUrl}/${binary}`\n}\n\n/**\n * Ensure a binary is available.\n * 1. Check PATH first (respects user's system install)\n * 2. Check ~/.openacp/bin/\n * 3. Download from GitHub releases\n */\nexport async function ensureBinary(spec: BinarySpec, binDir?: string): Promise<string> {\n const resolvedBinDir = binDir ?? DEFAULT_BIN_DIR\n const binName = IS_WINDOWS ? `${spec.name}.exe` : spec.name\n const binPath = path.join(resolvedBinDir, binName)\n\n // 1. Check PATH first\n if (commandExists(spec.name)) {\n log.debug({ name: spec.name }, 'Found in PATH')\n return spec.name\n }\n\n // 2. Check our bin directory\n if (fs.existsSync(binPath)) {\n if (!IS_WINDOWS) fs.chmodSync(binPath, '755')\n log.debug({ name: spec.name, path: binPath }, 'Found in ~/.openacp/bin')\n return binPath\n }\n\n // 3. Download\n log.info({ name: spec.name }, 'Not found, downloading from GitHub...')\n fs.mkdirSync(resolvedBinDir, { recursive: true })\n\n const url = getDownloadUrl(spec)\n const isArchive = spec.isArchive?.(url) ?? false\n const downloadDest = isArchive ? path.join(resolvedBinDir, `${spec.name}.tgz`) : binPath\n\n await downloadFile(url, downloadDest)\n\n if (isArchive) {\n execSync(`tar -xzf \"${downloadDest}\" -C \"${resolvedBinDir}\"`, { stdio: 'pipe' })\n try { fs.unlinkSync(downloadDest) } catch { /* ignore */ }\n }\n\n // Validate the binary was actually produced\n if (!fs.existsSync(binPath)) {\n throw new Error(`${spec.name}: binary not found at ${binPath} after download/extraction. The archive structure may have changed.`)\n }\n\n if (!IS_WINDOWS) {\n fs.chmodSync(binPath, '755')\n }\n\n log.info({ name: spec.name, path: binPath }, 'Installed successfully')\n return binPath\n}\n","import { ensureBinary, type BinarySpec } from '../../../core/utils/install-binary.js'\n\nexport const CLOUDFLARED_SPEC: BinarySpec = {\n name: 'cloudflared',\n githubBaseUrl: 'https://github.com/cloudflare/cloudflared/releases/latest/download',\n platforms: {\n darwin: {\n x64: 'cloudflared-darwin-amd64.tgz',\n arm64: 'cloudflared-darwin-arm64.tgz',\n },\n win32: {\n x64: 'cloudflared-windows-amd64.exe',\n },\n linux: {\n x64: 'cloudflared-linux-amd64',\n arm64: 'cloudflared-linux-arm64',\n },\n },\n isArchive: (url) => url.endsWith('.tgz'),\n}\n\nexport async function ensureCloudflared(): Promise<string> {\n return ensureBinary(CLOUDFLARED_SPEC)\n}\n","export async function validateBotToken(\n token: string,\n): Promise<\n | { ok: true; botName: string; botUsername: string }\n | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { first_name: string; username: string };\n description?: string;\n };\n if (data.ok && data.result) {\n return {\n ok: true,\n botName: data.result.first_name,\n botUsername: data.result.username,\n };\n }\n return { ok: false, error: data.description || \"Invalid token\" };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateChatId(\n token: string,\n chatId: number,\n): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { title: string; type: string; is_forum?: boolean };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || \"Invalid chat ID\" };\n }\n if (data.result.type !== \"supergroup\") {\n return {\n ok: false,\n error: `Chat is \"${data.result.type}\", must be a supergroup`,\n };\n }\n return {\n ok: true,\n title: data.result.title,\n isForum: data.result.is_forum === true,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateBotAdmin(\n token: string,\n chatId: number,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n try {\n // Get bot's own user ID\n const meRes = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const meData = (await meRes.json()) as {\n ok: boolean;\n result?: { id: number };\n };\n if (!meData.ok || !meData.result) {\n return { ok: false, error: \"Could not retrieve bot info\" };\n }\n\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getChatMember`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId, user_id: meData.result.id }),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: { status: string };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return {\n ok: false,\n error: data.description || \"Could not check bot membership\",\n };\n }\n\n const { status } = data.result;\n if (status === \"administrator\" || status === \"creator\") {\n return { ok: true };\n }\n return {\n ok: false,\n error: `Bot is \"${status}\" in this group. It must be an admin. Please promote the bot to admin in group settings.`,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n","import { exec } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport * as fs from 'node:fs/promises'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nconst execAsync = promisify(exec)\n\n/**\n * Import a package resolved from a specific directory (not the project root).\n * Reads the package's package.json to find the ESM entry point, then imports by file path.\n */\nexport async function importFromDir(packageName: string, dir: string): Promise<any> {\n const pkgDir = path.join(dir, 'node_modules', ...packageName.split('/'))\n const pkgJsonPath = path.join(pkgDir, 'package.json')\n\n let pkgJson: Record<string, any>\n try {\n pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'))\n } catch (err) {\n throw new Error(`Cannot read package.json for \"${packageName}\" at ${pkgJsonPath}: ${(err as Error).message}`)\n }\n\n // Resolve entry: exports[\".\"].import > main > index.js\n let entry: string\n const exportsMain = pkgJson.exports?.['.']\n if (typeof exportsMain === 'string') {\n entry = exportsMain\n } else if (exportsMain?.import) {\n entry = exportsMain.import\n } else {\n entry = pkgJson.main ?? 'index.js'\n }\n\n const entryPath = path.join(pkgDir, entry)\n try {\n await fs.access(entryPath)\n } catch {\n throw new Error(`Entry point \"${entry}\" not found for \"${packageName}\" at ${entryPath}`)\n }\n\n return import(pathToFileURL(entryPath).href)\n}\n\n/** Valid npm package name: optional @scope/, alphanumeric/hyphens/dots, optional @version */\nconst VALID_NPM_NAME = /^(@[a-z0-9][\\w.-]*\\/)?[a-z0-9][\\w.-]*(@[\\w.^~>=<|-]+)?$/i;\n\n/**\n * Install an npm package to the plugins directory and return the loaded module.\n * Tries to import first; if not installed, runs npm install asynchronously.\n */\nexport async function installNpmPlugin(packageName: string, pluginsDir?: string): Promise<any> {\n if (!VALID_NPM_NAME.test(packageName)) {\n throw new Error(`Invalid package name: \"${packageName}\". Must be a valid npm package name.`);\n }\n\n const dir = pluginsDir ?? path.join(os.homedir(), '.openacp', 'plugins')\n\n // Try import from plugins dir first — already installed\n try {\n return await importFromDir(packageName, dir)\n } catch {\n // Not installed, proceed with install\n }\n\n await execAsync(`npm install ${packageName} --prefix \"${dir}\" --save`, {\n timeout: 60000,\n })\n\n return await importFromDir(packageName, dir)\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { SettingsAPI } from './types.js'\nimport type { ZodSchema } from 'zod'\n\nexport interface ValidationResult {\n valid: boolean\n errors?: string[]\n}\n\nexport class SettingsManager {\n constructor(private basePath: string) {}\n\n getBasePath(): string {\n return this.basePath\n }\n\n createAPI(pluginName: string): SettingsAPI {\n const settingsPath = this.getSettingsPath(pluginName)\n return new SettingsAPIImpl(settingsPath)\n }\n\n async loadSettings(pluginName: string): Promise<Record<string, unknown>> {\n const settingsPath = this.getSettingsPath(pluginName)\n try {\n const content = fs.readFileSync(settingsPath, 'utf-8')\n return JSON.parse(content)\n } catch {\n return {}\n }\n }\n\n validateSettings(\n _pluginName: string,\n settings: unknown,\n schema?: ZodSchema,\n ): ValidationResult {\n if (!schema) return { valid: true }\n const result = schema.safeParse(settings)\n if (result.success) return { valid: true }\n return {\n valid: false,\n errors: result.error.errors.map(\n (e: { path: (string | number)[]; message: string }) =>\n `${e.path.join('.')}: ${e.message}`,\n ),\n }\n }\n\n getSettingsPath(pluginName: string): string {\n return path.join(this.basePath, pluginName, 'settings.json')\n }\n\n async getPluginSettings(pluginName: string): Promise<Record<string, unknown>> {\n return this.loadSettings(pluginName)\n }\n\n async updatePluginSettings(pluginName: string, updates: Record<string, unknown>): Promise<void> {\n const api = this.createAPI(pluginName)\n const current = await api.getAll()\n await api.setAll({ ...current, ...updates })\n }\n}\n\nclass SettingsAPIImpl implements SettingsAPI {\n private cache: Record<string, unknown> | null = null\n\n constructor(private settingsPath: string) {}\n\n private readFile(): Record<string, unknown> {\n if (this.cache !== null) return this.cache\n try {\n const content = fs.readFileSync(this.settingsPath, 'utf-8')\n this.cache = JSON.parse(content)\n return this.cache!\n } catch {\n this.cache = {}\n return this.cache\n }\n }\n\n private writeFile(data: Record<string, unknown>): void {\n const dir = path.dirname(this.settingsPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(this.settingsPath, JSON.stringify(data, null, 2))\n this.cache = data\n }\n\n async get<T = unknown>(key: string): Promise<T | undefined> {\n const data = this.readFile()\n return data[key] as T | undefined\n }\n\n async set<T = unknown>(key: string, value: T): Promise<void> {\n const data = this.readFile()\n data[key] = value\n this.writeFile(data)\n }\n\n async getAll(): Promise<Record<string, unknown>> {\n return { ...this.readFile() }\n }\n\n async setAll(settings: Record<string, unknown>): Promise<void> {\n this.writeFile({ ...settings })\n }\n\n async delete(key: string): Promise<void> {\n const data = this.readFile()\n delete data[key]\n this.writeFile(data)\n }\n\n async clear(): Promise<void> {\n this.writeFile({})\n }\n\n async has(key: string): Promise<boolean> {\n const data = this.readFile()\n return key in data\n }\n}\n","import * as clack from '@clack/prompts'\nimport type { TerminalIO } from './types.js'\n\nfunction isCancel(value: unknown): value is symbol {\n return typeof value === 'symbol'\n}\n\nfunction guardCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n throw new Error('cancelled')\n }\n return value as T\n}\n\nexport function createTerminalIO(): TerminalIO {\n return {\n async text(opts) {\n const result = await clack.text(opts as Parameters<typeof clack.text>[0])\n return guardCancel(result)\n },\n async select<T>(opts: {\n message: string\n options: { value: T; label: string; hint?: string }[]\n }): Promise<T> {\n const result = await clack.select(opts as Parameters<typeof clack.select>[0])\n return guardCancel(result) as T\n },\n async confirm(opts) {\n const result = await clack.confirm(opts as Parameters<typeof clack.confirm>[0])\n return guardCancel(result)\n },\n async password(opts) {\n const result = await clack.password(opts as Parameters<typeof clack.password>[0])\n return guardCancel(result)\n },\n async multiselect<T>(opts: {\n message: string\n options: { value: T; label: string; hint?: string }[]\n required?: boolean\n }): Promise<T[]> {\n const result = await clack.multiselect(opts as Parameters<typeof clack.multiselect>[0])\n return guardCancel(result) as T[]\n },\n log: {\n info: (msg) => clack.log.info(msg),\n success: (msg) => clack.log.success(msg),\n warning: (msg) => clack.log.warning(msg),\n error: (msg) => clack.log.error(msg),\n step: (msg) => clack.log.step(msg),\n },\n spinner() {\n const s = clack.spinner()\n return {\n start: (msg: string) => s.start(msg),\n stop: (msg?: string) => s.stop(msg),\n fail: (msg?: string) => s.stop(msg ?? 'Failed'),\n }\n },\n note: (msg, title) => clack.note(msg, title),\n cancel: (msg) => clack.cancel(msg),\n }\n}\n","import path from 'node:path'\nimport type { InstallContext } from './types.js'\nimport type { SettingsManager } from './settings-manager.js'\nimport { createTerminalIO } from './terminal-io.js'\nimport { log as rootLog } from '../utils/log.js'\n\nexport interface CreateInstallContextOpts {\n pluginName: string\n settingsManager: SettingsManager\n basePath: string\n legacyConfig?: Record<string, unknown>\n instanceRoot?: string\n}\n\nexport function createInstallContext(opts: CreateInstallContextOpts): InstallContext {\n const { pluginName, settingsManager, basePath, legacyConfig, instanceRoot } = opts\n const dataDir = path.join(basePath, pluginName, 'data')\n\n return {\n pluginName,\n terminal: createTerminalIO(),\n settings: settingsManager.createAPI(pluginName),\n legacyConfig,\n dataDir,\n log: rootLog.child({ plugin: pluginName }),\n instanceRoot,\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\n\nconst DEFAULT_ROOT = path.join(os.homedir(), '.openacp')\n\nfunction defaultPortFile(root?: string): string {\n return path.join(root ?? DEFAULT_ROOT, 'api.port')\n}\n\nfunction defaultSecretFile(root?: string): string {\n return path.join(root ?? DEFAULT_ROOT, 'api-secret')\n}\n\nexport function readApiPort(portFilePath?: string, instanceRoot?: string): number | null {\n const filePath = portFilePath ?? defaultPortFile(instanceRoot)\n try {\n const content = fs.readFileSync(filePath, 'utf-8').trim()\n const port = parseInt(content, 10)\n return isNaN(port) ? null : port\n } catch {\n return null\n }\n}\n\nexport function readApiSecret(secretFilePath?: string, instanceRoot?: string): string | null {\n const filePath = secretFilePath ?? defaultSecretFile(instanceRoot)\n try {\n const content = fs.readFileSync(filePath, 'utf-8').trim()\n return content || null\n } catch {\n return null\n }\n}\n\nexport function removeStalePortFile(portFilePath?: string, instanceRoot?: string): void {\n const filePath = portFilePath ?? defaultPortFile(instanceRoot)\n try {\n fs.unlinkSync(filePath)\n } catch {\n // ignore\n }\n}\n\nexport async function apiCall(\n port: number,\n urlPath: string,\n options?: RequestInit,\n instanceRoot?: string,\n): Promise<Response> {\n const secret = readApiSecret(undefined, instanceRoot)\n const headers = new Headers(options?.headers)\n if (secret) {\n headers.set('Authorization', `Bearer ${secret}`)\n }\n return fetch(`http://127.0.0.1:${port}${urlPath}`, { ...options, headers })\n}\n","import type { FastifyError, FastifyReply, FastifyRequest } from 'fastify';\nimport { ZodError } from 'zod';\n\nexport interface ApiErrorResponse {\n error: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n };\n}\n\nexport class NotFoundError extends Error {\n constructor(\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = 'NotFoundError';\n }\n}\n\nexport class BadRequestError extends Error {\n constructor(\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = 'BadRequestError';\n }\n}\n\nexport class AuthError extends Error {\n constructor(\n public code: string,\n message: string,\n public statusCode: number = 401,\n ) {\n super(message);\n this.name = 'AuthError';\n }\n}\n\nexport function globalErrorHandler(\n error: FastifyError | Error,\n _request: FastifyRequest,\n reply: FastifyReply,\n): void {\n if (error instanceof ZodError) {\n reply.status(400).send({\n error: {\n code: 'VALIDATION_ERROR',\n message: error.errors.map((e) => e.message).join(', '),\n statusCode: 400,\n details: error.errors,\n },\n });\n return;\n }\n\n if (error instanceof BadRequestError) {\n reply.status(400).send({\n error: {\n code: error.code,\n message: error.message,\n statusCode: 400,\n },\n });\n return;\n }\n\n if (error instanceof NotFoundError) {\n reply.status(404).send({\n error: {\n code: error.code,\n message: error.message,\n statusCode: 404,\n },\n });\n return;\n }\n\n if (error instanceof AuthError) {\n reply.status(error.statusCode).send({\n error: {\n code: error.code,\n message: error.message,\n statusCode: error.statusCode,\n },\n });\n return;\n }\n\n reply.status(500).send({\n error: {\n code: 'INTERNAL_ERROR',\n message: 'Internal server error',\n statusCode: 500,\n },\n });\n}\n","import jwt from 'jsonwebtoken';\nimport type { SignOptions } from 'jsonwebtoken';\nimport type { JwtPayload } from './types.js';\n\nexport interface SignPayload {\n sub: string;\n role: string;\n scopes?: string[];\n rfd: number;\n}\n\nexport function signToken(payload: SignPayload, secret: string, expiresIn: string): string {\n const opts: SignOptions = { algorithm: 'HS256', expiresIn: expiresIn as SignOptions['expiresIn'] };\n return jwt.sign(payload, secret, opts);\n}\n\nexport function verifyToken(token: string, secret: string): JwtPayload {\n return jwt.verify(token, secret, { algorithms: ['HS256'] }) as JwtPayload;\n}\n\nexport function verifyForRefresh(token: string, secret: string): JwtPayload {\n return jwt.verify(token, secret, { algorithms: ['HS256'], ignoreExpiration: true }) as JwtPayload;\n}\n","export const ROLES = {\n admin: ['*'],\n operator: [\n 'sessions:read', 'sessions:write', 'sessions:prompt', 'sessions:permission',\n 'agents:read', 'commands:execute', 'system:health', 'config:read',\n ],\n viewer: ['sessions:read', 'agents:read', 'system:health'],\n} as const;\n\nexport type RoleName = keyof typeof ROLES;\n\nexport function isValidRole(role: string): role is RoleName {\n return role in ROLES;\n}\n\nexport function getRoleScopes(role: string): string[] {\n if (!isValidRole(role)) return [];\n return [...ROLES[role]];\n}\n\nexport function hasScope(userScopes: string[], requiredScope: string): boolean {\n if (userScopes.includes('*')) return true;\n return userScopes.includes(requiredScope);\n}\n","import type { FastifyReply, FastifyRequest, preHandlerHookHandler } from 'fastify';\nimport { createHmac, timingSafeEqual } from 'node:crypto';\nimport { AuthError } from './error-handler.js';\nimport { verifyToken } from '../auth/jwt.js';\nimport { getRoleScopes } from '../auth/roles.js';\nimport type { TokenStore } from '../auth/token-store.js';\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n auth: {\n type: 'secret' | 'jwt';\n tokenId?: string;\n role: string;\n scopes: string[];\n };\n }\n}\n\nfunction constantTimeSecretCheck(token: string, secret: string): boolean {\n // Hash both to fixed-length to prevent length leaking\n const tokenHash = createHmac('sha256', 'openacp-auth').update(token).digest();\n const secretHash = createHmac('sha256', 'openacp-auth').update(secret).digest();\n return timingSafeEqual(tokenHash, secretHash);\n}\n\nexport function createAuthPreHandler(\n getSecret: () => string,\n getJwtSecret: () => string,\n tokenStore: TokenStore,\n): preHandlerHookHandler {\n return async function authPreHandler(request: FastifyRequest, _reply: FastifyReply) {\n const authHeader = request.headers.authorization;\n const queryToken = (request.query as Record<string, string>)?.token;\n const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : queryToken;\n\n if (!token) {\n throw new AuthError('UNAUTHORIZED', 'Missing authentication token');\n }\n\n // 1. Check secret token (constant-time compare) — full admin access\n const secret = getSecret();\n if (constantTimeSecretCheck(token, secret)) {\n request.auth = { type: 'secret', role: 'admin', scopes: ['*'] };\n return;\n }\n\n // 2. Try JWT verification\n let payload;\n try {\n const jwtSecret = getJwtSecret();\n payload = verifyToken(token, jwtSecret);\n } catch {\n throw new AuthError('UNAUTHORIZED', 'Invalid authentication token');\n }\n\n // 3. Check if token is revoked in TokenStore\n const stored = tokenStore.get(payload.sub);\n if (!stored || stored.revoked) {\n throw new AuthError('UNAUTHORIZED', 'Token has been revoked');\n }\n\n // 4. Update lastUsedAt\n tokenStore.updateLastUsed(payload.sub);\n\n // 5. Resolve scopes from token override or role defaults\n const scopes = payload.scopes ?? getRoleScopes(payload.role);\n\n request.auth = {\n type: 'jwt',\n tokenId: payload.sub,\n role: payload.role,\n scopes,\n };\n };\n}\n\nexport function requireScopes(...scopes: string[]): preHandlerHookHandler {\n return async function scopeCheck(request: FastifyRequest, _reply: FastifyReply) {\n const { scopes: userScopes } = request.auth;\n if (userScopes.includes('*')) return;\n\n const missing = scopes.filter((s) => !userScopes.includes(s));\n if (missing.length > 0) {\n throw new AuthError('FORBIDDEN', `Missing scopes: ${missing.join(', ')}`, 403);\n }\n };\n}\n\nexport function requireRole(role: string): preHandlerHookHandler {\n const roleHierarchy: Record<string, number> = { viewer: 0, operator: 1, admin: 2 };\n\n return async function roleCheck(request: FastifyRequest, _reply: FastifyReply) {\n const userLevel = roleHierarchy[request.auth.role] ?? -1;\n const requiredLevel = roleHierarchy[role] ?? 999;\n\n if (userLevel < requiredLevel) {\n throw new AuthError('FORBIDDEN', `Requires ${role} role`, 403);\n }\n };\n}\n","import Fastify, { type FastifyInstance, type FastifyPluginAsync } from 'fastify';\nimport fastifyCors from '@fastify/cors';\nimport fastifySwagger from '@fastify/swagger';\nimport fastifySwaggerUi from '@fastify/swagger-ui';\nimport fastifyRateLimit from '@fastify/rate-limit';\nimport { serializerCompiler, validatorCompiler } from 'fastify-type-provider-zod';\nimport { globalErrorHandler } from './middleware/error-handler.js';\nimport { createAuthPreHandler } from './middleware/auth.js';\n\nexport interface ApiServerOptions {\n port: number;\n host: string;\n getSecret: () => string;\n getJwtSecret: () => string;\n tokenStore: import('./auth/token-store.js').TokenStore;\n logger?: boolean;\n}\n\nexport interface ApiServerInstance {\n app: FastifyInstance;\n start(): Promise<{ port: number; host: string }>;\n stop(): Promise<void>;\n registerPlugin(prefix: string, plugin: FastifyPluginAsync, opts?: { auth?: boolean }): void;\n}\n\nexport async function createApiServer(options: ApiServerOptions): Promise<ApiServerInstance> {\n const app = Fastify({ logger: options.logger ?? false, forceCloseConnections: true });\n\n // Zod validation\n app.setValidatorCompiler(validatorCompiler);\n app.setSerializerCompiler(serializerCompiler);\n\n // Plugins\n await app.register(fastifyCors, {\n origin: (origin, cb) => {\n // Allow requests with no origin (curl, native apps) or localhost\n if (!origin || origin.startsWith('http://localhost') || origin.startsWith('http://127.0.0.1')) {\n cb(null, true);\n } else {\n cb(null, false);\n }\n },\n credentials: true,\n });\n await app.register(fastifyRateLimit, { max: 100, timeWindow: '1 minute' });\n await app.register(fastifySwagger, {\n openapi: {\n info: { title: 'OpenACP API', version: '1.0.0' },\n components: {\n securitySchemes: {\n bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },\n },\n },\n },\n });\n await app.register(fastifySwaggerUi, { routePrefix: '/api/docs' });\n\n // Global error handler\n app.setErrorHandler(globalErrorHandler);\n\n // Backward-compatible redirects: /api/* → /api/v1/*\n app.addHook('onRequest', async (request, reply) => {\n const url = request.url;\n if (url.startsWith('/api/') && !url.startsWith('/api/v1/') && !url.startsWith('/api/docs')) {\n const newUrl = url.replace('/api/', '/api/v1/');\n return reply.redirect(newUrl, 308);\n }\n });\n\n // Auth pre-handler\n const authPreHandler = createAuthPreHandler(options.getSecret, options.getJwtSecret, options.tokenStore);\n\n // Decorate request with auth object\n app.decorateRequest('auth', null, []);\n\n return {\n app,\n\n registerPlugin(prefix: string, plugin: FastifyPluginAsync, opts?: { auth?: boolean }) {\n const wrappedPlugin: FastifyPluginAsync = async (pluginApp, pluginOpts) => {\n if (opts?.auth !== false) {\n pluginApp.addHook('onRequest', authPreHandler);\n }\n await plugin(pluginApp, pluginOpts);\n };\n app.register(wrappedPlugin, { prefix });\n },\n\n async start() {\n await app.ready();\n\n // Auto-detect available port: retry +1 up to 10 times on EADDRINUSE\n const maxRetries = 10;\n let port = options.port;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const address = await app.listen({ port, host: options.host });\n const url = new URL(address);\n return { port: Number(url.port), host: url.hostname };\n } catch (err: any) {\n if (err?.code === 'EADDRINUSE' && attempt < maxRetries && port < 65535) {\n port++;\n continue;\n }\n throw err;\n }\n }\n throw new Error(`All ports ${options.port}-${port} in use`);\n },\n\n async stop() {\n await app.close();\n },\n };\n}\n","import type { FastifyPluginAsync, preHandlerHookHandler } from 'fastify';\nimport type { ApiServerInstance } from './server.js';\nimport { requireScopes, requireRole } from './middleware/auth.js';\n\nexport interface ApiServerService {\n registerPlugin(prefix: string, plugin: FastifyPluginAsync, opts?: { auth?: boolean }): void;\n authPreHandler: preHandlerHookHandler;\n requireScopes(...scopes: string[]): preHandlerHookHandler;\n requireRole(role: string): preHandlerHookHandler;\n getPort(): number;\n getBaseUrl(): string;\n getTunnelUrl(): string | null;\n}\n\nexport function createApiServerService(\n server: ApiServerInstance,\n getPort: () => number,\n getBaseUrl: () => string,\n getTunnelUrl: () => string | null,\n authPreHandler: preHandlerHookHandler,\n): ApiServerService {\n return {\n registerPlugin: server.registerPlugin.bind(server),\n authPreHandler,\n requireScopes,\n requireRole,\n getPort,\n getBaseUrl,\n getTunnelUrl,\n };\n}\n","import * as http from \"node:http\";\nimport type { FastifyRequest, FastifyReply } from 'fastify';\nimport type { EventBus, EventBusEvents } from \"../../core/event-bus.js\";\n\ninterface SSEResponse extends http.ServerResponse {\n sessionFilter?: string;\n}\n\ninterface SessionStats {\n active: number;\n total: number;\n}\n\nexport class SSEManager {\n private sseConnections = new Set<http.ServerResponse>();\n private sseCleanupHandlers = new Map<http.ServerResponse, () => void>();\n private healthInterval?: ReturnType<typeof setInterval>;\n private boundHandlers: Array<{\n event: keyof EventBusEvents;\n handler: (data: unknown) => void;\n }> = [];\n\n constructor(\n private eventBus: EventBus | undefined,\n private getSessionStats: () => SessionStats,\n private startedAt: number,\n ) {}\n\n setup(): void {\n if (!this.eventBus) return;\n\n const events = [\n \"session:created\",\n \"session:updated\",\n \"session:deleted\",\n \"agent:event\",\n \"permission:request\",\n ] as const;\n\n for (const eventName of events) {\n const handler = (data: unknown) => {\n this.broadcast(eventName, data);\n };\n this.eventBus.on(eventName, handler);\n this.boundHandlers.push({ event: eventName, handler });\n }\n\n // Health heartbeat every 30s\n this.healthInterval = setInterval(() => {\n const mem = process.memoryUsage();\n const stats = this.getSessionStats();\n this.broadcast(\"health\", {\n uptime: Date.now() - this.startedAt,\n memory: {\n rss: mem.rss,\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n },\n sessions: stats,\n });\n }, 30_000);\n }\n\n handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {\n const parsedUrl = new URL(req.url || \"\", \"http://localhost\");\n const sessionFilter = parsedUrl.searchParams.get(\"sessionId\");\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.flushHeaders();\n\n // Store filter metadata on the response for broadcast\n (res as SSEResponse).sessionFilter = sessionFilter ?? undefined;\n\n this.sseConnections.add(res);\n\n const cleanup = () => {\n this.sseConnections.delete(res);\n this.sseCleanupHandlers.delete(res);\n };\n this.sseCleanupHandlers.set(res, cleanup);\n req.on(\"close\", cleanup);\n }\n\n broadcast(event: string, data: unknown): void {\n const payload = `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n // Events that carry sessionId and should be filtered\n const sessionEvents = [\n \"agent:event\",\n \"permission:request\",\n \"session:updated\",\n ];\n for (const res of this.sseConnections) {\n const filter = (res as SSEResponse).sessionFilter;\n if (filter && sessionEvents.includes(event)) {\n const eventData = data as { sessionId: string };\n if (eventData.sessionId !== filter) continue;\n }\n try {\n if (res.writable) res.write(payload);\n } catch {\n /* connection closed */\n }\n }\n }\n\n /**\n * Returns a Fastify route handler that hijacks the response\n * and delegates to the raw http SSE handler.\n */\n createFastifyHandler() {\n return async (request: FastifyRequest, reply: FastifyReply) => {\n reply.hijack();\n this.handleRequest(request.raw, reply.raw);\n };\n }\n\n stop(): void {\n if (this.healthInterval) clearInterval(this.healthInterval);\n\n // Remove only our own event bus listeners\n if (this.eventBus) {\n for (const { event, handler } of this.boundHandlers) {\n this.eventBus.off(event, handler);\n }\n }\n this.boundHandlers = [];\n\n // Copy to avoid modifying Map while iterating\n const entries = [...this.sseCleanupHandlers];\n for (const [res, cleanup] of entries) {\n res.end();\n cleanup();\n }\n }\n}\n\nexport type { SessionStats };\n","import * as http from \"node:http\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport class StaticServer {\n private uiDir: string | undefined;\n\n constructor(uiDir?: string) {\n this.uiDir = uiDir;\n\n if (!this.uiDir) {\n const __filename = fileURLToPath(import.meta.url);\n const candidate = path.resolve(path.dirname(__filename), \"../../ui/dist\");\n if (fs.existsSync(path.join(candidate, \"index.html\"))) {\n this.uiDir = candidate;\n }\n // Also check dist-publish layout\n if (!this.uiDir) {\n const publishCandidate = path.resolve(\n path.dirname(__filename),\n \"../ui\",\n );\n if (fs.existsSync(path.join(publishCandidate, \"index.html\"))) {\n this.uiDir = publishCandidate;\n }\n }\n }\n }\n\n isAvailable(): boolean {\n return this.uiDir !== undefined;\n }\n\n serve(req: http.IncomingMessage, res: http.ServerResponse): boolean {\n if (!this.uiDir) return false;\n\n const urlPath = (req.url || \"/\").split(\"?\")[0];\n const safePath = path.normalize(urlPath);\n\n // Try exact file match\n const filePath = path.join(this.uiDir, safePath);\n if (!filePath.startsWith(this.uiDir + path.sep) && filePath !== this.uiDir)\n return false; // path traversal guard\n\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {\n const ext = path.extname(filePath);\n const contentType = MIME_TYPES[ext] ?? \"application/octet-stream\";\n // Vite-hashed assets get long cache, others get no-cache\n const isHashed = /\\.[a-zA-Z0-9]{8,}\\.(js|css)$/.test(filePath);\n const cacheControl = isHashed\n ? \"public, max-age=31536000, immutable\"\n : \"no-cache\";\n res.writeHead(200, {\n \"Content-Type\": contentType,\n \"Cache-Control\": cacheControl,\n });\n fs.createReadStream(filePath).pipe(res);\n return true;\n }\n\n // SPA fallback — serve index.html\n const indexPath = path.join(this.uiDir, \"index.html\");\n if (fs.existsSync(indexPath)) {\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-cache\",\n });\n fs.createReadStream(indexPath).pipe(res);\n return true;\n }\n\n return false;\n }\n}\n","import { fileURLToPath } from 'node:url'\nimport { dirname, join, resolve } from 'node:path'\nimport { existsSync, readFileSync } from 'node:fs'\n\nconst NPM_PACKAGE = '@openacp/cli'\n\nfunction findPackageJson(): string | null {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (let i = 0; i < 5; i++) {\n const candidate = join(dir, 'package.json')\n if (existsSync(candidate)) return candidate\n const parent = resolve(dir, '..')\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n\nexport function getCurrentVersion(): string {\n try {\n const pkgPath = findPackageJson()\n if (!pkgPath) return '0.0.0-dev'\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\n return pkg.version as string\n } catch {\n return '0.0.0-dev'\n }\n}\n\nexport async function getLatestVersion(): Promise<string | null> {\n try {\n const res = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`, {\n signal: AbortSignal.timeout(5000),\n })\n if (!res.ok) return null\n const data = (await res.json()) as { version?: string }\n return data.version ?? null\n } catch {\n return null\n }\n}\n\nexport function compareVersions(current: string, latest: string): -1 | 0 | 1 {\n const a = current.split('.').map(Number)\n const b = latest.split('.').map(Number)\n for (let i = 0; i < 3; i++) {\n if ((a[i] ?? 0) < (b[i] ?? 0)) return -1\n if ((a[i] ?? 0) > (b[i] ?? 0)) return 1\n }\n return 0\n}\n\nexport async function runUpdate(): Promise<boolean> {\n const { spawn } = await import('node:child_process')\n return new Promise((resolve) => {\n const child = spawn('npm', ['install', '-g', `${NPM_PACKAGE}@latest`], {\n stdio: 'inherit',\n shell: true,\n })\n const onSignal = () => {\n child.kill('SIGTERM')\n resolve(false)\n }\n process.on('SIGINT', onSignal)\n process.on('SIGTERM', onSignal)\n child.on('close', (code) => {\n process.off('SIGINT', onSignal)\n process.off('SIGTERM', onSignal)\n resolve(code === 0)\n })\n })\n}\n\nexport async function checkAndPromptUpdate(): Promise<void> {\n if (process.env.OPENACP_DEV_LOOP || process.env.OPENACP_SKIP_UPDATE_CHECK) return\n\n const current = getCurrentVersion()\n if (current === '0.0.0-dev') return\n\n const latest = await getLatestVersion()\n if (!latest || compareVersions(current, latest) >= 0) return\n\n console.log(`\\x1b[33mUpdate available: v${current} → v${latest}\\x1b[0m`)\n const clack = await import('@clack/prompts')\n const yes = await clack.confirm({\n message: 'Update now before starting?',\n })\n if (clack.isCancel(yes) || !yes) {\n return\n }\n const ok = await runUpdate()\n if (ok) {\n console.log(`\\x1b[32m✓ Updated to v${latest}. Please re-run your command.\\x1b[0m`)\n process.exit(0)\n } else {\n console.error('\\x1b[31mUpdate failed. Continuing with current version.\\x1b[0m')\n }\n}\n","import type { Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { AgentCommand } from \"../../../core/index.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\n\nexport function buildMenuKeyboard(): InlineKeyboard {\n return new InlineKeyboard()\n .text(\"🆕 New Session\", \"m:new\")\n .text(\"📋 Sessions\", \"m:topics\")\n .row()\n .text(\"📊 Status\", \"m:status\")\n .text(\"🤖 Agents\", \"m:agents\")\n .row()\n .text(\"⚙️ Settings\", \"m:settings\")\n .text(\"🔗 Integrate\", \"m:integrate\")\n .row()\n .text(\"🔄 Restart\", \"m:restart\")\n .text(\"⬆️ Update\", \"m:update\")\n .row()\n .text(\"❓ Help\", \"m:help\")\n .text(\"🩺 Doctor\", \"m:doctor\");\n}\n\nexport async function handleMenu(ctx: Context): Promise<void> {\n await ctx.reply(`<b>OpenACP Menu</b>\\nChoose an action:`, {\n parse_mode: \"HTML\",\n reply_markup: buildMenuKeyboard(),\n });\n}\n\nexport async function handleHelp(ctx: Context): Promise<void> {\n await ctx.reply(\n `📖 <b>OpenACP Help</b>\\n\\n` +\n `🚀 <b>Getting Started</b>\\n` +\n `Tap 🆕 New Session to start coding with AI.\\n` +\n `Each session gets its own topic — chat there to work with the agent.\\n\\n` +\n `💡 <b>Common Tasks</b>\\n` +\n `/new [agent] [workspace] — Create new session\\n` +\n `/cancel — Cancel session (in session topic)\\n` +\n `/status — Show session or system status\\n` +\n `/sessions — List all sessions\\n` +\n `/agents — Browse & install agents\\n` +\n `/install <name> — Install an agent\\n\\n` +\n `⚙️ <b>System</b>\\n` +\n `/restart — Restart OpenACP\\n` +\n `/update — Update to latest version\\n` +\n `/integrate — Manage agent integrations\\n` +\n `/menu — Show action menu\\n\\n` +\n `🔒 <b>Session Options</b>\\n` +\n `/enable_dangerous — Auto-approve permissions\\n` +\n `/disable_dangerous — Restore permission prompts\\n` +\n `/handoff — Continue session in terminal\\n` +\n `/archive — Archive session topic\\n` +\n `/clear — Clear assistant history\\n\\n` +\n `💬 Need help? Just ask me in this topic!`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function handleClear(ctx: Context, assistant?: CommandsAssistantContext): Promise<void> {\n if (!assistant) {\n await ctx.reply(\"⚠️ Assistant is not available.\", { parse_mode: \"HTML\" });\n return;\n }\n\n const threadId = ctx.message?.message_thread_id;\n if (threadId !== assistant.topicId) {\n await ctx.reply(\"ℹ️ /clear only works in the Assistant topic.\", { parse_mode: \"HTML\" });\n return;\n }\n\n await ctx.reply(\"🔄 Clearing assistant history...\", { parse_mode: \"HTML\" });\n\n try {\n await assistant.respawn();\n await ctx.reply(\"✅ Assistant history cleared.\", { parse_mode: \"HTML\" });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.reply(`❌ Failed to clear: <code>${message}</code>`, { parse_mode: \"HTML\" });\n }\n}\n\nconst TELEGRAM_MSG_LIMIT = 4096;\n\n/**\n * Build plain-text skill command messages. Each command is on its own line\n * wrapped in <code> for tap-to-copy. If the list exceeds Telegram's message\n * limit, it is split into multiple messages (cut at line boundaries).\n */\nexport function buildSkillMessages(commands: AgentCommand[]): string[] {\n const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));\n const header = \"🛠 <b>Available Skills</b>\\n\";\n const lines = sorted.map((c) => `<code>/${c.name}</code>`);\n\n const messages: string[] = [];\n let current = header;\n\n for (const line of lines) {\n const candidate = current + \"\\n\" + line;\n if (candidate.length > TELEGRAM_MSG_LIMIT) {\n messages.push(current);\n current = line;\n } else {\n current = candidate;\n }\n }\n if (current) messages.push(current);\n return messages;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, chmodSync, rmdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { getAgentCapabilities, commandExists, listAgentsWithIntegration } from \"../core/agents/agent-dependencies.js\";\nimport type { AgentIntegrationSpec } from \"../core/agents/agent-dependencies.js\";\n\nexport interface IntegrationResult {\n success: boolean;\n logs: string[];\n}\n\nexport interface IntegrationItem {\n id: string;\n name: string;\n description: string;\n isInstalled(): boolean;\n install(): Promise<IntegrationResult>;\n uninstall(): Promise<IntegrationResult>;\n}\n\nexport interface AgentIntegration {\n items: IntegrationItem[];\n}\n\nconst HOOK_MARKER = \"openacp-inject-session.sh\";\n\nfunction expandPath(p: string): string {\n return p.replace(/^~/, homedir());\n}\n\n// --- Script generators ---\n\nfunction generateInjectScript(_agentKey: string, spec: AgentIntegrationSpec): string {\n const sidVar = spec.sessionIdVar ?? \"SESSION_ID\";\n const cwdVar = spec.workingDirVar ?? \"WORKING_DIR\";\n\n // Resolve jq: check ~/.openacp/bin first, then PATH\n const jqResolver = `JQ=$(command -v jq 2>/dev/null || echo \"$HOME/.openacp/bin/jq\")`;\n\n if (spec.outputFormat === \"plaintext\") {\n return `#!/bin/bash\n${jqResolver}\nINPUT=$(cat)\nSESSION_ID=$(echo \"$INPUT\" | \"$JQ\" -r '${spec.sessionIdField}')\nCWD=$(echo \"$INPUT\" | \"$JQ\" -r '.cwd')\n\necho \"${sidVar}: $SESSION_ID\"\necho \"${cwdVar}: $CWD\"\n\nexit 0\n`;\n }\n\n // JSON output (Gemini, Cline, Cursor)\n return `#!/bin/bash\n${jqResolver}\nINPUT=$(cat)\nSESSION_ID=$(echo \"$INPUT\" | \"$JQ\" -r '${spec.sessionIdField}')\nCWD=$(echo \"$INPUT\" | \"$JQ\" -r '.cwd')\n\n\"$JQ\" -n --arg sid \"$SESSION_ID\" --arg cwd \"$CWD\" \\\\\n '{\"additionalContext\":\"${sidVar}: \\\\($sid)\\\\n${cwdVar}: \\\\($cwd)\"}'\n\nexit 0\n`;\n}\n\nfunction generateHandoffScript(agentKey: string): string {\n return `#!/bin/bash\nSESSION_ID=$1\nCWD=$2\nCHANNEL=$3\n\nif [ -z \"$SESSION_ID\" ]; then\n echo \"Usage: openacp-handoff.sh <session_id> [cwd] [channel]\"\n exit 1\nfi\n\nopenacp adopt ${agentKey} \"$SESSION_ID\" \\${CWD:+--cwd \"$CWD\"} \\${CHANNEL:+--channel \"$CHANNEL\"}\n`;\n}\n\nfunction generateTunnelCommand(): string {\n return `---\ndescription: Expose local ports to the internet. Use when user wants to share, preview, or access their local dev server remotely. Triggers on phrases like \"expose port\", \"map port\", \"share my app\", \"make it public\", \"open tunnel\", \"public URL\", \"share localhost\", \"preview on phone\", \"access from outside\", \"forward port\", \"ngrok\", \"cloudflare tunnel\", etc.\n---\n\nYou have access to OpenACP tunnel management via CLI. This creates a public URL for any local port (dev servers, APIs, static sites, etc.) using Cloudflare tunnel.\n\n## Commands\n\n\\`\\`\\`bash\n# Create a tunnel — exposes local port to the internet\nopenacp tunnel add <port> --label <name>\n\n# List all active tunnels with their public URLs\nopenacp tunnel list\n\n# Stop a specific tunnel\nopenacp tunnel stop <port>\n\n# Stop all tunnels\nopenacp tunnel stop-all\n\\`\\`\\`\n\n## When to use\n\nUser wants to:\n- **Share their local app** — \"share this on my phone\", \"let my friend see this\", \"preview on mobile\"\n- **Expose a port** — \"expose port 3000\", \"map port 5173\", \"make port 8080 public\"\n- **Get a public URL** — \"give me a public URL\", \"I need an external link\", \"make localhost accessible\"\n- **Open a tunnel** — \"open tunnel\", \"start tunnel\", \"tunnel this\"\n- **Forward/proxy a port** — \"forward port 3000\", \"proxy my server\"\n- **Deploy preview** — \"deploy preview\", \"share a preview link\"\n- **Access remotely** — \"access from my phone\", \"access from outside\"\n- **Manage tunnels** — \"show tunnels\", \"list tunnels\", \"stop tunnel\", \"close tunnel\", \"kill tunnel\"\n\n## How to respond\n\n1. Run the CLI command\n2. Share the public URL with the user\n3. Mention the URL works on any device (phone, tablet, other computer)\n4. If the user hasn't started a dev server yet, remind them to start one first\n\n## Example flow\n\nUser: \"I want to see this React app on my phone\"\n→ Check if dev server is running (e.g. port 5173 for Vite)\n→ Run: \\`openacp tunnel add 5173 --label react-app\\`\n→ Share the public URL\n`;\n}\n\nfunction generateHandoffCommand(_agentKey: string, spec: AgentIntegrationSpec): string {\n const sidVar = spec.sessionIdVar ?? \"SESSION_ID\";\n const cwdVar = spec.workingDirVar ?? \"WORKING_DIR\";\n const hooksDir = expandPath(spec.hooksDirPath);\n\n return `---\ndescription: Transfer current session to OpenACP (Telegram/Discord)\n---\n\nLook at the context injected at the start of this message to find\n${sidVar} and ${cwdVar}, then run:\n\nbash ${hooksDir}openacp-handoff.sh <${sidVar}> <${cwdVar}> <args if any>\n\nUsage: /openacp:handoff [channel]\n channel: name of a registered adapter (e.g. telegram), or omit for default\n\nExamples:\n /openacp:handoff\n /openacp:handoff telegram\n`;\n}\n\n// --- Settings mergers ---\n\nfunction mergeSettingsJson(settingsPath: string, hookEvent: string, hookScriptPath: string): void {\n const fullPath = expandPath(settingsPath);\n let settings: Record<string, unknown> = {};\n\n if (existsSync(fullPath)) {\n const raw = readFileSync(fullPath, \"utf-8\");\n writeFileSync(`${fullPath}.bak`, raw);\n settings = JSON.parse(raw);\n }\n\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n settings.hooks = hooks;\n\n const eventHooks = (hooks[hookEvent] ?? []) as Array<{ hooks?: Array<{ type?: string; command?: string }> }>;\n hooks[hookEvent] = eventHooks;\n\n const alreadyInstalled = eventHooks.some((group) =>\n group.hooks?.some((h) => h.command?.includes(HOOK_MARKER)),\n );\n\n if (!alreadyInstalled) {\n eventHooks.push({\n hooks: [{ type: \"command\", command: hookScriptPath }],\n });\n }\n\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\nfunction mergeHooksJson(settingsPath: string, hookEvent: string, hookScriptPath: string): void {\n const fullPath = expandPath(settingsPath);\n let config: Record<string, unknown> = { version: 1 };\n\n if (existsSync(fullPath)) {\n const raw = readFileSync(fullPath, \"utf-8\");\n writeFileSync(`${fullPath}.bak`, raw);\n config = JSON.parse(raw);\n }\n\n const hooks = (config.hooks ?? {}) as Record<string, unknown[]>;\n config.hooks = hooks;\n\n const eventHooks = (hooks[hookEvent] ?? []) as Array<{ command?: string }>;\n hooks[hookEvent] = eventHooks;\n\n const alreadyInstalled = eventHooks.some((h) => h.command?.includes(HOOK_MARKER));\n\n if (!alreadyInstalled) {\n eventHooks.push({ command: hookScriptPath });\n }\n\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nfunction removeFromSettingsJson(settingsPath: string, hookEvent: string): void {\n const fullPath = expandPath(settingsPath);\n if (!existsSync(fullPath)) return;\n\n const raw = readFileSync(fullPath, \"utf-8\");\n const settings = JSON.parse(raw);\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n if (!hooks?.[hookEvent]) return;\n\n hooks[hookEvent] = (hooks[hookEvent] as Array<{ hooks?: Array<{ command?: string }> }>).filter(\n (group) => !group.hooks?.some((h) => h.command?.includes(\"openacp-\")),\n );\n\n if ((hooks[hookEvent] as unknown[]).length === 0) {\n delete hooks[hookEvent];\n }\n\n writeFileSync(fullPath, JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\nfunction removeFromHooksJson(settingsPath: string, hookEvent: string): void {\n const fullPath = expandPath(settingsPath);\n if (!existsSync(fullPath)) return;\n\n const raw = readFileSync(fullPath, \"utf-8\");\n const config = JSON.parse(raw);\n const hooks = config.hooks as Record<string, unknown[]> | undefined;\n if (!hooks?.[hookEvent]) return;\n\n hooks[hookEvent] = (hooks[hookEvent] as Array<{ command?: string }>).filter(\n (h) => !h.command?.includes(\"openacp-\"),\n );\n\n if ((hooks[hookEvent] as unknown[]).length === 0) {\n delete hooks[hookEvent];\n }\n\n writeFileSync(fullPath, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\n// --- Core install/uninstall ---\n\nexport async function installIntegration(agentKey: string, spec: AgentIntegrationSpec): Promise<IntegrationResult> {\n const logs: string[] = [];\n try {\n // Check jq\n if (!commandExists(\"jq\")) {\n return {\n success: false,\n logs: [\"jq is required for handoff hooks. Install: brew install jq (macOS) or apt install jq (Linux)\"],\n };\n }\n\n const hooksDir = expandPath(spec.hooksDirPath);\n mkdirSync(hooksDir, { recursive: true });\n\n // Inject script\n const injectPath = join(hooksDir, \"openacp-inject-session.sh\");\n writeFileSync(injectPath, generateInjectScript(agentKey, spec));\n chmodSync(injectPath, 0o755);\n logs.push(`Created ${injectPath}`);\n\n // Handoff script\n const handoffPath = join(hooksDir, \"openacp-handoff.sh\");\n writeFileSync(handoffPath, generateHandoffScript(agentKey));\n chmodSync(handoffPath, 0o755);\n logs.push(`Created ${handoffPath}`);\n\n // Slash command / skill\n if (spec.commandsPath && spec.handoffCommandName) {\n if (spec.commandFormat === \"skill\") {\n const skillDir = expandPath(join(spec.commandsPath, spec.handoffCommandName));\n mkdirSync(skillDir, { recursive: true });\n const skillPath = join(skillDir, \"SKILL.md\");\n writeFileSync(skillPath, generateHandoffCommand(agentKey, spec));\n logs.push(`Created ${skillPath}`);\n } else {\n const cmdsDir = expandPath(spec.commandsPath);\n mkdirSync(cmdsDir, { recursive: true });\n const cmdPath = join(cmdsDir, `${spec.handoffCommandName}.md`);\n writeFileSync(cmdPath, generateHandoffCommand(agentKey, spec));\n logs.push(`Created ${cmdPath}`);\n }\n }\n\n // Merge settings\n const injectFullPath = join(hooksDir, \"openacp-inject-session.sh\");\n if (spec.settingsFormat === \"hooks_json\") {\n mergeHooksJson(spec.settingsPath, spec.hookEvent, injectFullPath);\n } else {\n mergeSettingsJson(spec.settingsPath, spec.hookEvent, injectFullPath);\n }\n logs.push(`Updated ${expandPath(spec.settingsPath)}`);\n\n return { success: true, logs };\n } catch (err) {\n logs.push(`Error: ${err instanceof Error ? err.message : String(err)}`);\n return { success: false, logs };\n }\n}\n\nexport async function uninstallIntegration(agentKey: string, spec: AgentIntegrationSpec): Promise<IntegrationResult> {\n const logs: string[] = [];\n try {\n const hooksDir = expandPath(spec.hooksDirPath);\n\n // Remove hook scripts\n for (const filename of [\"openacp-inject-session.sh\", \"openacp-handoff.sh\"]) {\n const filePath = join(hooksDir, filename);\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n logs.push(`Removed ${filePath}`);\n }\n }\n\n // Remove slash command / skill\n if (spec.commandsPath && spec.handoffCommandName) {\n if (spec.commandFormat === \"skill\") {\n const skillDir = expandPath(join(spec.commandsPath, spec.handoffCommandName));\n const skillPath = join(skillDir, \"SKILL.md\");\n if (existsSync(skillPath)) {\n unlinkSync(skillPath);\n try { rmdirSync(skillDir); } catch { /* not empty */ }\n logs.push(`Removed ${skillPath}`);\n }\n } else {\n const cmdPath = expandPath(join(spec.commandsPath, `${spec.handoffCommandName}.md`));\n if (existsSync(cmdPath)) {\n unlinkSync(cmdPath);\n logs.push(`Removed ${cmdPath}`);\n }\n }\n }\n\n // Clean settings\n if (spec.settingsFormat === \"hooks_json\") {\n removeFromHooksJson(spec.settingsPath, spec.hookEvent);\n } else {\n removeFromSettingsJson(spec.settingsPath, spec.hookEvent);\n }\n logs.push(`Updated ${expandPath(spec.settingsPath)}`);\n\n return { success: true, logs };\n } catch (err) {\n logs.push(`Error: ${err instanceof Error ? err.message : String(err)}`);\n return { success: false, logs };\n }\n}\n\n// --- Public API (backward compat with existing cmdIntegrate / Telegram integrate) ---\n\nfunction buildHandoffItem(agentKey: string, spec: AgentIntegrationSpec): IntegrationItem {\n const hooksDir = expandPath(spec.hooksDirPath);\n return {\n id: \"handoff\",\n name: \"Handoff\",\n description: \"Transfer sessions between terminal and messaging platforms\",\n isInstalled(): boolean {\n return (\n existsSync(join(hooksDir, \"openacp-inject-session.sh\")) &&\n existsSync(join(hooksDir, \"openacp-handoff.sh\"))\n );\n },\n install: () => installIntegration(agentKey, spec),\n uninstall: () => uninstallIntegration(agentKey, spec),\n };\n}\n\nfunction getSkillBasePath(spec: AgentIntegrationSpec): string {\n // Skills go into the agent's skills directory (sibling to commands)\n // Claude: ~/.claude/skills/, Cursor: ~/.cursor/skills/\n const base = spec.commandsPath!;\n // If commandsPath is commands/, use skills/ instead\n const skillsBase = base.replace(/\\/commands\\/?$/, \"/skills/\");\n return expandPath(skillsBase);\n}\n\nfunction buildTunnelItem(spec: AgentIntegrationSpec): IntegrationItem | null {\n if (!spec.commandsPath) return null;\n\n function getTunnelPath(): string {\n return join(getSkillBasePath(spec), \"openacp-tunnel\", \"SKILL.md\");\n }\n\n return {\n id: \"tunnel\",\n name: \"Tunnel\",\n description: \"Expose local ports to the internet via OpenACP tunnel\",\n isInstalled(): boolean {\n return existsSync(getTunnelPath());\n },\n async install(): Promise<IntegrationResult> {\n const logs: string[] = [];\n try {\n const skillPath = getTunnelPath();\n mkdirSync(dirname(skillPath), { recursive: true });\n writeFileSync(skillPath, generateTunnelCommand());\n logs.push(`Created ${skillPath}`);\n return { success: true, logs };\n } catch (err) {\n logs.push(`Error: ${err instanceof Error ? err.message : String(err)}`);\n return { success: false, logs };\n }\n },\n async uninstall(): Promise<IntegrationResult> {\n const logs: string[] = [];\n try {\n const skillPath = getTunnelPath();\n if (existsSync(skillPath)) {\n unlinkSync(skillPath);\n try { rmdirSync(dirname(skillPath)); } catch { /* not empty */ }\n logs.push(`Removed ${skillPath}`);\n }\n return { success: true, logs };\n } catch (err) {\n logs.push(`Error: ${err instanceof Error ? err.message : String(err)}`);\n return { success: false, logs };\n }\n },\n };\n}\n\nexport function getIntegration(agentName: string): AgentIntegration | undefined {\n const caps = getAgentCapabilities(agentName);\n if (!caps.integration) return undefined;\n const items: IntegrationItem[] = [buildHandoffItem(agentName, caps.integration)];\n const tunnelItem = buildTunnelItem(caps.integration);\n if (tunnelItem) items.push(tunnelItem);\n return { items };\n}\n\nexport function listIntegrations(): string[] {\n return listAgentsWithIntegration();\n}\n","// ─── Core modules ───────────────────────────────────────────────────────────\nexport * from \"./types.js\";\nexport {\n log,\n initLogger,\n createChildLogger,\n createSessionLogger,\n shutdownLogger,\n cleanupOldSessionLogs,\n setLogLevel,\n type Logger,\n} from \"./utils/log.js\";\nexport {\n ChannelAdapter,\n type IChannelAdapter,\n type AdapterCapabilities,\n type ChannelConfig,\n} from \"./channel.js\";\nexport { nodeToWebWritable, nodeToWebReadable } from \"./utils/streams.js\";\nexport { StderrCapture } from \"./utils/stderr-capture.js\";\nexport {\n ConfigManager,\n expandHome,\n type Config,\n type LoggingConfig,\n type UsageConfig,\n} from \"./config/config.js\";\nexport { AgentInstance } from \"./agents/agent-instance.js\";\nexport { AgentManager } from \"./agents/agent-manager.js\";\nexport { Session, type SessionEvents } from \"./sessions/session.js\";\nexport { TypedEmitter } from \"./utils/typed-emitter.js\";\nexport { PromptQueue } from \"./sessions/prompt-queue.js\";\nexport { PermissionGate } from \"./sessions/permission-gate.js\";\nexport { MessageTransformer } from \"./message-transformer.js\";\nexport type { FileServiceInterface } from \"./plugin/types.js\";\nexport { SessionManager } from \"./sessions/session-manager.js\";\nexport { SessionBridge, type BridgeDeps } from \"./sessions/session-bridge.js\";\nexport {\n SessionFactory,\n type SessionCreateParams,\n type SideEffectDeps,\n} from \"./sessions/session-factory.js\";\nexport { OpenACPCore } from \"./core.js\";\nexport { EventBus, type EventBusEvents } from \"./event-bus.js\";\nexport { CommandRegistry } from \"./command-registry.js\";\nexport { DoctorEngine, type DoctorReport, type PendingFix } from \"./doctor/index.js\";\nexport {\n CONFIG_REGISTRY,\n getFieldDef,\n getSafeFields,\n isHotReloadable,\n resolveOptions,\n getConfigValue,\n type ConfigFieldDef,\n} from \"./config/config-registry.js\";\nexport { runConfigEditor } from \"./config/config-editor.js\";\nexport { startDaemon, stopDaemon, getStatus, getPidPath } from \"../cli/daemon.js\";\nexport {\n installAutoStart,\n uninstallAutoStart,\n isAutoStartInstalled,\n isAutoStartSupported,\n} from \"../cli/autostart.js\";\n\n// ─── Plugin re-exports (convenience for @openacp/cli consumers) ──────────────\n// These are NOT core dependencies — they're re-exported for public API\n// convenience so consumers don't need to import from deep plugin paths.\nexport { NotificationManager } from \"../plugins/notifications/notification.js\";\nexport { FileService } from \"../plugins/file-service/file-service.js\";\nexport { SecurityGuard } from \"../plugins/security/security-guard.js\";\nexport { type ApiConfig } from \"../plugins/api-server/index.js\";\nexport { createApiServer, type ApiServerInstance, type ApiServerOptions } from \"../plugins/api-server/server.js\";\nexport { createApiServerService, type ApiServerService } from \"../plugins/api-server/service.js\";\nexport { SSEManager } from \"../plugins/api-server/sse-manager.js\";\nexport { StaticServer } from \"../plugins/api-server/static-server.js\";\nexport {\n TopicManager,\n type TopicInfo,\n type DeleteTopicResult,\n type CleanupResult,\n} from \"../plugins/telegram/topic-manager.js\";\nexport { SpeechService, GroqSTT } from \"../plugins/speech/exports.js\";\nexport type {\n STTProvider,\n TTSProvider,\n STTOptions,\n STTResult,\n TTSOptions,\n TTSResult,\n SpeechServiceConfig,\n SpeechProviderConfig,\n} from \"../plugins/speech/exports.js\";\nexport type {\n ContextProvider,\n ContextQuery,\n ContextOptions,\n ContextResult,\n SessionInfo as ContextSessionInfo,\n SessionListResult,\n} from \"../plugins/context/context-provider.js\";\nexport { ContextManager } from \"../plugins/context/context-manager.js\";\nexport { EntireProvider } from \"../plugins/context/entire/entire-provider.js\";\n\n// ─── Adapter primitives ─────────────────────────────────────────────────────\nexport { MessagingAdapter, StreamAdapter } from './adapter-primitives/index.js'\nexport type { MessagingAdapterConfig } from './adapter-primitives/index.js'\nexport { BaseRenderer } from './adapter-primitives/index.js'\nexport type { IRenderer, RenderedMessage } from './adapter-primitives/index.js'\nexport { SendQueue, DraftManager, ToolCallTracker, ActivityTracker } from './adapter-primitives/index.js'\nexport type { DisplayVerbosity, ToolCallMeta, ToolUpdateMeta, ViewerLinks } from './adapter-primitives/index.js'\nexport { STATUS_ICONS, KIND_ICONS } from './adapter-primitives/index.js'\nexport { progressBar, formatTokens, truncateContent, stripCodeFences, splitMessage } from './adapter-primitives/index.js'\nexport { extractContentText, formatToolSummary, formatToolTitle, resolveToolIcon } from './adapter-primitives/index.js'\nexport { ToolStateMap, ThoughtBuffer } from './adapter-primitives/index.js'\nexport type { ToolEntry } from './adapter-primitives/index.js'\nexport { DisplaySpecBuilder } from './adapter-primitives/index.js'\nexport type { ToolDisplaySpec, ThoughtDisplaySpec } from './adapter-primitives/index.js'\nexport { OutputModeResolver } from './adapter-primitives/index.js'\nexport type { OutputMode } from './adapter-primitives/index.js'\nexport { ToolCardState } from './adapter-primitives/index.js'\nexport type { ToolCardSnapshot, ToolCardStateConfig } from './adapter-primitives/index.js'\n\n// ─── Plugin types (for SDK re-exports) ──────────────────────────────────────\nexport type {\n OpenACPPlugin, PluginContext, PluginPermission, PluginStorage,\n InstallContext, MigrateContext, TerminalIO, SettingsAPI,\n CommandDef, CommandArgs, CommandResponse, MenuOption, ListItem,\n SecurityService, NotificationService, UsageService,\n SpeechServiceInterface, TunnelServiceInterface, ContextService,\n} from './plugin/types.js'\nexport { PRODUCT_GUIDE } from '../data/product-guide.js'\n","import type { OutgoingMessage, PermissionRequest, NotificationMessage, AgentCommand } from './types.js'\n\nexport interface ChannelConfig {\n enabled: boolean\n [key: string]: unknown\n}\n\nexport interface AdapterCapabilities {\n streaming: boolean\n richFormatting: boolean\n threads: boolean\n reactions: boolean\n fileUpload: boolean\n voice: boolean\n}\n\nexport interface IChannelAdapter {\n readonly name: string\n readonly capabilities: AdapterCapabilities\n\n start(): Promise<void>\n stop(): Promise<void>\n\n // Outgoing: core → channel\n sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n sendNotification(notification: NotificationMessage): Promise<void>\n\n // Session lifecycle on channel side\n createSessionThread(sessionId: string, name: string): Promise<string> // returns threadId\n renameSessionThread(sessionId: string, newName: string): Promise<void>\n deleteSessionThread?(sessionId: string): Promise<void>\n archiveSessionTopic?(sessionId: string): Promise<void>\n\n // TTS strip — optional, called after TTS audio is synthesized to remove [TTS] block from text\n stripTTSBlock?(sessionId: string): Promise<void>\n\n // Skill commands — optional\n sendSkillCommands?(sessionId: string, commands: AgentCommand[]): Promise<void>\n cleanupSkillCommands?(sessionId: string): Promise<void>\n /** Flush skill commands that were queued before threadId was available */\n flushPendingSkillCommands?(sessionId: string): Promise<void>\n\n // Agent switch cleanup — optional, called when switching agents to clear adapter-side per-session state\n cleanupSessionState?(sessionId: string): Promise<void>\n}\n\n/**\n * Base class providing default no-op implementations for optional methods.\n * Adapters can extend this or implement IChannelAdapter directly.\n * @deprecated Use MessagingAdapter or StreamAdapter instead. Kept for backward compat during migration.\n */\nexport abstract class ChannelAdapter<TCore = unknown> implements IChannelAdapter {\n abstract readonly name: string\n readonly capabilities: AdapterCapabilities = {\n streaming: false, richFormatting: false, threads: false,\n reactions: false, fileUpload: false, voice: false,\n }\n\n constructor(public readonly core: TCore, protected config: ChannelConfig) {}\n\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n\n abstract sendMessage(sessionId: string, content: OutgoingMessage): Promise<void>\n abstract sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void>\n abstract sendNotification(notification: NotificationMessage): Promise<void>\n\n abstract createSessionThread(sessionId: string, name: string): Promise<string>\n abstract renameSessionThread(sessionId: string, newName: string): Promise<void>\n async deleteSessionThread(_sessionId: string): Promise<void> {}\n\n async sendSkillCommands(_sessionId: string, _commands: AgentCommand[]): Promise<void> {}\n async cleanupSkillCommands(_sessionId: string): Promise<void> {}\n async cleanupSessionState(_sessionId: string): Promise<void> {}\n async archiveSessionTopic(_sessionId: string): Promise<void> {}\n}\n","export function nodeToWebWritable(nodeStream: NodeJS.WritableStream): WritableStream<Uint8Array> {\n return new WritableStream<Uint8Array>({\n write(chunk) {\n return new Promise<void>((resolve, reject) => {\n const ok = nodeStream.write(chunk);\n if (ok) { resolve(); return; }\n (nodeStream as any).once(\"drain\", resolve);\n (nodeStream as any).once(\"error\", reject);\n });\n },\n close() {\n (nodeStream as any).end();\n },\n abort(reason) {\n (nodeStream as any).destroy(reason instanceof Error ? reason : new Error(String(reason)));\n },\n });\n}\n\nexport function nodeToWebReadable(nodeStream: NodeJS.ReadableStream): ReadableStream<Uint8Array> {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n nodeStream.on(\"data\", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));\n nodeStream.on(\"end\", () => controller.close());\n nodeStream.on(\"error\", (err) => controller.error(err));\n },\n cancel() {\n (nodeStream as any).destroy();\n },\n });\n}\n","export class StderrCapture {\n private lines: string[] = []\n\n constructor(private maxLines: number = 50) {}\n\n append(chunk: string): void {\n this.lines.push(...chunk.split('\\n').filter(Boolean))\n if (this.lines.length > this.maxLines) {\n this.lines = this.lines.slice(-this.maxLines)\n }\n }\n\n getLastLines(): string {\n return this.lines.join('\\n')\n }\n}\n","import { spawn, execFileSync, type ChildProcess } from \"node:child_process\";\nimport { Transform } from \"node:stream\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ClientSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\";\nimport type {\n Agent,\n Client,\n PromptResponse,\n PermissionOption as SdkPermissionOption,\n} from \"@agentclientprotocol/sdk\";\nimport { nodeToWebWritable, nodeToWebReadable } from \"../utils/streams.js\";\nimport { StderrCapture } from \"../utils/stderr-capture.js\";\nimport { TypedEmitter } from \"../utils/typed-emitter.js\";\nimport type {\n AgentDefinition,\n AgentEvent,\n Attachment,\n ConfigOption,\n McpServerConfig,\n PermissionRequest,\n SetConfigOptionValue,\n} from \"../types.js\";\nimport { readTextFileWithRange } from \"../utils/read-text-file.js\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\nimport { PROTOCOL_VERSION } from \"@agentclientprotocol/sdk\";\nimport { TerminalManager } from \"../sessions/terminal-manager.js\";\nimport { McpManager } from \"./mcp-manager.js\";\nimport type {\n ListSessionsResponse,\n LoadSessionResponse,\n ForkSessionResponse,\n SetSessionConfigOptionResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { createDebugTracer, type DebugTracer } from \"../utils/debug-tracer.js\";\nimport { createChildLogger } from \"../utils/log.js\";\nconst log = createChildLogger({ module: \"agent-instance\" });\n\n/** Find the nearest ancestor directory containing package.json */\nfunction findPackageRoot(startDir: string): string {\n let dir = startDir;\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n return startDir;\n}\n\n/** Resolve an agent command to a directly executable form (avoids shell wrappers) */\nfunction resolveAgentCommand(cmd: string): { command: string; args: string[] } {\n // Directories to search for node_modules: cwd AND the package's own directory\n const searchRoots = [process.cwd()];\n // Add the directory where this package is installed (for global installs)\n // Use findPackageRoot instead of hardcoded \"../..\" to handle both tsc (dist/core/)\n // and tsup bundle (dist/) directory structures correctly\n const ownDir = findPackageRoot(import.meta.dirname);\n if (ownDir !== process.cwd()) {\n searchRoots.push(ownDir);\n }\n\n // 1. Check node_modules for the package's actual JS entry point\n for (const root of searchRoots) {\n const packageDirs = [\n path.resolve(root, \"node_modules\", \"@zed-industries\", cmd, \"dist\", \"index.js\"),\n path.resolve(root, \"node_modules\", cmd, \"dist\", \"index.js\"),\n ];\n for (const jsPath of packageDirs) {\n if (fs.existsSync(jsPath)) {\n return { command: process.execPath, args: [jsPath] };\n }\n }\n }\n\n // 2. Check .bin — if it's a JS file with shebang, run with node directly\n for (const root of searchRoots) {\n const localBin = path.resolve(root, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(localBin)) {\n const content = fs.readFileSync(localBin, \"utf-8\");\n if (content.startsWith(\"#!/usr/bin/env node\")) {\n return { command: process.execPath, args: [localBin] };\n }\n // Shell wrapper — try to find the target JS file\n const match = content.match(/\"([^\"]+\\.js)\"/);\n if (match) {\n const target = path.resolve(path.dirname(localBin), match[1]);\n if (fs.existsSync(target)) {\n return { command: process.execPath, args: [target] };\n }\n }\n }\n }\n\n // 3. Try resolving from PATH using which\n try {\n const fullPath = execFileSync(\"which\", [cmd], { encoding: \"utf-8\" }).trim();\n if (fullPath) {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n if (content.startsWith(\"#!/usr/bin/env node\")) {\n return { command: process.execPath, args: [fullPath] };\n }\n }\n } catch {\n // which failed\n }\n\n // 4. Fallback: use command as-is\n return { command: cmd, args: [] };\n}\n\n// TerminalState has been extracted to TerminalManager\n\n// Local types for ACP session update shapes not fully typed by SDK\ninterface SdkToolCallFields {\n rawInput?: unknown;\n rawOutput?: unknown;\n _meta?: Record<string, unknown>;\n}\n\ninterface SdkSessionInfoUpdate {\n sessionUpdate: 'session_info_update';\n title?: string | null;\n updatedAt?: string | null;\n _meta?: Record<string, unknown>;\n}\n\ninterface SdkCurrentModeUpdate {\n sessionUpdate: 'current_mode_update';\n currentModeId: string;\n _meta?: Record<string, unknown>;\n}\n\ninterface SdkConfigOptionUpdate {\n sessionUpdate: 'config_option_update';\n configOptions: unknown[];\n _meta?: Record<string, unknown>;\n}\n\ninterface SdkUserMessageChunk {\n sessionUpdate: 'user_message_chunk';\n content: { type: string; text?: string };\n}\n\ninterface SdkReadTextFileParams {\n path: string;\n line?: number;\n limit?: number;\n}\n\nexport interface AgentInstanceEvents {\n agent_event: (event: AgentEvent) => void;\n}\n\nexport class AgentInstance extends TypedEmitter<AgentInstanceEvents> {\n private connection!: ClientSideConnection;\n private child!: ChildProcess;\n private stderrCapture!: StderrCapture;\n private terminalManager = new TerminalManager();\n private static mcpManager = new McpManager();\n private _destroying = false;\n\n sessionId!: string;\n agentName: string;\n promptCapabilities?: { image?: boolean; audio?: boolean };\n agentCapabilities?: import(\"../types.js\").AgentCapabilities;\n /** Preserved from newSession/resumeSession response for ACP state propagation */\n initialSessionResponse?: { modes?: unknown; configOptions?: unknown; models?: unknown };\n middlewareChain?: MiddlewareChain;\n debugTracer: DebugTracer | null = null;\n\n // Callback — set by core when wiring events\n onPermissionRequest: (request: PermissionRequest) => Promise<string> =\n async () => \"\";\n\n private constructor(agentName: string) {\n super();\n this.agentName = agentName;\n }\n\n private static async spawnSubprocess(\n agentDef: AgentDefinition,\n workingDirectory: string,\n ): Promise<AgentInstance> {\n const instance = new AgentInstance(agentDef.name);\n const resolved = resolveAgentCommand(agentDef.command);\n log.debug(\n {\n agentName: agentDef.name,\n command: resolved.command,\n args: resolved.args,\n },\n \"Resolved agent command\",\n );\n\n instance.child = spawn(\n resolved.command,\n [...resolved.args, ...agentDef.args],\n {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n cwd: workingDirectory,\n env: { ...process.env, ...agentDef.env },\n },\n );\n\n await new Promise<void>((resolve, reject) => {\n instance.child.on(\"error\", (err) => {\n reject(\n new Error(\n `Failed to spawn agent \"${agentDef.name}\": ${err.message}. Is \"${agentDef.command}\" installed?`,\n ),\n );\n });\n instance.child.on(\"spawn\", () => resolve());\n });\n\n instance.stderrCapture = new StderrCapture(50);\n instance.child.stderr!.on(\"data\", (chunk: Buffer) => {\n instance.stderrCapture.append(chunk.toString());\n });\n\n const stdinLogger = new Transform({\n transform(chunk, _enc, cb) {\n if (instance.debugTracer) {\n const raw = chunk.toString().trimEnd();\n try {\n instance.debugTracer.log(\"acp\", { dir: \"send\", data: JSON.parse(raw) });\n } catch {\n instance.debugTracer.log(\"acp\", { dir: \"send\", data: raw });\n }\n }\n cb(null, chunk);\n },\n });\n stdinLogger.pipe(instance.child.stdin!);\n\n const stdoutLogger = new Transform({\n transform(chunk, _enc, cb) {\n if (instance.debugTracer) {\n const raw = chunk.toString().trimEnd();\n try {\n instance.debugTracer.log(\"acp\", { dir: \"recv\", data: JSON.parse(raw) });\n } catch {\n instance.debugTracer.log(\"acp\", { dir: \"recv\", data: raw });\n }\n }\n cb(null, chunk);\n },\n });\n instance.child.stdout!.pipe(stdoutLogger);\n\n const toAgent = nodeToWebWritable(stdinLogger);\n const fromAgent = nodeToWebReadable(stdoutLogger);\n const stream = ndJsonStream(toAgent, fromAgent);\n\n instance.connection = new ClientSideConnection(\n (_agent: Agent): Client => instance.createClient(_agent),\n stream,\n );\n\n const initResponse = await instance.connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {\n fs: { readTextFile: true, writeTextFile: true },\n terminal: true,\n },\n });\n\n if (initResponse.protocolVersion !== PROTOCOL_VERSION) {\n log.warn(\n { expected: PROTOCOL_VERSION, got: initResponse.protocolVersion },\n \"ACP protocol version mismatch — some features may not work correctly\",\n );\n }\n\n instance.promptCapabilities =\n initResponse.agentCapabilities?.promptCapabilities;\n\n // Store full agent capabilities for introspection (session list, fork, close, etc.)\n instance.agentCapabilities = initResponse.agentCapabilities as import(\"../types.js\").AgentCapabilities | undefined;\n\n log.info(\n { promptCapabilities: instance.promptCapabilities ?? {} },\n \"Agent prompt capabilities\",\n );\n\n return instance;\n }\n\n private setupCrashDetection(): void {\n this.child.on(\"exit\", (code, signal) => {\n if (this._destroying) return;\n log.info(\n { sessionId: this.sessionId, exitCode: code, signal },\n \"Agent process exited\",\n );\n if ((code !== 0 && code !== null) || signal) {\n const stderr = this.stderrCapture.getLastLines();\n this.emit('agent_event', {\n type: \"error\",\n message: signal\n ? `Agent killed by signal ${signal}\\n${stderr}`\n : `Agent crashed (exit code ${code})\\n${stderr}`,\n });\n }\n });\n\n this.connection.closed.then(() => {\n log.debug({ sessionId: this.sessionId }, \"ACP connection closed\");\n });\n }\n\n static async spawn(\n agentDef: AgentDefinition,\n workingDirectory: string,\n mcpServers?: McpServerConfig[],\n ): Promise<AgentInstance> {\n log.debug(\n { agentName: agentDef.name, command: agentDef.command },\n \"Spawning agent\",\n );\n const spawnStart = Date.now();\n\n const instance = await AgentInstance.spawnSubprocess(\n agentDef,\n workingDirectory,\n );\n\n const resolvedMcp = AgentInstance.mcpManager.resolve(mcpServers);\n const response = await instance.connection.newSession({\n cwd: workingDirectory,\n mcpServers: resolvedMcp as any,\n });\n instance.sessionId = response.sessionId;\n instance.initialSessionResponse = response;\n instance.debugTracer = createDebugTracer(response.sessionId, workingDirectory);\n instance.setupCrashDetection();\n\n log.info(\n { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },\n \"Agent spawn complete\",\n );\n return instance;\n }\n\n static async resume(\n agentDef: AgentDefinition,\n workingDirectory: string,\n agentSessionId: string,\n mcpServers?: McpServerConfig[],\n ): Promise<AgentInstance> {\n log.debug({ agentName: agentDef.name, agentSessionId }, \"Resuming agent\");\n const spawnStart = Date.now();\n\n const instance = await AgentInstance.spawnSubprocess(\n agentDef,\n workingDirectory,\n );\n\n try {\n const response = await instance.connection.unstable_resumeSession({\n sessionId: agentSessionId,\n cwd: workingDirectory,\n });\n instance.sessionId = response.sessionId;\n instance.initialSessionResponse = response;\n instance.debugTracer = createDebugTracer(response.sessionId, workingDirectory);\n log.info(\n { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },\n \"Agent resume complete\",\n );\n } catch (err) {\n log.warn(\n { err, agentSessionId },\n \"Resume failed, falling back to new session\",\n );\n const resolvedMcp = AgentInstance.mcpManager.resolve(mcpServers);\n const response = await instance.connection.newSession({\n cwd: workingDirectory,\n mcpServers: resolvedMcp as any,\n });\n instance.sessionId = response.sessionId;\n instance.initialSessionResponse = response;\n instance.debugTracer = createDebugTracer(response.sessionId, workingDirectory);\n log.info(\n { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },\n \"Agent fallback spawn complete\",\n );\n }\n\n instance.setupCrashDetection();\n return instance;\n }\n\n // createClient — implemented in Task 6b\n private createClient(_agent: Agent): Client {\n const self = this;\n const MAX_OUTPUT_BYTES = 1024 * 1024; // 1MB cap\n\n return {\n // ── Session updates ──────────────────────────────────────────────────\n async sessionUpdate(params) {\n const update = params.update;\n let event: AgentEvent | null = null;\n\n switch (update.sessionUpdate) {\n case \"agent_message_chunk\":\n if (update.content.type === \"text\") {\n event = { type: \"text\", content: update.content.text };\n } else if (update.content.type === \"image\") {\n // ACP SDK types don't expose data/mimeType fields for image content\n const c = update.content as unknown as { data: string; mimeType: string };\n event = { type: \"image_content\", data: c.data, mimeType: c.mimeType };\n } else if (update.content.type === \"audio\") {\n // ACP SDK types don't expose data/mimeType fields for audio content\n const c = update.content as unknown as { data: string; mimeType: string };\n event = { type: \"audio_content\", data: c.data, mimeType: c.mimeType };\n } else if (update.content.type === \"resource\") {\n // EmbeddedResource: content.resource is TextResourceContents or BlobResourceContents\n // TextResourceContents has { uri, text, mimeType? }\n // BlobResourceContents has { uri, blob, mimeType? }\n const c = update.content as unknown as {\n resource: { uri: string; text?: string; blob?: string; mimeType?: string };\n annotations?: { audience?: string[]; priority?: number };\n };\n // The EmbeddedResource content block doesn't carry a top-level name field —\n // use the uri as a fallback name since AgentEvent.resource_content requires one.\n event = {\n type: \"resource_content\",\n uri: c.resource.uri,\n name: c.resource.uri,\n text: c.resource.text ?? undefined,\n blob: c.resource.blob ?? undefined,\n mimeType: c.resource.mimeType ?? undefined,\n };\n } else if (update.content.type === \"resource_link\") {\n // ResourceLink: { uri, name, mimeType?, title?, description?, size? }\n const c = update.content as unknown as {\n uri: string;\n name: string;\n mimeType?: string | null;\n title?: string | null;\n description?: string | null;\n size?: number | null;\n };\n event = {\n type: \"resource_link\",\n uri: c.uri,\n name: c.name,\n mimeType: c.mimeType ?? undefined,\n title: c.title ?? undefined,\n description: c.description ?? undefined,\n size: c.size ?? undefined,\n };\n }\n break;\n case \"agent_thought_chunk\":\n if (update.content.type === \"text\") {\n event = { type: \"thought\", content: update.content.text };\n }\n break;\n case \"tool_call\": {\n const tc = update as unknown as SdkToolCallFields;\n event = {\n type: \"tool_call\",\n id: update.toolCallId,\n name: update.title,\n kind: update.kind ?? undefined,\n status: update.status ?? \"pending\",\n content: update.content ?? undefined,\n rawInput: tc.rawInput ?? undefined,\n rawOutput: tc.rawOutput ?? undefined,\n meta: tc._meta ?? undefined,\n };\n break;\n }\n case \"tool_call_update\": {\n const tcu = update as unknown as SdkToolCallFields;\n event = {\n type: \"tool_update\",\n id: update.toolCallId,\n name: update.title ?? undefined,\n kind: update.kind ?? undefined,\n status: update.status ?? \"pending\",\n content: update.content ?? undefined,\n rawInput: tcu.rawInput ?? undefined,\n rawOutput: tcu.rawOutput ?? undefined,\n meta: tcu._meta ?? undefined,\n };\n break;\n }\n case \"plan\":\n event = { type: \"plan\", entries: update.entries };\n break;\n case \"usage_update\":\n event = {\n type: \"usage\",\n tokensUsed: update.used,\n contextSize: update.size,\n cost: update.cost ?? undefined,\n };\n break;\n case \"available_commands_update\":\n event = {\n type: \"commands_update\",\n commands: update.availableCommands,\n };\n break;\n case \"session_info_update\": {\n const si = update as unknown as SdkSessionInfoUpdate;\n event = {\n type: \"session_info_update\",\n title: si.title ?? undefined,\n updatedAt: si.updatedAt ?? undefined,\n _meta: si._meta ?? undefined,\n };\n break;\n }\n case \"current_mode_update\": {\n const cm = update as unknown as SdkCurrentModeUpdate;\n event = {\n type: \"current_mode_update\",\n modeId: cm.currentModeId,\n };\n break;\n }\n case \"config_option_update\": {\n const co = update as unknown as SdkConfigOptionUpdate;\n event = {\n type: \"config_option_update\",\n options: (co.configOptions ?? []) as ConfigOption[],\n };\n break;\n }\n case \"user_message_chunk\": {\n const um = update as unknown as SdkUserMessageChunk;\n event = {\n type: \"user_message_chunk\",\n content: um.content?.text ?? \"\",\n };\n break;\n }\n // NOTE: model_update is NOT a session update type in the ACP SDK schema.\n // Model changes are applied via the unstable_setSessionModel() method and\n // the response is synchronous — the SDK does not push a model_update\n // notification to the client. Therefore AgentEvent \"model_update\" cannot\n // originate from sessionUpdate and must be emitted by callers of setModel()\n // if they need to propagate the change downstream.\n default:\n // Unknown update type — ignore\n return;\n }\n\n if (event !== null) {\n self.emit('agent_event', event);\n }\n },\n\n // ── Permission requests ──────────────────────────────────────────────\n async requestPermission(params) {\n const permissionRequest: PermissionRequest = {\n id: params.toolCall.toolCallId,\n description: params.toolCall.title ?? params.toolCall.toolCallId,\n options: params.options.map((opt: SdkPermissionOption) => ({\n id: opt.optionId,\n label: opt.name,\n isAllow: opt.kind === \"allow_once\" || opt.kind === \"allow_always\",\n })),\n };\n\n const selectedOptionId =\n await self.onPermissionRequest(permissionRequest);\n return {\n outcome: { outcome: \"selected\" as const, optionId: selectedOptionId },\n };\n },\n\n // ── File operations ──────────────────────────────────────────────────\n async readTextFile(params) {\n const p = params as unknown as SdkReadTextFileParams;\n // Hook: fs:beforeRead — modifiable, can block\n if (self.middlewareChain) {\n const result = await self.middlewareChain.execute('fs:beforeRead', { sessionId: self.sessionId, path: p.path, line: p.line, limit: p.limit }, async (r) => r);\n if (!result) return { content: \"\" }; // blocked by middleware\n p.path = result.path;\n }\n const content = await readTextFileWithRange(p.path, {\n line: p.line ?? undefined,\n limit: p.limit ?? undefined,\n });\n return { content };\n },\n\n async writeTextFile(params) {\n // Hook: fs:beforeWrite — modifiable, can block\n let writePath = params.path;\n let writeContent = params.content;\n if (self.middlewareChain) {\n const result = await self.middlewareChain.execute('fs:beforeWrite', { sessionId: self.sessionId, path: writePath, content: writeContent }, async (r) => r);\n if (!result) return {}; // blocked by middleware\n writePath = result.path;\n writeContent = result.content;\n }\n await fs.promises.mkdir(path.dirname(writePath), { recursive: true });\n await fs.promises.writeFile(writePath, writeContent, \"utf-8\");\n return {};\n },\n\n // ── Terminal operations (delegated to TerminalManager) ─────────────\n async createTerminal(params) {\n return self.terminalManager.createTerminal(\n self.sessionId,\n {\n command: params.command,\n args: params.args,\n env: params.env,\n cwd: params.cwd,\n outputByteLimit: params.outputByteLimit ?? MAX_OUTPUT_BYTES,\n },\n self.middlewareChain,\n );\n },\n\n async terminalOutput(params) {\n return self.terminalManager.getOutput(params.terminalId);\n },\n\n async waitForTerminalExit(params) {\n return self.terminalManager.waitForExit(params.terminalId);\n },\n\n async killTerminal(params) {\n self.terminalManager.kill(params.terminalId);\n return {};\n },\n\n async releaseTerminal(params) {\n self.terminalManager.release(params.terminalId);\n },\n };\n }\n\n // ── New ACP methods ──────────────────────────────────────────────────\n\n async setMode(modeId: string): Promise<void> {\n await this.connection.setSessionMode({ sessionId: this.sessionId, modeId });\n }\n\n async setConfigOption(\n configId: string,\n value: SetConfigOptionValue,\n ): Promise<SetSessionConfigOptionResponse> {\n return await this.connection.setSessionConfigOption({\n sessionId: this.sessionId,\n configId,\n ...value,\n } as any);\n }\n\n async setModel(modelId: string): Promise<void> {\n await this.connection.unstable_setSessionModel({\n sessionId: this.sessionId,\n modelId,\n });\n }\n\n async listSessions(\n cwd?: string,\n cursor?: string,\n ): Promise<ListSessionsResponse> {\n return await this.connection.listSessions({\n cwd: cwd ?? null,\n cursor: cursor ?? null,\n });\n }\n\n async loadSession(\n sessionId: string,\n cwd: string,\n mcpServers?: McpServerConfig[],\n ): Promise<LoadSessionResponse> {\n const resolvedMcp = AgentInstance.mcpManager.resolve(mcpServers);\n return await this.connection.loadSession({\n sessionId,\n cwd,\n mcpServers: resolvedMcp as any,\n });\n }\n\n async authenticate(methodId: string): Promise<void> {\n await this.connection.authenticate({ methodId });\n }\n\n async forkSession(\n sessionId: string,\n cwd: string,\n mcpServers?: McpServerConfig[],\n ): Promise<ForkSessionResponse> {\n const resolvedMcp = AgentInstance.mcpManager.resolve(mcpServers);\n return await this.connection.unstable_forkSession({\n sessionId,\n cwd,\n mcpServers: resolvedMcp as any,\n });\n }\n\n async closeSession(sessionId: string): Promise<void> {\n await this.connection.unstable_closeSession({ sessionId });\n }\n\n // ── Prompt & lifecycle ──────────────────────────────────────────────\n\n async prompt(text: string, attachments?: Attachment[]): Promise<PromptResponse> {\n const contentBlocks: Array<Record<string, unknown>> = [{ type: \"text\", text }];\n\n // MIME types supported by Claude API for base64 image content\n const SUPPORTED_IMAGE_MIMES = new Set([\"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\"]);\n\n for (const att of attachments ?? []) {\n const tooLarge = att.size > 10 * 1024 * 1024; // 10MB base64 guard\n\n if (att.type === \"image\" && this.promptCapabilities?.image && !tooLarge && SUPPORTED_IMAGE_MIMES.has(att.mimeType)) {\n const data = await fs.promises.readFile(att.filePath);\n contentBlocks.push({ type: \"image\", data: data.toString(\"base64\"), mimeType: att.mimeType });\n } else if (att.type === \"audio\" && this.promptCapabilities?.audio && !tooLarge) {\n const data = await fs.promises.readFile(att.filePath);\n contentBlocks.push({ type: \"audio\", data: data.toString(\"base64\"), mimeType: att.mimeType });\n } else {\n // Fallback: append file path to text so agent can read from disk\n if ((att.type === \"image\" || att.type === \"audio\") && !tooLarge) {\n log.debug(\n { type: att.type, capabilities: this.promptCapabilities ?? {} },\n \"Agent does not support %s content, falling back to file path\",\n att.type,\n );\n }\n (contentBlocks[0] as { text: string }).text += `\\n\\n[Attached file: ${att.filePath}]`;\n }\n }\n\n return this.connection.prompt({\n sessionId: this.sessionId,\n prompt: contentBlocks as any,\n });\n }\n\n async cancel(): Promise<void> {\n await this.connection.cancel({ sessionId: this.sessionId });\n }\n\n async destroy(): Promise<void> {\n this._destroying = true;\n\n // Cleanup terminals\n this.terminalManager.destroyAll();\n\n // If process already exited, nothing to do\n if (this.child.exitCode !== null) return;\n\n // Kill agent subprocess and wait for it to actually exit\n await new Promise<void>((resolve) => {\n // Register exit listener BEFORE sending signal to avoid race\n this.child.on(\"exit\", () => {\n clearTimeout(forceKillTimer);\n resolve();\n });\n\n this.child.kill(\"SIGTERM\");\n\n const forceKillTimer = setTimeout(() => {\n // Use exitCode check — child.killed is true after ANY kill() call\n if (this.child.exitCode === null) this.child.kill(\"SIGKILL\");\n resolve();\n }, 10_000);\n if (typeof forceKillTimer === 'object' && forceKillTimer !== null && 'unref' in forceKillTimer) {\n (forceKillTimer as NodeJS.Timeout).unref();\n }\n });\n }\n}\n","/**\n * A minimal, generic typed event emitter.\n *\n * Usage:\n * interface MyEvents {\n * data: (payload: string) => void\n * error: (err: Error) => void\n * }\n * const emitter = new TypedEmitter<MyEvents>()\n * emitter.on('data', (payload) => { ... })\n * emitter.emit('data', 'hello')\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class TypedEmitter<T extends Record<string & keyof T, (...args: any[]) => void>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private listeners = new Map<keyof T, Set<(...args: any[]) => void>>()\n private paused = false\n private buffer: Array<{ event: keyof T; args: unknown[] }> = []\n\n on<K extends keyof T>(event: K, listener: T[K]): this {\n let set = this.listeners.get(event)\n if (!set) {\n set = new Set()\n this.listeners.set(event, set)\n }\n set.add(listener)\n return this\n }\n\n off<K extends keyof T>(event: K, listener: T[K]): this {\n this.listeners.get(event)?.delete(listener)\n return this\n }\n\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n if (this.paused) {\n // Check passthrough filter — some events may bypass the pause\n if (this.passthroughFn?.(event, args)) {\n this.deliver(event, args)\n } else {\n this.buffer.push({ event, args })\n }\n return\n }\n this.deliver(event, args)\n }\n\n /**\n * Pause event delivery. Events emitted while paused are buffered.\n * Optionally pass a filter to allow specific events through even while paused.\n */\n pause(passthrough?: (event: keyof T, args: unknown[]) => boolean): void {\n this.paused = true\n this.passthroughFn = passthrough\n }\n private passthroughFn?: (event: keyof T, args: unknown[]) => boolean\n\n /** Resume event delivery and replay buffered events in order. */\n resume(): void {\n this.paused = false\n this.passthroughFn = undefined\n const buffered = this.buffer.splice(0)\n for (const { event, args } of buffered) {\n this.deliver(event, args)\n }\n }\n\n /** Discard all buffered events without delivering them. */\n clearBuffer(): void {\n this.buffer.length = 0\n }\n\n get isPaused(): boolean {\n return this.paused\n }\n\n get bufferSize(): number {\n return this.buffer.length\n }\n\n removeAllListeners(event?: keyof T): void {\n if (event) {\n this.listeners.delete(event)\n } else {\n this.listeners.clear()\n }\n }\n\n private deliver(event: keyof T, args: unknown[]): void {\n const set = this.listeners.get(event)\n if (!set) return\n for (const listener of set) {\n (listener as (...a: unknown[]) => void)(...args)\n }\n }\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\n\ninterface TerminalState {\n process: ChildProcess;\n output: string;\n exitStatus: { exitCode: number | null; signal: string | null } | null;\n command: string;\n startTime: number;\n}\n\ninterface CreateTerminalParams {\n command: string;\n args?: string[] | Array<{ name: string; value: string }>;\n env?: Array<{ name: string; value: string }>;\n cwd?: string;\n outputByteLimit?: number;\n}\n\ninterface TerminalOutputResult {\n output: string;\n truncated: boolean;\n exitStatus?: { exitCode: number | null; signal: string | null };\n}\n\ninterface WaitForExitResult {\n exitCode: number | null;\n signal: string | null;\n}\n\nexport class TerminalManager {\n private terminals: Map<string, TerminalState> = new Map();\n private maxOutputBytes: number;\n\n constructor(maxOutputBytes = 1024 * 1024) {\n this.maxOutputBytes = maxOutputBytes;\n }\n\n async createTerminal(\n sessionId: string,\n params: CreateTerminalParams,\n middlewareChain?: MiddlewareChain,\n ): Promise<{ terminalId: string }> {\n let termCommand = params.command;\n let termArgs = params.args ?? [];\n let termEnvArr = params.env ?? [];\n let termCwd = params.cwd ?? undefined;\n\n if (middlewareChain) {\n const envRecord: Record<string, string> = {};\n for (const ev of termEnvArr) { envRecord[ev.name] = ev.value; }\n const result = await middlewareChain.execute('terminal:beforeCreate', {\n sessionId,\n command: termCommand,\n args: termArgs as string[],\n env: envRecord,\n cwd: termCwd,\n }, async (p) => p);\n if (!result) return { terminalId: \"\" }; // blocked by middleware\n termCommand = result.command;\n termArgs = result.args ?? termArgs;\n termCwd = result.cwd ?? termCwd;\n if (result.env) {\n termEnvArr = Object.entries(result.env).map(([name, value]) => ({ name, value }));\n }\n }\n\n const terminalId = randomUUID();\n const args = termArgs as string[];\n const env: Record<string, string> = {};\n for (const ev of termEnvArr) {\n env[ev.name] = ev.value;\n }\n\n const childProcess = spawn(termCommand, args, {\n cwd: termCwd,\n env: { ...process.env, ...env },\n shell: false,\n });\n\n const state: TerminalState = {\n process: childProcess,\n output: \"\",\n exitStatus: null,\n command: termCommand,\n startTime: Date.now(),\n };\n this.terminals.set(terminalId, state);\n\n const outputByteLimit = params.outputByteLimit ?? this.maxOutputBytes;\n\n const appendOutput = (chunk: string) => {\n state.output += chunk;\n const bytes = Buffer.byteLength(state.output, \"utf-8\");\n if (bytes > outputByteLimit) {\n const excess = bytes - outputByteLimit;\n state.output = state.output.slice(excess);\n }\n };\n\n childProcess.stdout?.on(\"data\", (chunk: Buffer) =>\n appendOutput(chunk.toString()),\n );\n childProcess.stderr?.on(\"data\", (chunk: Buffer) =>\n appendOutput(chunk.toString()),\n );\n\n childProcess.on(\"exit\", (code, signal) => {\n state.exitStatus = { exitCode: code, signal };\n if (middlewareChain) {\n middlewareChain.execute('terminal:afterExit', {\n sessionId,\n terminalId,\n command: state.command,\n exitCode: code ?? -1,\n durationMs: Date.now() - state.startTime,\n }, async (p) => p).catch(() => {});\n }\n });\n\n return { terminalId };\n }\n\n getOutput(terminalId: string): TerminalOutputResult {\n const state = this.terminals.get(terminalId);\n if (!state) {\n throw new Error(`Terminal not found: ${terminalId}`);\n }\n return {\n output: state.output,\n truncated: false,\n exitStatus: state.exitStatus\n ? {\n exitCode: state.exitStatus.exitCode,\n signal: state.exitStatus.signal,\n }\n : undefined,\n };\n }\n\n async waitForExit(terminalId: string): Promise<WaitForExitResult> {\n const state = this.terminals.get(terminalId);\n if (!state) {\n throw new Error(`Terminal not found: ${terminalId}`);\n }\n if (state.exitStatus !== null) {\n return {\n exitCode: state.exitStatus.exitCode,\n signal: state.exitStatus.signal,\n };\n }\n return new Promise((resolve) => {\n state.process.on(\"exit\", (code, signal) => {\n resolve({ exitCode: code, signal });\n });\n });\n }\n\n kill(terminalId: string): void {\n const state = this.terminals.get(terminalId);\n if (!state) {\n throw new Error(`Terminal not found: ${terminalId}`);\n }\n state.process.kill(\"SIGTERM\");\n }\n\n release(terminalId: string): void {\n const state = this.terminals.get(terminalId);\n if (!state) {\n return;\n }\n state.process.kill(\"SIGKILL\");\n this.terminals.delete(terminalId);\n }\n\n destroyAll(): void {\n for (const [, t] of this.terminals) {\n t.process.kill(\"SIGKILL\");\n }\n this.terminals.clear();\n }\n}\n","import type { McpServerConfig } from \"../types.js\";\n\n/**\n * Resolves MCP server configuration for agent sessions.\n * Centralizes the logic for providing MCP servers to newSession/resumeSession/loadSession/forkSession.\n */\nexport class McpManager {\n /**\n * Resolve the MCP server config to pass to ACP session methods.\n * Returns the provided config array or an empty array if none given.\n */\n resolve(sessionConfig?: McpServerConfig[]): McpServerConfig[] {\n return sessionConfig ?? [];\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type TraceLayer = \"acp\" | \"core\" | \"telegram\";\n\n// Evaluated once at module load — zero overhead when disabled\nconst DEBUG_ENABLED = process.env.OPENACP_DEBUG === \"true\" || process.env.OPENACP_DEBUG === \"1\";\n\n/**\n * Per-session debug trace logger. Writes JSONL files to <workingDirectory>/.log/.\n * Only active when OPENACP_DEBUG=true. Zero overhead when disabled.\n *\n * Note: Uses appendFileSync for simplicity. This blocks the event loop briefly per write,\n * which is acceptable for a debug-only tool. The DEBUG_ENABLED guard ensures zero overhead\n * in production.\n */\nexport class DebugTracer {\n private dirCreated = false;\n private logDir: string;\n\n constructor(\n private sessionId: string,\n private workingDirectory: string,\n ) {\n this.logDir = path.join(workingDirectory, \".log\");\n }\n\n log(layer: TraceLayer, data: Record<string, unknown>): void {\n try {\n if (!this.dirCreated) {\n fs.mkdirSync(this.logDir, { recursive: true });\n this.dirCreated = true;\n }\n const filePath = path.join(this.logDir, `${this.sessionId}_${layer}.jsonl`);\n const line = JSON.stringify({ ts: Date.now(), ...data }) + \"\\n\";\n fs.appendFileSync(filePath, line);\n } catch {\n // Debug logging must never crash the app\n }\n }\n\n /** No-op cleanup — establishes the pattern for future async implementations */\n destroy(): void {\n // No file handles to close with appendFileSync\n }\n}\n\n/**\n * Create a DebugTracer if debug mode is enabled, otherwise return null.\n * The DEBUG_ENABLED const is evaluated once at module load time from process.env.OPENACP_DEBUG.\n */\nexport function createDebugTracer(sessionId: string, workingDirectory: string): DebugTracer | null {\n if (!DEBUG_ENABLED) return null;\n return new DebugTracer(sessionId, workingDirectory);\n}\n","import type { AgentDefinition } from \"../types.js\";\nimport { AgentInstance } from \"./agent-instance.js\";\nimport type { AgentCatalog } from \"./agent-catalog.js\";\n\nexport class AgentManager {\n constructor(private catalog: AgentCatalog) {}\n\n getAvailableAgents(): AgentDefinition[] {\n const installed = this.catalog.getInstalledEntries();\n return Object.entries(installed).map(([key, agent]) => ({\n name: key,\n command: agent.command,\n args: agent.args,\n env: agent.env,\n }));\n }\n\n getAgent(name: string): AgentDefinition | undefined {\n return this.catalog.resolve(name);\n }\n\n async spawn(\n agentName: string,\n workingDirectory: string,\n ): Promise<AgentInstance> {\n const agentDef = this.getAgent(agentName);\n if (!agentDef) throw new Error(`Agent \"${agentName}\" is not installed. Run \"openacp agents install ${agentName}\" to add it.`);\n return AgentInstance.spawn(agentDef, workingDirectory);\n }\n\n async resume(\n agentName: string,\n workingDirectory: string,\n agentSessionId: string,\n ): Promise<AgentInstance> {\n const agentDef = this.getAgent(agentName);\n if (!agentDef) throw new Error(`Agent \"${agentName}\" is not installed. Run \"openacp agents install ${agentName}\" to add it.`);\n return AgentInstance.resume(agentDef, workingDirectory, agentSessionId);\n }\n}\n","import { nanoid } from \"nanoid\";\nimport type { AgentInstance } from \"../agents/agent-instance.js\";\nimport type { AgentCapabilities, AgentEvent, AgentSwitchEntry, Attachment, PermissionRequest, SessionStatus, SessionMode, ConfigOption, ModelInfo, SessionModeState, SessionModelState } from \"../types.js\";\nimport { TypedEmitter } from \"../utils/typed-emitter.js\";\nimport { PromptQueue } from \"./prompt-queue.js\";\nimport { PermissionGate } from \"./permission-gate.js\";\nimport { createChildLogger, createSessionLogger, closeSessionLogger, type Logger } from \"../utils/log.js\";\nimport type { SpeechService } from \"../../plugins/speech/exports.js\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\nimport * as fs from \"node:fs\";\nconst moduleLog = createChildLogger({ module: \"session\" });\n\n// TTS constants\nexport const TTS_PROMPT_INSTRUCTION = `\\n\\nAdditionally, include a [TTS]...[/TTS] block with a spoken-friendly summary of your response. Focus on key information, decisions the user needs to make, or actions required. The agent decides what to say and how long. Respond in the same language the user is using. This instruction applies to this message only.`;\nexport const TTS_BLOCK_REGEX = /\\[TTS\\]([\\s\\S]*?)\\[\\/TTS\\]/;\nexport const TTS_MAX_LENGTH = 5000;\nexport const TTS_TIMEOUT_MS = 30_000;\n\n// Valid state transitions: from → Set<to>\nconst VALID_TRANSITIONS: Record<SessionStatus, Set<SessionStatus>> = {\n initializing: new Set([\"active\", \"error\"]),\n active: new Set([\"error\", \"finished\", \"cancelled\"]),\n error: new Set([\"active\", \"cancelled\"]),\n cancelled: new Set([\"active\"]),\n finished: new Set(),\n};\n\nexport interface SessionEvents {\n agent_event: (event: AgentEvent) => void;\n permission_request: (request: PermissionRequest) => void;\n session_end: (reason: string) => void;\n status_change: (from: SessionStatus, to: SessionStatus) => void;\n named: (name: string) => void;\n error: (error: Error) => void;\n prompt_count_changed: (count: number) => void;\n}\n\nexport class Session extends TypedEmitter<SessionEvents> {\n id: string;\n channelId: string;\n threadId: string = \"\";\n agentName: string;\n workingDirectory: string;\n agentInstance: AgentInstance;\n agentSessionId: string = \"\";\n private _status: SessionStatus = \"initializing\";\n name?: string;\n createdAt: Date = new Date();\n voiceMode: \"off\" | \"next\" | \"on\" = \"off\";\n dangerousMode: boolean = false;\n currentMode?: string;\n availableModes: SessionMode[] = [];\n configOptions: ConfigOption[] = [];\n currentModel?: string;\n availableModels: ModelInfo[] = [];\n agentCapabilities?: AgentCapabilities;\n archiving: boolean = false;\n promptCount: number = 0;\n firstAgent: string;\n agentSwitchHistory: AgentSwitchEntry[] = [];\n log: Logger;\n middlewareChain?: MiddlewareChain;\n\n readonly permissionGate = new PermissionGate();\n private readonly queue: PromptQueue;\n private speechService?: SpeechService;\n private pendingContext: string | null = null;\n\n constructor(opts: {\n id?: string;\n channelId: string;\n agentName: string;\n workingDirectory: string;\n agentInstance: AgentInstance;\n speechService?: SpeechService;\n }) {\n super();\n this.id = opts.id || nanoid(12);\n this.channelId = opts.channelId;\n this.agentName = opts.agentName;\n this.firstAgent = opts.agentName;\n this.workingDirectory = opts.workingDirectory;\n this.agentInstance = opts.agentInstance;\n this.speechService = opts.speechService;\n this.log = createSessionLogger(this.id, moduleLog);\n this.log.info({ agentName: this.agentName }, \"Session created\");\n\n this.queue = new PromptQueue(\n (text, attachments) => this.processPrompt(text, attachments),\n (err) => {\n this.fail(\"Prompt execution failed\");\n this.log.error({ err }, \"Prompt execution failed\");\n },\n );\n }\n\n // --- State Machine ---\n\n get status(): SessionStatus {\n return this._status;\n }\n\n\n /** Transition to active — from initializing, error, or cancelled */\n activate(): void {\n this.transition(\"active\");\n }\n\n /** Transition to error — from initializing or active */\n fail(reason: string): void {\n this.transition(\"error\");\n this.emit(\"error\", new Error(reason));\n }\n\n /** Transition to finished — from active only. Emits session_end for backward compat. */\n finish(reason?: string): void {\n this.transition(\"finished\");\n this.emit(\"session_end\", reason ?? \"completed\");\n }\n\n /** Transition to cancelled — from active only (terminal session cancel) */\n markCancelled(): void {\n this.transition(\"cancelled\");\n }\n\n private transition(to: SessionStatus): void {\n const from = this._status;\n const allowed = VALID_TRANSITIONS[from];\n if (!allowed?.has(to)) {\n throw new Error(\n `Invalid session transition: ${from} → ${to}`,\n );\n }\n this._status = to;\n this.log.debug({ from, to }, \"Session status transition\");\n this.emit(\"status_change\", from, to);\n }\n\n /** Number of prompts waiting in queue */\n get queueDepth(): number {\n return this.queue.pending;\n }\n\n get promptRunning(): boolean {\n return this.queue.isProcessing;\n }\n\n // --- Context Injection ---\n\n setContext(markdown: string): void {\n this.pendingContext = markdown;\n }\n\n // --- Voice Mode ---\n\n setVoiceMode(mode: \"off\" | \"next\" | \"on\"): void {\n this.voiceMode = mode;\n this.log.info({ voiceMode: mode }, \"TTS mode changed\");\n }\n\n // --- Public API ---\n\n async enqueuePrompt(text: string, attachments?: Attachment[]): Promise<void> {\n // Hook: agent:beforePrompt — modifiable, can block\n if (this.middlewareChain) {\n const payload = { text, attachments, sessionId: this.id };\n const result = await this.middlewareChain.execute('agent:beforePrompt', payload, async (p) => p);\n if (!result) return; // blocked by middleware\n text = result.text;\n attachments = result.attachments;\n }\n await this.queue.enqueue(text, attachments);\n }\n\n private async processPrompt(text: string, attachments?: Attachment[]): Promise<void> {\n if (text === \"\\x00__warmup__\") {\n await this.runWarmup();\n return;\n }\n\n // Don't process prompts for finished sessions (queue may still drain)\n if (this._status === \"finished\") return;\n\n this.promptCount++;\n this.emit('prompt_count_changed', this.promptCount);\n\n if (this._status === \"initializing\" || this._status === \"cancelled\" || this._status === \"error\") {\n this.activate();\n }\n const promptStart = Date.now();\n this.log.debug(\"Prompt execution started\");\n\n // Context injection: prepend on first real prompt only\n const contextUsed = this.pendingContext;\n if (contextUsed) {\n text = `[CONVERSATION HISTORY - This is context from previous sessions, not current conversation]\\n\\n${contextUsed}\\n\\n[END CONVERSATION HISTORY]\\n\\n${text}`;\n this.log.debug(\"Context injected into prompt\");\n }\n\n // STT: transcribe audio attachments if agent doesn't support audio\n const processed = await this.maybeTranscribeAudio(text, attachments);\n\n // TTS: determine if TTS is active for this prompt\n const ttsActive =\n this.voiceMode !== \"off\" &&\n !!this.speechService?.isTTSAvailable();\n\n // TTS: inject prompt instruction\n if (ttsActive) {\n processed.text += TTS_PROMPT_INSTRUCTION;\n }\n\n // TTS: set up text accumulator before prompting\n let accumulatedText = \"\";\n const accumulatorListener = ttsActive\n ? (event: AgentEvent) => {\n if (event.type === \"text\") {\n accumulatedText += event.content;\n }\n }\n : null;\n\n if (accumulatorListener) {\n this.on(\"agent_event\", accumulatorListener);\n }\n\n // Hook: turn:start — read-only, fire-and-forget\n if (this.middlewareChain) {\n this.middlewareChain.execute('turn:start', { sessionId: this.id, promptText: processed.text, promptNumber: this.promptCount }, async (p) => p).catch(() => {});\n }\n\n let stopReason: string = 'end_turn';\n try {\n const response = await this.agentInstance.prompt(processed.text, processed.attachments);\n if (response && typeof response === 'object' && 'stopReason' in response) {\n stopReason = (response as { stopReason?: string }).stopReason ?? 'end_turn';\n }\n // Clear context only after successful prompt — if prompt fails, context is preserved for retry\n if (contextUsed) {\n this.pendingContext = null;\n }\n // Reset \"next\" voice mode only after successful prompt\n if (ttsActive && this.voiceMode === \"next\") {\n this.voiceMode = \"off\";\n }\n } finally {\n if (accumulatorListener) {\n this.off(\"agent_event\", accumulatorListener);\n }\n }\n\n // Hook: turn:end — read-only, fire-and-forget\n if (this.middlewareChain) {\n this.middlewareChain.execute('turn:end', { sessionId: this.id, stopReason: stopReason as import('../types.js').StopReason, durationMs: Date.now() - promptStart }, async (p) => p).catch(() => {});\n }\n\n this.log.info(\n { durationMs: Date.now() - promptStart },\n \"Prompt execution completed\",\n );\n\n // TTS: fire-and-forget post-response synthesis\n if (ttsActive && accumulatedText) {\n this.processTTSResponse(accumulatedText).catch((err) => {\n this.log.warn({ err }, \"TTS post-processing failed\");\n });\n }\n\n if (!this.name) {\n await this.autoName();\n }\n }\n\n private async maybeTranscribeAudio(\n text: string,\n attachments?: Attachment[],\n ): Promise<{ text: string; attachments?: Attachment[] }> {\n if (!attachments?.length || !this.speechService) {\n return { text, attachments };\n }\n\n const hasAudioCapability = this.agentInstance.promptCapabilities?.audio === true;\n if (hasAudioCapability) {\n return { text, attachments };\n }\n\n if (!this.speechService.isSTTAvailable()) {\n return { text, attachments };\n }\n\n let transcribedText = text;\n const remainingAttachments: Attachment[] = [];\n\n for (const att of attachments) {\n if (att.type !== \"audio\") {\n remainingAttachments.push(att);\n continue;\n }\n\n try {\n const audioPath = att.originalFilePath || att.filePath;\n const audioMime = att.originalFilePath ? \"audio/ogg\" : att.mimeType;\n const audioBuffer = await fs.promises.readFile(audioPath);\n const result = await this.speechService.transcribe(audioBuffer, audioMime);\n this.log.info({ provider: \"stt\", duration: result.duration }, \"Voice transcribed\");\n // Notify user of transcription result\n this.emit(\"agent_event\", {\n type: \"system_message\",\n message: `🎤 You said: ${result.text}`,\n });\n // Strip [Audio: ...] placeholder since we have the transcription\n transcribedText = transcribedText.replace(/\\[Audio:\\s*[^\\]]*\\]\\s*/g, \"\").trim();\n transcribedText = transcribedText\n ? `${transcribedText}\\n${result.text}`\n : result.text;\n } catch (err) {\n this.log.warn({ err }, \"STT transcription failed, keeping audio attachment\");\n this.emit(\"agent_event\", {\n type: \"error\",\n message: `Voice transcription failed: ${(err as Error).message}`,\n });\n remainingAttachments.push(att);\n }\n }\n\n return {\n text: transcribedText,\n attachments: remainingAttachments.length > 0 ? remainingAttachments : undefined,\n };\n }\n\n private async processTTSResponse(responseText: string): Promise<void> {\n const match = TTS_BLOCK_REGEX.exec(responseText);\n if (!match?.[1]) {\n this.log.debug(\"No [TTS] block found in response, skipping synthesis\");\n return;\n }\n\n let ttsText = match[1].trim();\n if (!ttsText) return;\n\n if (ttsText.length > TTS_MAX_LENGTH) {\n ttsText = ttsText.slice(0, TTS_MAX_LENGTH);\n }\n\n try {\n let ttsTimer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n ttsTimer = setTimeout(() => reject(new Error(\"TTS synthesis timed out\")), TTS_TIMEOUT_MS);\n });\n try {\n const result = await Promise.race([\n this.speechService!.synthesize(ttsText),\n timeoutPromise,\n ]);\n const base64 = result.audioBuffer.toString(\"base64\");\n this.emit(\"agent_event\", {\n type: \"audio_content\",\n data: base64,\n mimeType: result.mimeType,\n });\n this.emit(\"agent_event\", { type: \"tts_strip\" });\n this.log.info(\"TTS synthesis completed\");\n } finally {\n clearTimeout(ttsTimer!);\n }\n } catch (err) {\n this.log.warn({ err }, \"TTS synthesis failed, skipping\");\n }\n }\n\n // NOTE: This injects a summary prompt into the agent's conversation history.\n private async autoName(): Promise<void> {\n let title = \"\";\n\n // Temporarily remove all agent_event listeners so auto-name output\n // is not forwarded to the adapter. Add a capture-only listener instead.\n const captureHandler = (event: AgentEvent) => {\n if (event.type === \"text\") title += event.content;\n // Swallow all other events from auto-name prompt\n };\n\n // Pause the session emitter so agent_event emissions from SessionBridge\n // don't reach the adapter during auto-name. The AgentInstance emitter\n // stays active — we just intercept with our capture handler.\n this.pause((event) => event !== \"agent_event\");\n this.agentInstance.on(\"agent_event\", captureHandler);\n\n try {\n await this.agentInstance.prompt(\n \"Summarize this conversation in max 5 words for a topic title. Reply ONLY with the title, nothing else.\",\n );\n this.name = title.trim().slice(0, 50) || `Session ${this.id.slice(0, 6)}`;\n this.log.info({ name: this.name }, \"Session auto-named\");\n\n // Emit named event — SessionBridge listens to rename the thread\n this.emit(\"named\", this.name);\n } catch {\n this.name = `Session ${this.id.slice(0, 6)}`;\n } finally {\n this.agentInstance.off(\"agent_event\", captureHandler);\n // Discard buffered auto-name agent_events, then resume normal delivery\n this.clearBuffer();\n this.resume();\n }\n }\n\n /** Fire-and-forget warm-up: primes model cache while user types their first message */\n async warmup(): Promise<void> {\n // Route through PromptQueue to prevent concurrent prompt execution.\n // Any user prompts arriving during warmup will be queued and drained after.\n await this.queue.enqueue(\"\\x00__warmup__\");\n }\n\n private async runWarmup(): Promise<void> {\n // Pause events but let commands_update pass through\n this.pause((_event, args) => {\n const agentEvent = args[0] as AgentEvent;\n return agentEvent?.type === \"commands_update\";\n });\n\n try {\n const start = Date.now();\n await this.agentInstance.prompt('Reply with only \"ready\".');\n this.activate();\n this.log.info({ durationMs: Date.now() - start }, \"Warm-up complete\");\n } catch (err) {\n this.log.error({ err }, \"Warm-up failed\");\n } finally {\n this.clearBuffer();\n this.resume();\n }\n }\n\n // --- ACP Mode / Config / Model State ---\n\n setInitialAcpState(state: {\n modes?: SessionModeState | null;\n configOptions?: ConfigOption[] | null;\n models?: SessionModelState | null;\n agentCapabilities?: AgentCapabilities | null;\n }): void {\n if (state.modes) {\n this.currentMode = state.modes.currentModeId;\n this.availableModes = state.modes.availableModes;\n }\n if (state.configOptions) {\n this.configOptions = state.configOptions;\n }\n if (state.models) {\n this.currentModel = state.models.currentModelId;\n this.availableModels = state.models.availableModels;\n }\n if (state.agentCapabilities) {\n this.agentCapabilities = state.agentCapabilities;\n }\n }\n\n /** Set session name explicitly and emit 'named' event */\n setName(name: string): void {\n this.name = name;\n this.emit(\"named\", name);\n }\n\n async updateMode(modeId: string): Promise<void> {\n // Hook: mode:beforeChange — await-able, can block\n if (this.middlewareChain) {\n const result = await this.middlewareChain.execute('mode:beforeChange', { sessionId: this.id, fromMode: this.currentMode, toMode: modeId }, async (p) => p);\n if (!result) return; // blocked by middleware\n }\n this.currentMode = modeId;\n }\n\n async updateConfigOptions(options: ConfigOption[]): Promise<void> {\n // Hook: config:beforeChange — await-able, can block\n if (this.middlewareChain) {\n const result = await this.middlewareChain.execute('config:beforeChange', { sessionId: this.id, configId: 'options', oldValue: this.configOptions, newValue: options }, async (p) => p);\n if (!result) return; // blocked by middleware\n }\n this.configOptions = options;\n }\n\n async updateModel(modelId: string): Promise<void> {\n // Hook: model:beforeChange — await-able, can block\n if (this.middlewareChain) {\n const result = await this.middlewareChain.execute('model:beforeChange', { sessionId: this.id, fromModel: this.currentModel, toModel: modelId }, async (p) => p);\n if (!result) return; // blocked by middleware\n }\n this.currentModel = modelId;\n }\n\n /** Snapshot of current ACP state for persistence */\n toAcpStateSnapshot(): NonNullable<import(\"../types.js\").SessionRecord[\"acpState\"]> {\n return {\n currentMode: this.currentMode,\n availableModes: this.availableModes.length > 0 ? this.availableModes : undefined,\n configOptions: this.configOptions.length > 0 ? this.configOptions : undefined,\n currentModel: this.currentModel,\n availableModels: this.availableModels.length > 0 ? this.availableModels : undefined,\n agentCapabilities: this.agentCapabilities,\n };\n }\n\n /** Check if the agent supports a specific session capability */\n supportsCapability(cap: 'list' | 'fork' | 'close' | 'loadSession'): boolean {\n if (cap === 'loadSession') return this.agentCapabilities?.loadSession === true;\n return this.agentCapabilities?.sessionCapabilities?.[cap] === true;\n }\n\n /** Cancel the current prompt and clear the queue. Stays in active state. */\n async abortPrompt(): Promise<void> {\n // Hook: agent:beforeCancel — modifiable, can block\n if (this.middlewareChain) {\n const result = await this.middlewareChain.execute('agent:beforeCancel', { sessionId: this.id }, async (p) => p);\n if (!result) return; // blocked by middleware\n }\n this.queue.clear();\n this.log.info(\"Prompt aborted\");\n await this.agentInstance.cancel();\n }\n\n /** Search backward through agentSwitchHistory for the last entry matching agentName */\n findLastSwitchEntry(agentName: string): AgentSwitchEntry | undefined {\n for (let i = this.agentSwitchHistory.length - 1; i >= 0; i--) {\n if (this.agentSwitchHistory[i].agentName === agentName) {\n return this.agentSwitchHistory[i];\n }\n }\n return undefined;\n }\n\n /** Switch the agent instance in-place, preserving session identity */\n async switchAgent(agentName: string, createAgent: () => Promise<AgentInstance>): Promise<void> {\n if (agentName === this.agentName) {\n throw new Error(`Already using ${agentName}`);\n }\n\n // Record current agent in history\n this.agentSwitchHistory.push({\n agentName: this.agentName,\n agentSessionId: this.agentSessionId,\n switchedAt: new Date().toISOString(),\n promptCount: this.promptCount,\n });\n\n // Clear queued prompts and abort in-flight prompt before destroying old agent\n this.queue.clear();\n\n // Reject any pending permission request before destroying old agent\n if (this.permissionGate.isPending) {\n this.permissionGate.reject(\"Agent switched\");\n }\n\n // Destroy old agent\n await this.agentInstance.destroy();\n\n // Create and wire new agent\n const newAgent = await createAgent();\n this.agentInstance = newAgent;\n this.agentName = agentName;\n this.agentSessionId = newAgent.sessionId;\n this.promptCount = 0;\n\n // Reset agent-specific ACP state (will be re-populated by new agent)\n this.agentCapabilities = undefined;\n this.currentMode = undefined;\n this.availableModes = [];\n this.currentModel = undefined;\n this.availableModels = [];\n this.configOptions = [];\n\n this.log.info({ from: this.agentSwitchHistory.at(-1)!.agentName, to: agentName }, \"Agent switched\");\n }\n\n async destroy(): Promise<void> {\n this.log.info(\"Session destroyed\");\n // Reject any pending permission promise so callers don't hang\n if (this.permissionGate.isPending) {\n this.permissionGate.reject(\"Session destroyed\");\n }\n // Clear queued prompts\n this.queue.clear();\n await this.agentInstance.destroy();\n closeSessionLogger(this.log);\n }\n}\n","import type { Attachment } from '../types.js'\n\n/**\n * Serial prompt queue — ensures prompts are processed one at a time.\n */\nexport class PromptQueue {\n private queue: Array<{ text: string; attachments?: Attachment[]; resolve: () => void }> = []\n private processing = false\n private abortController: AbortController | null = null\n\n constructor(\n private processor: (text: string, attachments?: Attachment[]) => Promise<void>,\n private onError?: (err: unknown) => void,\n ) {}\n\n async enqueue(text: string, attachments?: Attachment[]): Promise<void> {\n if (this.processing) {\n return new Promise<void>((resolve) => {\n this.queue.push({ text, attachments, resolve })\n })\n }\n await this.process(text, attachments)\n }\n\n private async process(text: string, attachments?: Attachment[]): Promise<void> {\n this.processing = true\n this.abortController = new AbortController()\n const { signal } = this.abortController\n try {\n await Promise.race([\n this.processor(text, attachments),\n new Promise<never>((_, reject) => {\n signal.addEventListener('abort', () => reject(new Error('Prompt aborted')), { once: true })\n }),\n ])\n } catch (err) {\n // Only forward non-abort errors to onError handler\n if (!(err instanceof Error && err.message === 'Prompt aborted')) {\n this.onError?.(err)\n }\n } finally {\n this.abortController = null\n this.processing = false\n this.drainNext()\n }\n }\n\n private drainNext(): void {\n const next = this.queue.shift()\n if (next) {\n this.process(next.text, next.attachments).then(next.resolve)\n }\n }\n\n clear(): void {\n // Abort the currently running prompt so the queue can drain\n if (this.abortController) {\n this.abortController.abort()\n }\n // Resolve pending promises so callers don't hang\n for (const item of this.queue) {\n item.resolve()\n }\n this.queue = []\n }\n\n get pending(): number {\n return this.queue.length\n }\n\n get isProcessing(): boolean {\n return this.processing\n }\n}\n","import type { PermissionRequest } from \"../types.js\";\n\nconst DEFAULT_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes\n\n/**\n * Encapsulates pending permission state with a typed Promise API.\n */\nexport class PermissionGate {\n private request?: PermissionRequest;\n private resolveFn?: (optionId: string) => void;\n private rejectFn?: (reason: Error) => void;\n private settled = false;\n private timeoutTimer?: ReturnType<typeof setTimeout>;\n private timeoutMs: number;\n\n constructor(timeoutMs?: number) {\n this.timeoutMs = timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n setPending(request: PermissionRequest): Promise<string> {\n // Reject any existing pending promise so callers don't hang forever\n if (!this.settled && this.rejectFn) {\n this.rejectFn(new Error(\"Superseded by new permission request\"));\n }\n this.request = request;\n this.settled = false;\n this.clearTimeout();\n\n return new Promise<string>((resolve, reject) => {\n this.resolveFn = resolve;\n this.rejectFn = reject;\n\n this.timeoutTimer = setTimeout(() => {\n this.reject(\"Permission request timed out (no response received)\");\n }, this.timeoutMs);\n if (typeof this.timeoutTimer === 'object' && 'unref' in this.timeoutTimer) {\n (this.timeoutTimer as NodeJS.Timeout).unref();\n }\n });\n }\n\n resolve(optionId: string): void {\n if (this.settled || !this.resolveFn) return;\n this.settled = true;\n this.clearTimeout();\n this.resolveFn(optionId);\n this.cleanup();\n }\n\n reject(reason?: string): void {\n if (this.settled || !this.rejectFn) return;\n this.settled = true;\n this.clearTimeout();\n this.rejectFn(new Error(reason ?? \"Permission rejected\"));\n this.cleanup();\n }\n\n get isPending(): boolean {\n return !!this.request && !this.settled;\n }\n\n get currentRequest(): PermissionRequest | undefined {\n return this.isPending ? this.request : undefined;\n }\n\n /** The request ID of the current pending request, undefined after settlement */\n get requestId(): string | undefined {\n return this.request?.id;\n }\n\n private clearTimeout(): void {\n if (this.timeoutTimer) {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = undefined;\n }\n }\n\n private cleanup(): void {\n this.request = undefined;\n this.resolveFn = undefined;\n this.rejectFn = undefined;\n }\n}\n","export interface FileInfo {\n filePath: string\n content: string\n oldContent?: string\n}\n\n/**\n * Extract file path and content from ACP tool_call/tool_update content.\n *\n * ACP content formats observed:\n * - Diff block: [{ type: \"diff\", path: \"...\", oldText: \"...\", newText: \"...\" }]\n * - Content wrapper: [{ type: \"content\", content: { type: \"text\", text: \"...\" } }]\n * - Text block: { type: \"text\", text: \"...\" }\n * - rawInput: { file_path: \"...\", content: \"...\" }\n */\nexport function extractFileInfo(\n name: string,\n kind: string | undefined,\n content: unknown,\n rawInput?: unknown,\n meta?: unknown,\n): FileInfo | null {\n // Only process file-related tool kinds\n if (kind && !['read', 'edit', 'write'].includes(kind)) return null\n\n let info: Partial<FileInfo> | null = null\n\n // 1. Try agent-specific _meta extensions (e.g. _meta.claudeCode.toolResponse)\n // This is the highest-fidelity source — raw file content without formatting.\n // Falls through to generic paths 2-3 for agents that don't use this namespace.\n if (meta) {\n const m = meta as Record<string, unknown>\n const toolResponse = resolveToolResponse(m)\n\n if (toolResponse) {\n // Read: toolResponse.file.filePath + file.content\n const file = toolResponse.file as Record<string, unknown> | undefined\n if (typeof file?.filePath === 'string' && typeof file?.content === 'string') {\n info = { filePath: file.filePath, content: file.content }\n }\n // Edit: toolResponse.originalFile (full before-edit content) + oldString/newString\n if (!info && typeof toolResponse.filePath === 'string' && typeof toolResponse.originalFile === 'string') {\n const originalFile = toolResponse.originalFile as string\n const oldString = typeof toolResponse.oldString === 'string' ? toolResponse.oldString : undefined\n const newString = typeof toolResponse.newString === 'string' ? toolResponse.newString : undefined\n const newContent = oldString && newString\n ? originalFile.replace(oldString, newString)\n : originalFile\n info = { filePath: toolResponse.filePath as string, content: newContent, oldContent: originalFile }\n }\n // Write: toolResponse.filePath + toolResponse.content\n if (!info && typeof toolResponse.filePath === 'string' && typeof toolResponse.content === 'string') {\n info = { filePath: toolResponse.filePath, content: toolResponse.content }\n }\n }\n }\n\n // 2. Try rawInput for file path + content\n if (!info && rawInput && typeof rawInput === 'object') {\n const ri = rawInput as Record<string, unknown>\n const filePath = ri?.file_path || ri?.filePath || ri?.path\n if (typeof filePath === 'string') {\n const parsed = content ? parseContent(content) : null\n const riContent = typeof ri?.content === 'string' ? ri.content : undefined\n\n if (kind === 'edit') {\n // Edit tool: use old_string/new_string from rawInput for diff viewer\n const oldStr = typeof ri.old_string === 'string' ? ri.old_string : typeof ri.oldText === 'string' ? ri.oldText : undefined\n const newStr = typeof ri.new_string === 'string' ? ri.new_string : typeof ri.newText === 'string' ? ri.newText : undefined\n if (newStr) {\n info = { filePath, content: newStr, oldContent: oldStr }\n } else {\n // Fallback to riContent, then parsed content (e.g. ACP diff blocks)\n info = { filePath, content: riContent || parsed?.content, oldContent: parsed?.oldContent }\n }\n } else if (kind === 'write') {\n // Write tool: prefer rawInput.content (the actual file content) over tool result message\n info = { filePath, content: riContent || parsed?.content, oldContent: parsed?.oldContent }\n } else {\n // Read and other kinds: tool_update content IS the file content\n info = { filePath, content: parsed?.content || riContent, oldContent: parsed?.oldContent }\n }\n }\n }\n\n // 3. Try to extract from known ACP content patterns\n if (!info && content) {\n info = parseContent(content)\n }\n\n if (!info) return null\n\n // Infer file path from tool name if not in content\n if (!info.filePath) {\n const pathMatch = name.match(/(?:Read|Edit|Write|View)\\s+(.+)/i)\n if (pathMatch) info.filePath = pathMatch[1].trim()\n }\n\n if (!info.filePath || !info.content) return null\n return info as FileInfo\n}\n\n/**\n * Resolve toolResponse from agent-specific _meta namespaces.\n * Supports: _meta.claudeCode.toolResponse (Claude Code)\n * Add new agents here as they adopt the pattern.\n */\nfunction resolveToolResponse(meta: Record<string, unknown>): Record<string, unknown> | undefined {\n // Claude Code namespace\n const claudeCode = meta.claudeCode as Record<string, unknown> | undefined\n if (claudeCode?.toolResponse && typeof claudeCode.toolResponse === 'object') {\n return claudeCode.toolResponse as Record<string, unknown>\n }\n // Generic: _meta.toolResponse (for agents that put it directly)\n if (meta.toolResponse && typeof meta.toolResponse === 'object') {\n return meta.toolResponse as Record<string, unknown>\n }\n return undefined\n}\n\nfunction parseContent(content: unknown): Partial<FileInfo> | null {\n if (typeof content === 'string') {\n return { content }\n }\n\n if (Array.isArray(content)) {\n // Array of content blocks — try each\n for (const block of content) {\n const result = parseContent(block)\n if (result?.content || result?.filePath) return result\n }\n return null\n }\n\n if (typeof content === 'object' && content !== null) {\n const c = content as Record<string, unknown>\n\n // ACP diff block: { type: 'diff', path: '...', oldText: '...', newText: '...' }\n if (c.type === 'diff' && typeof c.path === 'string') {\n const newText = c.newText as string | null | undefined\n const oldText = c.oldText as string | null | undefined\n if (newText) {\n return {\n filePath: c.path as string,\n content: newText,\n oldContent: oldText ?? undefined,\n }\n }\n }\n\n // ACP content wrapper: { type: 'content', content: { type: 'text', text: '...' } }\n if (c.type === 'content' && c.content) {\n return parseContent(c.content)\n }\n\n // ACP text block: { type: 'text', text: '...' }\n if (c.type === 'text' && typeof c.text === 'string') {\n return { content: c.text, filePath: c.filePath as string | undefined }\n }\n\n // Direct fields\n if (typeof c.text === 'string') {\n return { content: c.text, filePath: c.filePath as string | undefined }\n }\n\n // Tool input with file path: { file_path: '...', content: '...' }\n if (typeof c.file_path === 'string' || typeof c.filePath === 'string' || typeof c.path === 'string') {\n const filePath = (c.file_path || c.filePath || c.path) as string\n const fileContent = (c.content || c.text || c.output || c.newText) as string | undefined\n if (typeof fileContent === 'string') {\n return {\n filePath,\n content: fileContent,\n oldContent: (c.old_content || c.oldText) as string | undefined,\n }\n }\n }\n\n // Nested input/output\n if (c.input) {\n const result = parseContent(c.input)\n if (result) return result\n }\n if (c.output) {\n const result = parseContent(c.output)\n if (result) return result\n }\n }\n\n return null\n}\n","import type { AgentEvent, OutgoingMessage } from \"./types.js\";\nimport type { TunnelServiceInterface } from \"./plugin/types.js\";\nimport { extractFileInfo } from \"./utils/extract-file-info.js\";\nimport { createChildLogger } from \"./utils/log.js\";\n\nconst log = createChildLogger({ module: \"message-transformer\" });\n\n/**\n * Compute actual line-level diff by stripping common prefix/suffix lines.\n * This avoids counting unchanged context lines as added/removed.\n */\nfunction computeLineDiff(oldStr: string, newStr: string): { added: number; removed: number } {\n const oldLines = oldStr ? oldStr.split(\"\\n\") : [];\n const newLines = newStr ? newStr.split(\"\\n\") : [];\n\n // Find common prefix\n let prefixLen = 0;\n const minLen = Math.min(oldLines.length, newLines.length);\n while (prefixLen < minLen && oldLines[prefixLen] === newLines[prefixLen]) {\n prefixLen++;\n }\n\n // Find common suffix (not overlapping with prefix)\n let suffixLen = 0;\n const maxSuffix = minLen - prefixLen;\n while (\n suffixLen < maxSuffix &&\n oldLines[oldLines.length - 1 - suffixLen] === newLines[newLines.length - 1 - suffixLen]\n ) {\n suffixLen++;\n }\n\n return {\n added: Math.max(0, newLines.length - prefixLen - suffixLen),\n removed: Math.max(0, oldLines.length - prefixLen - suffixLen),\n };\n}\n\nexport class MessageTransformer {\n tunnelService?: TunnelServiceInterface;\n /** Cache rawInput from tool_call so it's available in tool_update (which often lacks it) */\n private toolRawInputCache: Map<string, unknown> = new Map();\n /** Cache viewer links generated from intermediate updates so completion events carry them */\n private toolViewerCache: Map<string, { viewerLinks: Record<string, string>; viewerFilePath: string }> = new Map();\n\n constructor(tunnelService?: TunnelServiceInterface) {\n this.tunnelService = tunnelService;\n }\n\n transform(\n event: AgentEvent,\n sessionContext?: { id: string; workingDirectory: string },\n ): OutgoingMessage {\n switch (event.type) {\n case \"text\":\n return { type: \"text\", text: event.content };\n case \"thought\":\n return { type: \"thought\", text: event.content };\n case \"tool_call\": {\n // Cache rawInput (only if non-empty) for later tool_update events\n if (event.id && this.isNonEmptyInput(event.rawInput)) {\n this.toolRawInputCache.set(event.id, event.rawInput);\n }\n const meta = event.meta as Record<string, unknown> | undefined;\n const metadata: Record<string, unknown> = {\n id: event.id,\n name: event.name,\n kind: event.kind,\n status: event.status,\n content: event.content,\n locations: event.locations,\n rawInput: event.rawInput,\n displaySummary: meta?.displaySummary,\n displayTitle: meta?.displayTitle,\n displayKind: meta?.displayKind,\n };\n this.enrichWithViewerLinks(event, metadata, sessionContext);\n return { type: \"tool_call\", text: event.name, metadata };\n }\n case \"tool_update\": {\n // Update cache if this update carries non-empty rawInput (some agents send it on first update)\n if (event.id && this.isNonEmptyInput(event.rawInput)) {\n this.toolRawInputCache.set(event.id, event.rawInput);\n }\n // Merge cached rawInput when tool_update doesn't carry it\n const cachedRawInput = event.id ? this.toolRawInputCache.get(event.id) : undefined;\n const effectiveRawInput = this.isNonEmptyInput(event.rawInput) ? event.rawInput : cachedRawInput;\n // Clean up cache on terminal status\n if (event.id && (event.status === \"completed\" || event.status === \"done\" || event.status === \"failed\" || event.status === \"error\")) {\n this.toolRawInputCache.delete(event.id);\n }\n const meta = event.meta as Record<string, unknown> | undefined;\n const metadata: Record<string, unknown> = {\n id: event.id,\n name: event.name,\n kind: event.kind,\n status: event.status,\n content: event.content,\n rawInput: effectiveRawInput,\n displaySummary: meta?.displaySummary,\n displayTitle: meta?.displayTitle,\n displayKind: meta?.displayKind,\n };\n // Use a synthetic event with merged rawInput for enrichWithViewerLinks\n const enrichEvent = { ...event, rawInput: effectiveRawInput };\n this.enrichWithViewerLinks(enrichEvent as typeof event, metadata, sessionContext);\n // Viewer link caching: intermediate updates have raw content (preferred),\n // completion events have formatted content (with line numbers) — always prefer cached\n if (event.id) {\n const cached = this.toolViewerCache.get(event.id);\n if (cached) {\n // Cache already has links from intermediate update (raw content) — always use those\n metadata.viewerLinks = cached.viewerLinks;\n metadata.viewerFilePath = cached.viewerFilePath;\n } else if (metadata.viewerLinks) {\n // First time generating links — cache them\n this.toolViewerCache.set(event.id, {\n viewerLinks: metadata.viewerLinks as Record<string, string>,\n viewerFilePath: metadata.viewerFilePath as string,\n });\n }\n // Clean up viewer cache on terminal status\n if (event.status === \"completed\" || event.status === \"done\" || event.status === \"failed\" || event.status === \"error\") {\n this.toolViewerCache.delete(event.id);\n }\n }\n return { type: \"tool_update\", text: \"\", metadata };\n }\n case \"plan\":\n return {\n type: \"plan\",\n text: \"\",\n metadata: { entries: event.entries },\n };\n case \"usage\":\n return {\n type: \"usage\",\n text: \"\",\n metadata: {\n tokensUsed: event.tokensUsed,\n contextSize: event.contextSize,\n cost: event.cost?.amount,\n },\n };\n case \"session_end\":\n return { type: \"session_end\", text: `Done (${event.reason})` };\n case \"error\":\n return { type: \"error\", text: event.message };\n case \"system_message\":\n return { type: \"system_message\", text: event.message };\n case \"session_info_update\":\n return {\n type: \"system_message\",\n text: `Session updated: ${event.title ?? \"\"}`.trim(),\n metadata: { title: event.title, updatedAt: event.updatedAt },\n };\n case \"current_mode_update\":\n return {\n type: \"mode_change\",\n text: `Mode: ${event.modeId}`,\n metadata: { modeId: event.modeId },\n };\n case \"config_option_update\":\n return {\n type: \"config_update\",\n text: \"Config updated\",\n metadata: { options: event.options },\n };\n case \"model_update\":\n return {\n type: \"model_update\",\n text: `Model: ${event.modelId}`,\n metadata: { modelId: event.modelId },\n };\n case \"user_message_chunk\":\n return {\n type: \"user_replay\",\n text: event.content,\n };\n case \"resource_content\":\n return {\n type: \"resource\",\n text: event.name,\n metadata: { uri: event.uri, text: event.text, blob: event.blob, mimeType: event.mimeType },\n };\n case \"resource_link\":\n return {\n type: \"resource_link\",\n text: event.name,\n metadata: { uri: event.uri, mimeType: event.mimeType, title: event.title, description: event.description, size: event.size },\n };\n default:\n return { type: \"text\", text: \"\" };\n }\n }\n\n /** Check if rawInput is a non-empty object (not null, not {}) */\n private isNonEmptyInput(input: unknown): input is Record<string, unknown> {\n return input !== null && input !== undefined && typeof input === \"object\" && !Array.isArray(input) && Object.keys(input as object).length > 0;\n }\n\n private enrichWithViewerLinks(\n event: AgentEvent & { type: \"tool_call\" | \"tool_update\" },\n metadata: Record<string, unknown>,\n sessionContext?: { id: string; workingDirectory: string },\n ): void {\n // Compute diffStats from rawInput even without tunnelService\n const kind = \"kind\" in event ? event.kind : undefined;\n if (!metadata.diffStats && (kind === \"edit\" || kind === \"write\")) {\n const ri = event.rawInput as Record<string, unknown> | undefined;\n if (ri) {\n const oldStr = typeof ri.old_string === \"string\" ? ri.old_string : typeof ri.oldText === \"string\" ? ri.oldText : null;\n const newStr = typeof ri.new_string === \"string\" ? ri.new_string : typeof ri.newText === \"string\" ? ri.newText : typeof ri.content === \"string\" ? ri.content : null;\n if (oldStr !== null && newStr !== null) {\n const stats = computeLineDiff(oldStr, newStr);\n if (stats.added > 0 || stats.removed > 0) {\n metadata.diffStats = stats;\n }\n } else if (oldStr === null && newStr !== null && kind === \"write\") {\n // New file creation — no old content, count all new lines as added\n const added = newStr.split(\"\\n\").length;\n if (added > 0) metadata.diffStats = { added, removed: 0 };\n }\n }\n }\n\n if (!this.tunnelService || !sessionContext) {\n log.debug(\n { hasTunnel: !!this.tunnelService, hasCtx: !!sessionContext, kind },\n \"enrichWithViewerLinks: skipping (no tunnel or session context)\",\n );\n return;\n }\n\n const name = \"name\" in event ? event.name || \"\" : \"\";\n\n log.debug(\n { name, kind, status: event.status, hasContent: !!event.content, hasRawInput: !!event.rawInput },\n \"enrichWithViewerLinks: inspecting event\",\n );\n\n const fileInfo = extractFileInfo(\n name,\n kind,\n event.content,\n event.rawInput,\n event.meta,\n );\n if (!fileInfo) {\n log.debug(\n { name, kind, hasContent: !!event.content, hasRawInput: !!event.rawInput, hasMeta: !!event.meta },\n \"enrichWithViewerLinks: extractFileInfo returned null\",\n );\n return;\n }\n\n // Skip viewer link generation if the tunnel only has a localhost URL —\n // Telegram strips <a href=\"localhost:...\"> tags, rendering plain unclickable text.\n const publicUrl = this.tunnelService.getPublicUrl();\n if (publicUrl.startsWith(\"http://localhost\") || publicUrl.startsWith(\"http://127.0.0.1\")) {\n log.debug({ kind, filePath: fileInfo.filePath }, \"enrichWithViewerLinks: skipping (no public tunnel URL)\");\n return;\n }\n\n log.info(\n {\n name,\n kind,\n filePath: fileInfo.filePath,\n hasOldContent: !!fileInfo.oldContent,\n },\n \"enrichWithViewerLinks: extracted file info\",\n );\n\n const store = this.tunnelService.getStore();\n const viewerLinks: Record<string, string> = {};\n\n // For edits/writes with diff data (oldText + newText)\n if (fileInfo.oldContent) {\n const id = store.storeDiff(\n sessionContext.id,\n fileInfo.filePath,\n fileInfo.oldContent,\n fileInfo.content,\n sessionContext.workingDirectory,\n );\n if (id) viewerLinks.diff = this.tunnelService.diffUrl(id);\n\n // Compute diff stats from full file content only if not already set from rawInput\n if (!metadata.diffStats) {\n const stats = computeLineDiff(fileInfo.oldContent, fileInfo.content);\n if (stats.added > 0 || stats.removed > 0) {\n metadata.diffStats = stats;\n }\n }\n }\n\n // Always store as file view (new file creation or read)\n const id = store.storeFile(\n sessionContext.id,\n fileInfo.filePath,\n fileInfo.content,\n sessionContext.workingDirectory,\n );\n if (id) viewerLinks.file = this.tunnelService.fileUrl(id);\n\n if (Object.keys(viewerLinks).length > 0) {\n metadata.viewerLinks = viewerLinks;\n metadata.viewerFilePath = fileInfo.filePath;\n }\n }\n}\n","import type { AgentManager } from \"../agents/agent-manager.js\";\nimport { Session } from \"./session.js\";\nimport type { SessionStore } from \"./session-store.js\";\nimport type { EventBus } from \"../event-bus.js\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\n\nexport class SessionManager {\n private sessions: Map<string, Session> = new Map();\n private store: SessionStore | null;\n private eventBus?: EventBus;\n middlewareChain?: MiddlewareChain;\n\n setEventBus(eventBus: EventBus): void {\n this.eventBus = eventBus;\n }\n\n constructor(store: SessionStore | null = null) {\n this.store = store;\n }\n\n async createSession(\n channelId: string,\n agentName: string,\n workingDirectory: string,\n agentManager: AgentManager,\n ): Promise<Session> {\n const agentInstance = await agentManager.spawn(agentName, workingDirectory);\n const session = new Session({\n channelId,\n agentName,\n workingDirectory,\n agentInstance,\n });\n this.sessions.set(session.id, session);\n session.agentSessionId = session.agentInstance.sessionId;\n\n if (this.store) {\n await this.store.save({\n sessionId: session.id,\n agentSessionId: session.agentInstance.sessionId,\n agentName: session.agentName,\n workingDir: session.workingDirectory,\n channelId,\n status: session.status,\n createdAt: session.createdAt.toISOString(),\n lastActiveAt: new Date().toISOString(),\n name: session.name,\n dangerousMode: false,\n platform: {},\n });\n }\n\n return session;\n }\n\n getSession(sessionId: string): Session | undefined {\n return this.sessions.get(sessionId);\n }\n\n getSessionByThread(channelId: string, threadId: string): Session | undefined {\n for (const session of this.sessions.values()) {\n if (session.channelId === channelId && session.threadId === threadId) {\n return session;\n }\n }\n return undefined;\n }\n\n getSessionByAgentSessionId(agentSessionId: string): Session | undefined {\n for (const session of this.sessions.values()) {\n if (session.agentSessionId === agentSessionId) {\n return session;\n }\n }\n return undefined;\n }\n\n getRecordByAgentSessionId(\n agentSessionId: string,\n ): import(\"../types.js\").SessionRecord | undefined {\n return this.store?.findByAgentSessionId(agentSessionId);\n }\n\n getRecordByThread(\n channelId: string,\n threadId: string,\n ): import(\"../types.js\").SessionRecord | undefined {\n return this.store?.findByPlatform(\n channelId,\n (p) => String(p.topicId) === threadId || p.threadId === threadId,\n );\n }\n\n registerSession(session: Session): void {\n this.sessions.set(session.id, session);\n }\n\n async patchRecord(\n sessionId: string,\n patch: Partial<import(\"../types.js\").SessionRecord>,\n ): Promise<void> {\n if (!this.store) return;\n const record = this.store.get(sessionId);\n if (record) {\n await this.store.save({ ...record, ...patch });\n } else if (patch.sessionId) {\n // Initial save — treat patch as full record\n await this.store.save(patch as import(\"../types.js\").SessionRecord);\n }\n }\n\n getSessionRecord(\n sessionId: string,\n ): import(\"../types.js\").SessionRecord | undefined {\n return this.store?.get(sessionId);\n }\n\n async cancelSession(sessionId: string): Promise<void> {\n const session = this.sessions.get(sessionId);\n if (session) {\n try {\n await session.abortPrompt();\n } catch {\n // Agent may already be dead — continue with cleanup\n }\n session.markCancelled();\n this.sessions.delete(sessionId);\n }\n if (this.store) {\n const record = this.store.get(sessionId);\n if (record && record.status !== \"cancelled\") {\n await this.store.save({ ...record, status: \"cancelled\" });\n }\n }\n // Hook: session:afterDestroy — read-only, fire-and-forget\n if (this.middlewareChain) {\n this.middlewareChain.execute('session:afterDestroy', { sessionId }, async (p) => p).catch(() => {});\n }\n }\n\n listSessions(channelId?: string): Session[] {\n const all = Array.from(this.sessions.values());\n if (channelId) return all.filter((s) => s.channelId === channelId);\n return all;\n }\n\n listRecords(filter?: {\n statuses?: string[];\n }): import(\"../types.js\").SessionRecord[] {\n if (!this.store) return [];\n let records = this.store.list();\n if (filter?.statuses?.length) {\n records = records.filter((r) => filter.statuses!.includes(r.status));\n }\n return records;\n }\n\n async removeRecord(sessionId: string): Promise<void> {\n if (!this.store) return;\n await this.store.remove(sessionId);\n this.eventBus?.emit(\"session:deleted\", { sessionId });\n }\n\n /**\n * Graceful shutdown: persist session state without killing agent subprocesses.\n * Agent processes will exit naturally when the parent process terminates.\n */\n async shutdownAll(): Promise<void> {\n if (this.store) {\n for (const session of this.sessions.values()) {\n const record = this.store.get(session.id);\n if (record) {\n await this.store.save({ ...record, status: \"finished\" });\n }\n }\n }\n this.sessions.clear();\n }\n\n /**\n * Forcefully destroy all sessions (kill agent subprocesses).\n * Use only when sessions must be fully torn down (e.g. archive).\n */\n async destroyAll(): Promise<void> {\n if (this.store) {\n for (const session of this.sessions.values()) {\n const record = this.store.get(session.id);\n if (record) {\n await this.store.save({ ...record, status: \"finished\" });\n }\n }\n }\n const sessionIds = [...this.sessions.keys()];\n for (const session of this.sessions.values()) {\n await session.destroy();\n }\n this.sessions.clear();\n // Hook: session:afterDestroy — read-only, fire-and-forget\n if (this.middlewareChain) {\n for (const sessionId of sessionIds) {\n this.middlewareChain.execute('session:afterDestroy', { sessionId }, async (p) => p).catch(() => {});\n }\n }\n }\n}\n","import type { Session } from \"./session.js\";\nimport type { IChannelAdapter } from \"../channel.js\";\nimport type { MessageTransformer } from \"../message-transformer.js\";\nimport type { NotificationManager } from \"../../plugins/notifications/notification.js\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { AgentEvent, PermissionRequest, SessionStatus } from \"../types.js\";\nimport type { EventBus } from \"../event-bus.js\";\nimport type { FileServiceInterface } from \"../plugin/types.js\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\nimport type { DebugTracer } from \"../utils/debug-tracer.js\";\nimport { createChildLogger } from \"../utils/log.js\";\n\nconst log = createChildLogger({ module: \"session-bridge\" });\n\nexport interface BridgeDeps {\n messageTransformer: MessageTransformer;\n notificationManager: NotificationManager;\n sessionManager: SessionManager;\n eventBus?: EventBus;\n fileService?: FileServiceInterface;\n middlewareChain?: MiddlewareChain;\n}\n\nexport class SessionBridge {\n private connected = false;\n private agentEventHandler?: (event: AgentEvent) => void;\n private sessionEventHandler?: (event: AgentEvent) => void;\n private statusChangeHandler?: (\n from: SessionStatus,\n to: SessionStatus,\n ) => void;\n private namedHandler?: (name: string) => void;\n private promptCountHandler?: (count: number) => void;\n\n constructor(\n private session: Session,\n private adapter: IChannelAdapter,\n private deps: BridgeDeps,\n ) {}\n\n private get tracer(): DebugTracer | null {\n return this.session.agentInstance.debugTracer ?? null;\n }\n\n /** Send message to adapter, optionally running through message:outgoing middleware */\n private async sendMessage(sessionId: string, message: ReturnType<MessageTransformer[\"transform\"]>): Promise<void> {\n try {\n const mw = this.deps.middlewareChain;\n if (mw) {\n const result = await mw.execute('message:outgoing', { sessionId, message }, async (m) => m);\n this.tracer?.log(\"core\", { step: \"middleware:outgoing\", sessionId, hook: \"message:outgoing\", blocked: !result });\n if (!result) return;\n this.tracer?.log(\"core\", { step: \"dispatch\", sessionId, message: result.message });\n this.adapter.sendMessage(sessionId, result.message).catch((err) => {\n log.error({ err, sessionId }, \"Failed to send message to adapter\");\n });\n } else {\n this.tracer?.log(\"core\", { step: \"dispatch\", sessionId, message });\n this.adapter.sendMessage(sessionId, message).catch((err) => {\n log.error({ err, sessionId }, \"Failed to send message to adapter\");\n });\n }\n } catch (err) {\n log.error({ err, sessionId }, \"Error in sendMessage middleware\");\n }\n }\n\n connect(): void {\n if (this.connected) return;\n this.connected = true;\n\n this.wireAgentToSession();\n this.wireSessionToAdapter();\n this.wirePermissions();\n this.wireLifecycle();\n }\n\n disconnect(): void {\n if (!this.connected) return;\n this.connected = false;\n\n if (this.agentEventHandler) {\n this.session.agentInstance.off(\"agent_event\", this.agentEventHandler);\n }\n if (this.sessionEventHandler) {\n this.session.off(\"agent_event\", this.sessionEventHandler);\n }\n if (this.statusChangeHandler) {\n this.session.off(\"status_change\", this.statusChangeHandler);\n }\n if (this.namedHandler) {\n this.session.off(\"named\", this.namedHandler);\n }\n if (this.promptCountHandler) {\n this.session.off(\"prompt_count_changed\", this.promptCountHandler);\n }\n\n // Reset agent callbacks to no-op\n this.session.agentInstance.onPermissionRequest = async () => \"\";\n }\n\n private wireAgentToSession(): void {\n this.agentEventHandler = (event: AgentEvent) => {\n this.session.emit(\"agent_event\", event);\n };\n this.session.agentInstance.on(\"agent_event\", this.agentEventHandler);\n }\n\n private wireSessionToAdapter(): void {\n this.sessionEventHandler = (event: AgentEvent) => {\n this.tracer?.log(\"core\", { step: \"agent_event\", sessionId: this.session.id, event });\n // Hook: agent:beforeEvent — modifiable, can block\n const mw = this.deps.middlewareChain;\n if (mw) {\n mw.execute('agent:beforeEvent', { sessionId: this.session.id, event }, async (e) => e).then((result) => {\n this.tracer?.log(\"core\", { step: \"middleware:before\", sessionId: this.session.id, hook: \"agent:beforeEvent\", blocked: !result });\n if (!result) return; // blocked by middleware\n try {\n const transformedEvent = result.event;\n const outgoing = this.handleAgentEvent(transformedEvent);\n // Hook: agent:afterEvent — read-only, fire-and-forget\n mw.execute('agent:afterEvent', {\n sessionId: this.session.id,\n event: transformedEvent,\n outgoingMessage: outgoing ?? { type: 'text' as const, text: '' },\n }, async (e) => e).catch(() => {});\n } catch (err) {\n log.error({ err, sessionId: this.session.id }, \"Error handling agent event after middleware\");\n }\n }).catch(() => {\n // Middleware error — proceed with original event\n try {\n this.handleAgentEvent(event);\n } catch (err) {\n log.error({ err, sessionId: this.session.id }, \"Error handling agent event (middleware fallback)\");\n }\n });\n } else {\n try {\n this.handleAgentEvent(event);\n } catch (err) {\n log.error({ err, sessionId: this.session.id }, \"Error handling agent event\");\n }\n }\n };\n\n this.session.on(\"agent_event\", this.sessionEventHandler);\n }\n\n private handleAgentEvent(event: AgentEvent): import('../types.js').OutgoingMessage | undefined {\n const session = this.session;\n const ctx = {\n get id() {\n return session.id;\n },\n get workingDirectory() {\n return session.workingDirectory;\n },\n };\n\n let outgoing: import('../types.js').OutgoingMessage | undefined;\n\n switch (event.type) {\n case \"text\":\n case \"thought\":\n case \"tool_call\":\n case \"tool_update\":\n case \"plan\":\n case \"usage\":\n outgoing = this.deps.messageTransformer.transform(event, ctx);\n this.tracer?.log(\"core\", { step: \"transform\", sessionId: this.session.id, input: event, output: outgoing });\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"session_end\":\n this.session.finish(event.reason);\n this.adapter.cleanupSkillCommands?.(this.session.id);\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n this.deps.notificationManager.notify(this.session.channelId, {\n sessionId: this.session.id,\n sessionName: this.session.name,\n type: \"completed\",\n summary: `Session \"${this.session.name || this.session.id}\" completed\\n⏱ ${Math.round((Date.now() - this.session.createdAt.getTime()) / 60000)} min · 💬 ${this.session.promptCount} prompts`,\n });\n break;\n\n case \"error\":\n this.session.fail(event.message);\n this.adapter.cleanupSkillCommands?.(this.session.id);\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n this.deps.notificationManager.notify(this.session.channelId, {\n sessionId: this.session.id,\n sessionName: this.session.name,\n type: \"error\",\n summary: event.message,\n });\n break;\n\n case \"image_content\": {\n if (this.deps.fileService) {\n const fs = this.deps.fileService;\n const sid = this.session.id;\n const { data, mimeType } = event;\n const buffer = Buffer.from(data, \"base64\");\n const ext = fs.extensionFromMime(mimeType);\n fs.saveFile(sid, `agent-image${ext}`, buffer, mimeType)\n .then((att) => {\n this.sendMessage(sid, {\n type: \"attachment\",\n text: \"\",\n attachment: att,\n });\n })\n .catch((err) => log.error({ err }, \"Failed to save agent image\"));\n }\n break;\n }\n case \"audio_content\": {\n if (this.deps.fileService) {\n const fs = this.deps.fileService;\n const sid = this.session.id;\n const { data, mimeType } = event;\n const buffer = Buffer.from(data, \"base64\");\n const ext = fs.extensionFromMime(mimeType);\n fs.saveFile(sid, `agent-audio${ext}`, buffer, mimeType)\n .then((att) => {\n this.sendMessage(sid, {\n type: \"attachment\",\n text: \"\",\n attachment: att,\n });\n })\n .catch((err) => log.error({ err }, \"Failed to save agent audio\"));\n }\n break;\n }\n\n case \"commands_update\":\n log.debug({ commands: event.commands }, \"Commands available\");\n this.adapter.sendSkillCommands?.(this.session.id, event.commands);\n break;\n\n case \"system_message\":\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"session_info_update\":\n if (event.title) {\n this.session.setName(event.title);\n }\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"current_mode_update\":\n this.session.updateMode(event.modeId);\n this.persistAcpState();\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"config_option_update\":\n this.session.updateConfigOptions(event.options);\n this.persistAcpState();\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"model_update\":\n this.session.updateModel(event.modelId);\n this.persistAcpState();\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"user_message_chunk\":\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"resource_content\":\n case \"resource_link\":\n outgoing = this.deps.messageTransformer.transform(event);\n this.sendMessage(this.session.id, outgoing);\n break;\n\n case \"tts_strip\":\n this.adapter.stripTTSBlock?.(this.session.id);\n break;\n }\n\n this.deps.eventBus?.emit(\"agent:event\", {\n sessionId: this.session.id,\n event,\n });\n\n return outgoing;\n }\n\n /** Persist current ACP state (mode, config, model) to session store as cache */\n private persistAcpState(): void {\n this.deps.sessionManager.patchRecord(this.session.id, {\n acpState: this.session.toAcpStateSnapshot(),\n });\n }\n\n private wirePermissions(): void {\n const mw = this.deps.middlewareChain;\n\n this.session.agentInstance.onPermissionRequest = async (\n request: PermissionRequest,\n ) => {\n const startTime = Date.now();\n\n // Hook: permission:beforeRequest — modifiable, can block or autoResolve\n let permReq = request;\n if (mw) {\n const payload = { sessionId: this.session.id, request, autoResolve: undefined as string | undefined };\n const result = await mw.execute('permission:beforeRequest', payload, async (r) => r);\n if (!result) return \"\"; // blocked by middleware\n permReq = result.request;\n // I4: If middleware set autoResolve, skip UI and return directly\n if (result.autoResolve) {\n if (mw) {\n mw.execute('permission:afterResolve', {\n sessionId: this.session.id, requestId: permReq.id, decision: result.autoResolve, userId: 'middleware', durationMs: Date.now() - startTime,\n }, async (p) => p).catch(() => {});\n }\n return result.autoResolve;\n }\n }\n\n this.session.emit(\"permission_request\", permReq);\n this.deps.eventBus?.emit(\"permission:request\", {\n sessionId: this.session.id,\n permission: permReq,\n });\n\n // Auto-approve openacp CLI commands\n if (permReq.description.toLowerCase().includes(\"openacp\")) {\n const allowOption = permReq.options.find((o) => o.isAllow);\n if (allowOption) {\n log.info(\n { sessionId: this.session.id, requestId: permReq.id },\n \"Auto-approving openacp command\",\n );\n // Hook: permission:afterResolve — read-only, fire-and-forget\n if (mw) {\n mw.execute('permission:afterResolve', {\n sessionId: this.session.id, requestId: permReq.id, decision: allowOption.id, userId: 'system', durationMs: Date.now() - startTime,\n }, async (p) => p).catch(() => {});\n }\n return allowOption.id;\n }\n }\n\n // Dangerous mode: auto-approve all permissions\n if (this.session.dangerousMode) {\n const allowOption = permReq.options.find((o) => o.isAllow);\n if (allowOption) {\n log.info(\n { sessionId: this.session.id, requestId: permReq.id, optionId: allowOption.id },\n \"Dangerous mode: auto-approving permission\",\n );\n // Hook: permission:afterResolve — read-only, fire-and-forget\n if (mw) {\n mw.execute('permission:afterResolve', {\n sessionId: this.session.id, requestId: permReq.id, decision: allowOption.id, userId: 'system', durationMs: Date.now() - startTime,\n }, async (p) => p).catch(() => {});\n }\n return allowOption.id;\n }\n }\n\n // Set pending BEFORE sending UI to avoid race condition\n const promise = this.session.permissionGate.setPending(permReq);\n\n // Send permission UI to session topic\n await this.adapter.sendPermissionRequest(this.session.id, permReq);\n\n // Wait for user response — adapter resolves this promise\n const optionId = await promise;\n\n // Hook: permission:afterResolve — read-only, fire-and-forget\n if (mw) {\n mw.execute('permission:afterResolve', {\n sessionId: this.session.id, requestId: permReq.id, decision: optionId, userId: 'user', durationMs: Date.now() - startTime,\n }, async (p) => p).catch(() => {});\n }\n\n return optionId;\n };\n }\n\n private wireLifecycle(): void {\n // Persist status changes and auto-disconnect on terminal states\n this.statusChangeHandler = (from: SessionStatus, to: SessionStatus) => {\n this.deps.sessionManager.patchRecord(this.session.id, {\n status: to,\n lastActiveAt: new Date().toISOString(),\n });\n this.deps.eventBus?.emit(\"session:updated\", {\n sessionId: this.session.id,\n status: to,\n });\n\n // Auto-disconnect on terminal states (finished only — cancelled sessions can resume)\n if (to === \"finished\") {\n // Disconnect on next tick so current event handlers can complete\n queueMicrotask(() => this.disconnect());\n }\n };\n this.session.on(\"status_change\", this.statusChangeHandler);\n\n // Persist and relay name changes — only rename thread once per session.\n this.namedHandler = async (name: string) => {\n const record = this.deps.sessionManager.getSessionRecord(this.session.id);\n const alreadyNamed = !!record?.name;\n await this.deps.sessionManager.patchRecord(this.session.id, { name });\n this.deps.eventBus?.emit(\"session:updated\", {\n sessionId: this.session.id,\n name,\n });\n if (!alreadyNamed) {\n await this.adapter.renameSessionThread(this.session.id, name);\n }\n };\n this.session.on(\"named\", this.namedHandler);\n\n // Persist prompt count after each prompt for resume decisions\n this.promptCountHandler = (count: number) => {\n this.deps.sessionManager.patchRecord(this.session.id, { currentPromptCount: count });\n };\n this.session.on(\"prompt_count_changed\", this.promptCountHandler);\n }\n}\n","import type { AgentManager } from \"../agents/agent-manager.js\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { SpeechService } from \"../../plugins/speech/exports.js\";\nimport type { EventBus } from \"../event-bus.js\";\nimport type { NotificationManager } from \"../../plugins/notifications/notification.js\";\nimport type { TunnelService } from \"../../plugins/tunnel/tunnel-service.js\";\nimport type { AgentEvent } from \"../types.js\";\nimport type { MiddlewareChain } from \"../plugin/middleware-chain.js\";\nimport type { SessionStore } from \"./session-store.js\";\nimport type { IChannelAdapter } from \"../channel.js\";\nimport type { ConfigManager } from \"../config/config.js\";\nimport type { AgentCatalog } from \"../agents/agent-catalog.js\";\nimport type { ContextManager } from \"../../plugins/context/context-manager.js\";\nimport type { ContextQuery, ContextOptions, ContextResult } from \"../../plugins/context/context-provider.js\";\nimport { Session } from \"./session.js\";\nimport { createChildLogger } from \"../utils/log.js\";\n\nconst log = createChildLogger({ module: \"session-factory\" });\n\nexport interface SessionCreateParams {\n channelId: string;\n agentName: string;\n workingDirectory: string;\n resumeAgentSessionId?: string;\n existingSessionId?: string;\n initialName?: string;\n}\n\nexport interface SideEffectDeps {\n eventBus: EventBus;\n notificationManager: NotificationManager;\n tunnelService?: TunnelService;\n}\n\nexport class SessionFactory {\n middlewareChain?: MiddlewareChain;\n private resumeLocks: Map<string, Promise<Session | null>> = new Map();\n\n /** Injected by Core after construction — needed for lazy resume error feedback */\n adapters?: Map<string, IChannelAdapter>;\n /** Injected by Core after construction — needed for lazy resume store lookup */\n sessionStore?: SessionStore | null;\n /** Injected by Core — creates full session with thread + bridge + persist */\n createFullSession?: (params: SessionCreateParams & { threadId?: string; createThread?: boolean }) => Promise<Session>;\n /** Injected by Core — needed for resolving default agent and workspace */\n configManager?: ConfigManager;\n /** Injected by Core — needed for resolving agent definitions */\n agentCatalog?: AgentCatalog;\n /** Injected by Core — needed for context-aware session creation */\n getContextManager?: () => ContextManager | undefined;\n\n constructor(\n private agentManager: AgentManager,\n private sessionManager: SessionManager,\n private speechServiceAccessor: SpeechService | (() => SpeechService),\n private eventBus: EventBus,\n private instanceRoot?: string,\n ) {}\n\n private get speechService(): SpeechService {\n return typeof this.speechServiceAccessor === 'function'\n ? this.speechServiceAccessor()\n : this.speechServiceAccessor;\n }\n\n async create(params: SessionCreateParams): Promise<Session> {\n // Hook: session:beforeCreate — modifiable, can block\n let createParams = params;\n if (this.middlewareChain) {\n const payload = {\n agentName: params.agentName,\n workingDir: params.workingDirectory,\n userId: '', // userId is not part of SessionCreateParams — resolved upstream\n channelId: params.channelId,\n threadId: '', // threadId is assigned after session creation\n };\n const result = await this.middlewareChain.execute('session:beforeCreate', payload, async (p) => p);\n if (!result) throw new Error(\"Session creation blocked by middleware\");\n // Apply any middleware modifications back to create params\n createParams = {\n ...params,\n agentName: result.agentName,\n workingDirectory: result.workingDir,\n channelId: result.channelId,\n };\n }\n\n // 1. Spawn or resume agent\n let agentInstance;\n try {\n agentInstance = createParams.resumeAgentSessionId\n ? await this.agentManager.resume(\n createParams.agentName,\n createParams.workingDirectory,\n createParams.resumeAgentSessionId,\n )\n : await this.agentManager.spawn(\n createParams.agentName,\n createParams.workingDirectory,\n );\n } catch (err) {\n const message =\n err instanceof Error ? err.message : String(err);\n\n // Emit a structured guidance error so adapters (Telegram, SSE UI) can show clear next steps.\n // We intentionally avoid leaking internal paths — instead, we point users at the openacp wrapper.\n const guidanceLines = [\n `❌ Failed to start agent \"${createParams.agentName}\": ${message}`,\n \"\",\n \"Run the agent CLI once in a terminal for this OpenACP instance to complete login or setup.\",\n ];\n if (this.instanceRoot) {\n guidanceLines.push(\n \"\",\n \"Copy and run this command in your terminal:\",\n ` cd \"${this.instanceRoot}\" && openacp agents run ${createParams.agentName}`,\n );\n } else {\n guidanceLines.push(\n \"\",\n \"Copy and run this command in your terminal (same project where you started OpenACP):\",\n ` openacp agents run ${createParams.agentName}`,\n );\n }\n guidanceLines.push(\n \"\",\n \"After setup completes, retry creating the session here.\",\n );\n\n const guidance: AgentEvent = {\n type: \"system_message\",\n message: guidanceLines.join(\"\\n\"),\n };\n\n // Create a lightweight \"failed\" session context so UIs listening on the event bus\n // still receive a message in the right channel/thread.\n const failedSession = new Session({\n id: createParams.existingSessionId,\n channelId: createParams.channelId,\n agentName: createParams.agentName,\n workingDirectory: createParams.workingDirectory,\n // Dummy agent instance — will never be prompted\n agentInstance: {\n sessionId: \"\",\n prompt: async () => {},\n cancel: async () => {},\n destroy: async () => {},\n on: () => {},\n off: () => {},\n } as any,\n speechService: this.speechService,\n });\n this.sessionManager.registerSession(failedSession);\n failedSession.emit(\"agent_event\", guidance);\n this.eventBus.emit(\"agent:event\", {\n sessionId: failedSession.id,\n event: guidance,\n });\n\n // Re-throw so callers still see the failure\n throw err;\n }\n\n // Wire middleware chain to agent instance for FS/terminal hooks\n agentInstance.middlewareChain = this.middlewareChain;\n\n // 2. Create Session instance\n const session = new Session({\n id: createParams.existingSessionId,\n channelId: createParams.channelId,\n agentName: createParams.agentName,\n workingDirectory: createParams.workingDirectory,\n agentInstance,\n speechService: this.speechService,\n });\n session.agentSessionId = agentInstance.sessionId;\n session.middlewareChain = this.middlewareChain;\n if (createParams.initialName) {\n session.name = createParams.initialName;\n }\n\n // 3. Propagate ACP state from agent session response\n const resp = agentInstance.initialSessionResponse;\n if (resp) {\n session.setInitialAcpState({\n modes: (resp.modes as any) ?? null,\n configOptions: (resp.configOptions as any) ?? null,\n models: (resp.models as any) ?? null,\n agentCapabilities: agentInstance.agentCapabilities ?? null,\n });\n } else if (agentInstance.agentCapabilities) {\n session.setInitialAcpState({\n agentCapabilities: agentInstance.agentCapabilities,\n });\n }\n\n // 4. Register in SessionManager\n this.sessionManager.registerSession(session);\n this.eventBus.emit(\"session:created\", {\n sessionId: session.id,\n agent: session.agentName,\n status: session.status,\n });\n\n return session;\n }\n\n /**\n * Get active session by thread, or attempt lazy resume from store.\n * Used by adapter command handlers and handleMessage().\n */\n async getOrResume(channelId: string, threadId: string): Promise<Session | null> {\n const session = this.sessionManager.getSessionByThread(channelId, threadId);\n if (session) return session;\n return this.lazyResume(channelId, threadId);\n }\n\n private async lazyResume(channelId: string, threadId: string): Promise<Session | null> {\n const store = this.sessionStore;\n if (!store || !this.createFullSession) return null;\n\n const lockKey = `${channelId}:${threadId}`;\n\n // Check for existing resume in progress\n const existing = this.resumeLocks.get(lockKey);\n if (existing) return existing;\n\n const record = store.findByPlatform(\n channelId,\n (p) => String(p.topicId) === threadId,\n );\n if (!record) {\n log.debug({ threadId, channelId }, \"No session record found for thread\");\n return null;\n }\n\n // Don't resume errored or cancelled sessions\n if (record.status === \"error\" || record.status === \"cancelled\") {\n log.debug({ threadId, sessionId: record.sessionId, status: record.status }, \"Skipping resume of error session\");\n return null;\n }\n\n log.info({ threadId, sessionId: record.sessionId, status: record.status }, \"Lazy resume: found record, attempting resume\");\n\n const resumePromise = (async (): Promise<Session | null> => {\n try {\n const session = await this.createFullSession!({\n channelId: record.channelId,\n agentName: record.agentName,\n workingDirectory: record.workingDir,\n resumeAgentSessionId: record.agentSessionId,\n existingSessionId: record.sessionId,\n initialName: record.name,\n threadId,\n });\n session.activate();\n session.dangerousMode = record.dangerousMode ?? false;\n if (record.firstAgent) session.firstAgent = record.firstAgent;\n if (record.agentSwitchHistory) session.agentSwitchHistory = record.agentSwitchHistory;\n if (record.currentPromptCount != null) session.promptCount = record.currentPromptCount;\n\n // Hydrate cached ACP state (will be overridden by agent events on resume)\n if (record.acpState) {\n const s = record.acpState;\n session.setInitialAcpState({\n modes: s.currentMode && s.availableModes\n ? { currentModeId: s.currentMode, availableModes: s.availableModes }\n : null,\n configOptions: s.configOptions ?? null,\n models: s.currentModel && s.availableModels\n ? { currentModelId: s.currentModel, availableModels: s.availableModels }\n : null,\n agentCapabilities: s.agentCapabilities ?? null,\n });\n }\n\n log.info({ sessionId: session.id, threadId }, \"Lazy resume successful\");\n return session;\n } catch (err) {\n log.error({ err, record }, \"Lazy resume failed\");\n // Send error feedback to user\n const adapter = this.adapters?.get(channelId);\n if (adapter) {\n try {\n await adapter.sendMessage(threadId, {\n type: \"error\",\n text: `⚠️ Failed to resume session: ${err instanceof Error ? err.message : String(err)}`,\n });\n } catch { /* best effort */ }\n }\n return null;\n } finally {\n this.resumeLocks.delete(lockKey);\n }\n })();\n\n this.resumeLocks.set(lockKey, resumePromise);\n return resumePromise;\n }\n\n async handleNewSession(\n channelId: string,\n agentName?: string,\n workspacePath?: string,\n options?: { createThread?: boolean },\n ): Promise<Session> {\n if (!this.configManager || !this.agentCatalog || !this.createFullSession) {\n throw new Error(\"SessionFactory not fully initialized\");\n }\n const config = this.configManager.get();\n const resolvedAgent = agentName || config.defaultAgent;\n log.info({ channelId, agentName: resolvedAgent }, \"New session request\");\n const agentDef = this.agentCatalog.resolve(resolvedAgent);\n const resolvedWorkspace = this.configManager.resolveWorkspace(\n workspacePath || agentDef?.workingDirectory,\n );\n\n return this.createFullSession({\n channelId,\n agentName: resolvedAgent,\n workingDirectory: resolvedWorkspace,\n ...options,\n });\n }\n\n /** NOTE: handleNewChat is currently dead code — never called outside core.ts itself.\n * Moving it anyway for completeness; can be removed in a future cleanup. */\n async handleNewChat(\n channelId: string,\n currentThreadId: string,\n ): Promise<Session | null> {\n const currentSession = this.sessionManager.getSessionByThread(\n channelId,\n currentThreadId,\n );\n\n if (currentSession) {\n return this.handleNewSession(\n channelId,\n currentSession.agentName,\n currentSession.workingDirectory,\n );\n }\n\n // Fallback: look up from store\n const record = this.sessionManager.getRecordByThread(\n channelId,\n currentThreadId,\n );\n if (!record || record.status === \"cancelled\" || record.status === \"error\")\n return null;\n\n return this.handleNewSession(\n channelId,\n record.agentName,\n record.workingDir,\n );\n }\n\n async createSessionWithContext(params: {\n channelId: string;\n agentName: string;\n workingDirectory: string;\n contextQuery: ContextQuery;\n contextOptions?: ContextOptions;\n createThread?: boolean;\n }): Promise<{ session: Session; contextResult: ContextResult | null }> {\n if (!this.createFullSession) throw new Error(\"SessionFactory not fully initialized\");\n\n let contextResult: ContextResult | null = null;\n const contextManager = this.getContextManager?.();\n if (contextManager) {\n try {\n contextResult = await contextManager.buildContext(\n params.contextQuery,\n params.contextOptions,\n );\n } catch (err) {\n log.warn({ err }, \"Context building failed, proceeding without context\");\n }\n }\n\n const session = await this.createFullSession({\n channelId: params.channelId,\n agentName: params.agentName,\n workingDirectory: params.workingDirectory,\n createThread: params.createThread,\n });\n\n if (contextResult) {\n session.setContext(contextResult.markdown);\n }\n\n return { session, contextResult };\n }\n\n wireSideEffects(session: Session, deps: SideEffectDeps): void {\n // Wire usage tracking via event bus (consumed by usage plugin)\n session.on(\"agent_event\", (event: AgentEvent) => {\n if (event.type !== \"usage\") return;\n deps.eventBus.emit(\"usage:recorded\", {\n sessionId: session.id,\n agentName: session.agentName,\n timestamp: new Date().toISOString(),\n tokensUsed: event.tokensUsed ?? 0,\n contextSize: event.contextSize ?? 0,\n cost: event.cost,\n });\n });\n\n // Clean up user tunnels when session ends\n session.on(\"status_change\", (_from, to) => {\n if ((to === \"finished\" || to === \"cancelled\") && deps.tunnelService) {\n deps.tunnelService\n .stopBySession(session.id)\n .then((stopped) => {\n for (const entry of stopped) {\n deps.notificationManager\n .notifyAll({\n sessionId: session.id,\n sessionName: session.name,\n type: \"completed\",\n summary: `Tunnel stopped: port ${entry.port}${entry.label ? ` (${entry.label})` : \"\"} — session ended`,\n })\n .catch(() => {});\n }\n })\n .catch(() => {});\n }\n });\n }\n}\n","import path from \"node:path\";\nimport os from \"node:os\";\nimport { ConfigManager } from \"./config/config.js\";\nimport { AgentManager } from \"./agents/agent-manager.js\";\nimport { SessionManager } from \"./sessions/session-manager.js\";\nimport { SessionBridge } from \"./sessions/session-bridge.js\";\nimport type { NotificationManager } from \"../plugins/notifications/notification.js\";\nimport type { IChannelAdapter } from \"./channel.js\";\nimport { Session } from \"./sessions/session.js\";\nimport { MessageTransformer } from \"./message-transformer.js\";\nimport type { FileServiceInterface } from \"./plugin/types.js\";\nimport { JsonFileSessionStore, type SessionStore } from \"./sessions/session-store.js\";\nimport type { SecurityGuard } from \"../plugins/security/security-guard.js\";\nimport { SessionFactory } from \"./sessions/session-factory.js\";\nimport type { IncomingMessage } from \"./types.js\";\nimport type { TunnelService } from \"../plugins/tunnel/tunnel-service.js\";\nimport { getAgentCapabilities } from \"./agents/agent-registry.js\";\nimport { AgentSwitchHandler } from \"./agent-switch-handler.js\";\nimport { AgentCatalog } from \"./agents/agent-catalog.js\";\nimport { AgentStore } from \"./agents/agent-store.js\";\nimport { EventBus } from \"./event-bus.js\";\nimport { LifecycleManager } from \"./plugin/lifecycle-manager.js\";\nimport { ServiceRegistry } from \"./plugin/service-registry.js\";\nimport { MiddlewareChain } from \"./plugin/middleware-chain.js\";\nimport { ErrorTracker } from \"./plugin/error-tracker.js\";\nimport { createChildLogger } from \"./utils/log.js\";\nimport type { SpeechService } from \"../plugins/speech/exports.js\";\nimport type { ContextManager } from \"../plugins/context/context-manager.js\";\nimport type { InstanceContext } from \"./instance/instance-context.js\";\nconst log = createChildLogger({ module: \"core\" });\n\nexport class OpenACPCore {\n configManager: ConfigManager;\n agentCatalog: AgentCatalog;\n agentManager: AgentManager;\n sessionManager: SessionManager;\n messageTransformer: MessageTransformer;\n adapters: Map<string, IChannelAdapter> = new Map();\n /** sessionId → SessionBridge — tracks active bridges for disconnect/reconnect during agent switch */\n private bridges: Map<string, SessionBridge> = new Map();\n /** Set by main.ts — triggers graceful shutdown with restart exit code */\n requestRestart: (() => Promise<void>) | null = null;\n private _tunnelService?: TunnelService;\n private sessionStore: SessionStore | null = null;\n eventBus: EventBus;\n sessionFactory: SessionFactory;\n readonly lifecycleManager: LifecycleManager;\n private agentSwitchHandler: AgentSwitchHandler;\n public readonly instanceContext?: InstanceContext;\n\n // --- Lazy getters: resolve from ServiceRegistry (populated by plugins during boot) ---\n\n private getService<T>(name: string): T {\n const svc = this.lifecycleManager.serviceRegistry.get<T>(name);\n if (!svc) throw new Error(`Service '${name}' not registered — is the ${name} plugin loaded?`);\n return svc;\n }\n\n get securityGuard(): SecurityGuard {\n return this.getService<SecurityGuard>('security');\n }\n\n get notificationManager(): NotificationManager {\n return this.getService<NotificationManager>('notifications');\n }\n\n get fileService(): FileServiceInterface {\n return this.getService<FileServiceInterface>('file-service');\n }\n\n get speechService(): SpeechService {\n return this.getService<SpeechService>('speech');\n }\n\n get contextManager(): ContextManager {\n return this.getService<ContextManager>('context');\n }\n\n constructor(configManager: ConfigManager, ctx?: InstanceContext) {\n this.configManager = configManager;\n this.instanceContext = ctx;\n const config = configManager.get();\n this.agentCatalog = new AgentCatalog(\n ctx ? new AgentStore(ctx.paths.agents) : undefined,\n ctx?.paths.registryCache,\n ctx?.paths.agentsDir,\n );\n this.agentCatalog.load();\n this.agentManager = new AgentManager(this.agentCatalog);\n const storePath = ctx?.paths.sessions ?? path.join(os.homedir(), \".openacp\", \"sessions.json\");\n this.sessionStore = new JsonFileSessionStore(\n storePath,\n config.sessionStore.ttlDays,\n );\n this.sessionManager = new SessionManager(this.sessionStore);\n\n this.messageTransformer = new MessageTransformer();\n this.eventBus = new EventBus();\n this.sessionManager.setEventBus(this.eventBus);\n\n // SessionFactory uses a lazy accessor for speechService (resolved from ServiceRegistry after plugin boot)\n this.sessionFactory = new SessionFactory(\n this.agentManager,\n this.sessionManager,\n () => this.speechService,\n this.eventBus,\n ctx?.root,\n );\n\n // Initialize plugin lifecycle manager (before setting middlewareChain on factory)\n this.lifecycleManager = new LifecycleManager({\n serviceRegistry: new ServiceRegistry(),\n middlewareChain: new MiddlewareChain(),\n errorTracker: new ErrorTracker(),\n eventBus: this.eventBus as any,\n sessions: this.sessionManager,\n config: this.configManager,\n core: this,\n storagePath: ctx?.paths.pluginsData ?? path.join(os.homedir(), \".openacp\", \"plugins\", \"data\"),\n instanceRoot: ctx?.root,\n log: createChildLogger({ module: \"plugin\" }),\n });\n\n // Wire middleware chain to session factory and session manager\n this.sessionFactory.middlewareChain = this.lifecycleManager.middlewareChain;\n this.sessionManager.middlewareChain = this.lifecycleManager.middlewareChain;\n\n // Wire lazy resume dependencies\n this.sessionFactory.sessionStore = this.sessionStore;\n this.sessionFactory.adapters = this.adapters;\n this.sessionFactory.createFullSession = (params) => this.createSession(params);\n this.sessionFactory.configManager = this.configManager;\n this.sessionFactory.agentCatalog = this.agentCatalog;\n this.sessionFactory.getContextManager = () => this.lifecycleManager.serviceRegistry.get<ContextManager>('context');\n\n this.agentSwitchHandler = new AgentSwitchHandler({\n sessionManager: this.sessionManager,\n agentManager: this.agentManager,\n configManager: this.configManager,\n eventBus: this.eventBus,\n adapters: this.adapters,\n bridges: this.bridges,\n createBridge: (session, adapter) => this.createBridge(session, adapter),\n getMiddlewareChain: () => this.lifecycleManager?.middlewareChain,\n getService: <T>(name: string) => this.lifecycleManager.serviceRegistry.get<T>(name),\n });\n\n // Hot-reload: handle config changes that need side effects\n this.configManager.on(\n \"config:changed\",\n async ({ path: configPath, value }: { path: string; value: unknown }) => {\n if (configPath === \"logging.level\" && typeof value === \"string\") {\n const { setLogLevel } = await import(\"./utils/log.js\");\n setLogLevel(value);\n log.info({ level: value }, \"Log level changed at runtime\");\n }\n if (configPath.startsWith(\"speech.\")) {\n const speechSvc = this.speechService;\n if (speechSvc) {\n const newConfig = this.configManager.get();\n const newSpeechConfig = newConfig.speech ?? {\n stt: { provider: null, providers: {} },\n tts: { provider: null, providers: {} },\n };\n speechSvc.refreshProviders(newSpeechConfig);\n log.info(\"Speech service config updated at runtime\");\n }\n }\n },\n );\n }\n\n get tunnelService(): TunnelService | undefined {\n return this._tunnelService;\n }\n\n set tunnelService(service: TunnelService | undefined) {\n this._tunnelService = service;\n this.messageTransformer.tunnelService = service;\n }\n\n registerAdapter(name: string, adapter: IChannelAdapter): void {\n this.adapters.set(name, adapter);\n }\n\n async start(): Promise<void> {\n this.agentCatalog.refreshRegistryIfStale().catch((err) => {\n log.warn({ err }, \"Background registry refresh failed\");\n });\n const failures: Array<{ name: string; error: unknown }> = [];\n for (const [name, adapter] of this.adapters.entries()) {\n try {\n await adapter.start();\n } catch (err) {\n log.error({ err, adapter: name }, `Adapter \"${name}\" failed to start`);\n failures.push({ name, error: err });\n }\n }\n if (failures.length > 0 && failures.length === this.adapters.size) {\n throw new Error(\n `All adapters failed to start: ${failures.map((f) => f.name).join(\", \")}`,\n );\n }\n }\n\n async stop(): Promise<void> {\n // 1. Notify users (best effort — service may not be available)\n try {\n const nm = this.lifecycleManager.serviceRegistry.get<NotificationManager>('notifications');\n if (nm) {\n await nm.notifyAll({\n sessionId: \"system\",\n type: \"error\",\n summary: \"OpenACP is shutting down\",\n });\n }\n } catch {\n /* best effort */\n }\n\n // 2. Persist session state (don't kill agents — they exit with parent)\n await this.sessionManager.shutdownAll();\n\n // 3. Stop adapters\n for (const adapter of this.adapters.values()) {\n await adapter.stop();\n }\n }\n\n // --- Archive ---\n\n async archiveSession(sessionId: string): Promise<{ ok: true } | { ok: false; error: string }> {\n const session = this.sessionManager.getSession(sessionId);\n if (!session) return { ok: false, error: \"Session not found (must be in memory)\" };\n\n // Must be active (not initializing or finished)\n if (session.status !== \"active\" && session.status !== \"cancelled\" && session.status !== \"error\") {\n return { ok: false, error: `Cannot archive session in '${session.status}' state` };\n }\n\n const adapter = this.adapters.get(session.channelId);\n if (!adapter) return { ok: false, error: \"Adapter not found for session\" };\n if (!adapter.archiveSessionTopic) return { ok: false, error: \"Adapter does not support topic archiving\" };\n\n try {\n // archiveSessionTopic handles: cleanup trackers → delete topic\n await adapter.archiveSessionTopic(session.id);\n\n // Cancel session — stops agent, removes from active sessions, marks record as cancelled\n await this.sessionManager.cancelSession(sessionId);\n\n return { ok: true };\n } catch (err) {\n // Clear archiving flag on error\n session.archiving = false;\n return { ok: false, error: (err as Error).message };\n }\n }\n\n // --- Message Routing ---\n\n async handleMessage(message: IncomingMessage): Promise<void> {\n log.debug(\n {\n channelId: message.channelId,\n threadId: message.threadId,\n userId: message.userId,\n },\n \"Incoming message\",\n );\n\n // Hook: message:incoming — modifiable, can block\n if (this.lifecycleManager?.middlewareChain) {\n const result = await this.lifecycleManager.middlewareChain.execute(\n 'message:incoming',\n message,\n async (msg) => msg,\n );\n if (!result) return; // blocked by middleware\n message = result;\n }\n\n // Security: check user access and session limits\n const access = this.securityGuard.checkAccess(message);\n if (!access.allowed) {\n log.warn({ userId: message.userId, reason: access.reason }, \"Access denied\");\n if (access.reason.includes(\"Session limit\")) {\n const adapter = this.adapters.get(message.channelId);\n if (adapter) {\n await adapter.sendMessage(message.threadId, {\n type: \"error\",\n text: `⚠️ ${access.reason}. Please cancel existing sessions with /cancel before starting new ones.`,\n });\n }\n }\n return;\n }\n\n // Find session by thread or lazy resume\n let session = await this.sessionFactory.getOrResume(message.channelId, message.threadId);\n\n if (!session) {\n log.warn(\n { channelId: message.channelId, threadId: message.threadId },\n \"No session found for thread (in-memory miss + lazy resume returned null)\",\n );\n return;\n }\n\n // Update activity timestamp\n this.sessionManager.patchRecord(session.id, {\n lastActiveAt: new Date().toISOString(),\n });\n\n // Forward to session\n await session.enqueuePrompt(message.text, message.attachments);\n }\n\n // --- Unified Session Creation Pipeline ---\n\n async createSession(params: {\n channelId: string;\n agentName: string;\n workingDirectory: string;\n resumeAgentSessionId?: string;\n existingSessionId?: string;\n createThread?: boolean;\n initialName?: string;\n threadId?: string;\n }): Promise<Session> {\n // 1-3. Spawn/resume agent, create Session, register in SessionManager\n const session = await this.sessionFactory.create(params);\n\n // Set threadId early so agent events during bridge.connect() can find the thread\n if (params.threadId) {\n session.threadId = params.threadId;\n }\n\n // 4. Create thread if needed\n const adapter = this.adapters.get(params.channelId);\n if (params.createThread && adapter) {\n const threadId = await adapter.createSessionThread(\n session.id,\n params.initialName ?? `🔄 ${params.agentName} — New Session`,\n );\n session.threadId = threadId;\n }\n\n // 5. Persist initial record BEFORE bridge.connect() so that:\n // - Lazy resume can find the record by threadId\n // - sendSkillCommands/renameSessionThread have threadId available\n const existingRecord = this.sessionStore?.get(session.id);\n const platform: Record<string, unknown> = {\n ...(existingRecord?.platform ?? {}),\n };\n if (session.threadId) {\n if (params.channelId === \"telegram\") {\n platform.topicId = Number(session.threadId);\n } else {\n platform.threadId = session.threadId;\n }\n }\n await this.sessionManager.patchRecord(session.id, {\n sessionId: session.id,\n agentSessionId: session.agentSessionId,\n agentName: params.agentName,\n workingDir: params.workingDirectory,\n channelId: params.channelId,\n status: session.status,\n createdAt: session.createdAt.toISOString(),\n lastActiveAt: new Date().toISOString(),\n name: session.name,\n platform,\n firstAgent: session.firstAgent,\n currentPromptCount: session.promptCount,\n agentSwitchHistory: session.agentSwitchHistory,\n // Cache ACP state for display before agent reconnects on lazy resume\n acpState: session.toAcpStateSnapshot(),\n });\n\n // 6. Connect SessionBridge — agent events can now fire with threadId available\n if (adapter) {\n const bridge = this.createBridge(session, adapter);\n bridge.connect();\n // Flush any skill commands that arrived before threadId was set (safety net)\n adapter.flushPendingSkillCommands?.(session.id).catch((err) => {\n log.warn({ err, sessionId: session.id }, \"Failed to flush pending skill commands\");\n });\n }\n\n // 6b. Wire usage tracking and tunnel cleanup\n this.sessionFactory.wireSideEffects(session, {\n eventBus: this.eventBus,\n notificationManager: this.notificationManager,\n tunnelService: this._tunnelService,\n });\n\n log.info(\n { sessionId: session.id, agentName: params.agentName },\n \"Session created via pipeline\",\n );\n return session;\n }\n\n async handleNewSession(\n channelId: string,\n agentName?: string,\n workspacePath?: string,\n options?: { createThread?: boolean },\n ): Promise<Session> {\n return this.sessionFactory.handleNewSession(channelId, agentName, workspacePath, options);\n }\n\n async adoptSession(\n agentName: string,\n agentSessionId: string,\n cwd: string,\n channelId?: string,\n ): Promise<\n | {\n ok: true;\n sessionId: string;\n threadId: string;\n status: \"adopted\" | \"existing\";\n }\n | { ok: false; error: string; message: string }\n > {\n // 1. Validate agent supports resume\n const caps = getAgentCapabilities(agentName);\n if (!caps.supportsResume) {\n return {\n ok: false,\n error: \"agent_not_supported\",\n message: `Agent '${agentName}' does not support session resume`,\n };\n }\n\n const agentDef = this.agentManager.getAgent(agentName);\n if (!agentDef) {\n return {\n ok: false,\n error: \"agent_not_supported\",\n message: `Agent '${agentName}' not found`,\n };\n }\n\n // 2. Validate cwd\n const { existsSync } = await import(\"node:fs\");\n if (!existsSync(cwd)) {\n return {\n ok: false,\n error: \"invalid_cwd\",\n message: `Directory does not exist: ${cwd}`,\n };\n }\n\n // 3. Check session limit\n const maxSessions = this.configManager.get().security.maxConcurrentSessions;\n if (this.sessionManager.listSessions().length >= maxSessions) {\n return {\n ok: false,\n error: \"session_limit\",\n message: \"Maximum concurrent sessions reached\",\n };\n }\n\n // 4. Check if session already exists on the same channel\n const existingRecord =\n this.sessionManager.getRecordByAgentSessionId(agentSessionId);\n if (existingRecord) {\n const sameChannel = !channelId || existingRecord.channelId === channelId;\n const platform = existingRecord.platform as { topicId?: number; threadId?: string } | undefined;\n const existingThreadId = platform?.topicId ? String(platform.topicId) : platform?.threadId;\n if (existingThreadId && sameChannel) {\n const adapter = this.adapters.get(existingRecord.channelId) ?? this.adapters.values().next().value;\n if (adapter) {\n try {\n await adapter.sendMessage(existingRecord.sessionId, {\n type: \"text\",\n text: \"Session resumed from CLI.\",\n });\n } catch { /* Topic/thread may be deleted */ }\n }\n return {\n ok: true,\n sessionId: existingRecord.sessionId,\n threadId: existingThreadId,\n status: \"existing\",\n };\n }\n }\n\n // 5. Find adapter (explicit channel or default first)\n let adapterChannelId: string;\n if (channelId) {\n if (!this.adapters.has(channelId)) {\n const available = Array.from(this.adapters.keys()).join(\", \") || \"none\";\n return { ok: false, error: \"adapter_not_found\", message: `Adapter '${channelId}' is not connected. Available: ${available}` };\n }\n adapterChannelId = channelId;\n } else {\n const firstEntry = this.adapters.entries().next().value;\n if (!firstEntry) {\n return { ok: false, error: \"no_adapter\", message: \"No channel adapter registered\" };\n }\n adapterChannelId = firstEntry[0];\n }\n\n // 6. Create session via unified pipeline\n let session: Session;\n try {\n session = await this.createSession({\n channelId: adapterChannelId,\n agentName,\n workingDirectory: cwd,\n resumeAgentSessionId: agentSessionId,\n createThread: true,\n initialName: \"Adopted session\",\n });\n } catch (err) {\n return {\n ok: false,\n error: \"resume_failed\",\n message: `Failed to resume session: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // 7. Update store with adopt-specific fields\n const adoptPlatform: Record<string, unknown> = {};\n if (adapterChannelId === 'telegram') {\n adoptPlatform.topicId = Number(session.threadId);\n } else {\n adoptPlatform.threadId = session.threadId;\n }\n await this.sessionManager.patchRecord(session.id, {\n originalAgentSessionId: agentSessionId,\n platform: adoptPlatform,\n });\n\n return {\n ok: true,\n sessionId: session.id,\n threadId: session.threadId,\n status: \"adopted\",\n };\n }\n\n async handleNewChat(channelId: string, currentThreadId: string): Promise<Session | null> {\n return this.sessionFactory.handleNewChat(channelId, currentThreadId);\n }\n\n async createSessionWithContext(params: {\n channelId: string;\n agentName: string;\n workingDirectory: string;\n contextQuery: import(\"../plugins/context/context-provider.js\").ContextQuery;\n contextOptions?: import(\"../plugins/context/context-provider.js\").ContextOptions;\n createThread?: boolean;\n }): Promise<{ session: Session; contextResult: import(\"../plugins/context/context-provider.js\").ContextResult | null }> {\n return this.sessionFactory.createSessionWithContext(params);\n }\n\n // --- Agent Switch ---\n\n async switchSessionAgent(sessionId: string, toAgent: string): Promise<{ resumed: boolean }> {\n return this.agentSwitchHandler.switch(sessionId, toAgent);\n }\n\n async getOrResumeSession(channelId: string, threadId: string): Promise<Session | null> {\n return this.sessionFactory.getOrResume(channelId, threadId);\n }\n\n // --- Event Wiring ---\n\n /** Create a SessionBridge for the given session and adapter */\n createBridge(session: Session, adapter: IChannelAdapter): SessionBridge {\n const bridge = new SessionBridge(session, adapter, {\n messageTransformer: this.messageTransformer,\n notificationManager: this.notificationManager,\n sessionManager: this.sessionManager,\n eventBus: this.eventBus,\n fileService: this.fileService,\n middlewareChain: this.lifecycleManager?.middlewareChain,\n });\n this.bridges.set(session.id, bridge);\n return bridge;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { SessionRecord } from \"../types.js\";\nimport { createChildLogger } from \"../utils/log.js\";\n\nconst log = createChildLogger({ module: \"session-store\" });\n\nexport interface SessionStore {\n save(record: SessionRecord): Promise<void>;\n get(sessionId: string): SessionRecord | undefined;\n findByPlatform(\n channelId: string,\n predicate: (platform: Record<string, unknown>) => boolean,\n ): SessionRecord | undefined;\n findByAgentSessionId(agentSessionId: string): SessionRecord | undefined;\n list(channelId?: string): SessionRecord[];\n remove(sessionId: string): Promise<void>;\n}\n\ninterface StoreFile {\n version: number;\n sessions: Record<string, SessionRecord>;\n}\n\nconst DEBOUNCE_MS = 2000;\n\nexport class JsonFileSessionStore implements SessionStore {\n private records: Map<string, SessionRecord> = new Map();\n private filePath: string;\n private ttlDays: number;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private cleanupInterval: ReturnType<typeof setInterval> | null = null;\n private flushHandler: (() => void) | null = null;\n\n constructor(filePath: string, ttlDays: number) {\n this.filePath = filePath;\n this.ttlDays = ttlDays;\n this.load();\n this.cleanup();\n\n // Daily cleanup for long-running instances\n this.cleanupInterval = setInterval(\n () => this.cleanup(),\n 24 * 60 * 60 * 1000,\n );\n\n // Force flush on shutdown\n this.flushHandler = () => this.flushSync();\n process.on(\"SIGTERM\", this.flushHandler);\n process.on(\"SIGINT\", this.flushHandler);\n process.on(\"exit\", this.flushHandler);\n }\n\n async save(record: SessionRecord): Promise<void> {\n this.records.set(record.sessionId, { ...record });\n this.scheduleDiskWrite();\n }\n\n get(sessionId: string): SessionRecord | undefined {\n return this.records.get(sessionId);\n }\n\n findByPlatform(\n channelId: string,\n predicate: (platform: Record<string, unknown>) => boolean,\n ): SessionRecord | undefined {\n for (const record of this.records.values()) {\n if (record.channelId === channelId && predicate(record.platform)) {\n return record;\n }\n }\n return undefined;\n }\n\n findByAgentSessionId(agentSessionId: string): SessionRecord | undefined {\n for (const record of this.records.values()) {\n if (\n record.agentSessionId === agentSessionId ||\n record.originalAgentSessionId === agentSessionId\n ) {\n return record;\n }\n // Also search switch history\n if (record.agentSwitchHistory?.some((e) => e.agentSessionId === agentSessionId)) {\n return record;\n }\n }\n return undefined;\n }\n\n list(channelId?: string): SessionRecord[] {\n const all = [...this.records.values()];\n if (channelId) return all.filter((r) => r.channelId === channelId);\n return all;\n }\n\n async remove(sessionId: string): Promise<void> {\n this.records.delete(sessionId);\n this.scheduleDiskWrite();\n }\n\n flushSync(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n const data: StoreFile = {\n version: 1,\n sessions: Object.fromEntries(this.records),\n };\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2));\n }\n\n destroy(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n if (this.cleanupInterval) clearInterval(this.cleanupInterval);\n if (this.flushHandler) {\n process.removeListener(\"SIGTERM\", this.flushHandler);\n process.removeListener(\"SIGINT\", this.flushHandler);\n process.removeListener(\"exit\", this.flushHandler);\n this.flushHandler = null;\n }\n }\n\n private load(): void {\n if (!fs.existsSync(this.filePath)) return;\n try {\n const raw = JSON.parse(\n fs.readFileSync(this.filePath, \"utf-8\"),\n ) as StoreFile;\n if (raw.version !== 1) {\n log.warn(\n { version: raw.version },\n \"Unknown session store version, skipping load\",\n );\n return;\n }\n for (const [id, record] of Object.entries(raw.sessions)) {\n this.records.set(id, record);\n }\n log.debug({ count: this.records.size }, \"Loaded session records\");\n } catch (err) {\n log.error({ err }, \"Failed to load session store, backing up corrupt file\");\n try {\n fs.renameSync(this.filePath, `${this.filePath}.bak`);\n } catch { /* best effort */ }\n }\n }\n\n private cleanup(): void {\n const cutoff = Date.now() - this.ttlDays * 24 * 60 * 60 * 1000;\n let removed = 0;\n for (const [id, record] of this.records) {\n if (record.status === \"active\" || record.status === \"initializing\")\n continue;\n const lastActive = new Date(record.lastActiveAt).getTime();\n if (lastActive < cutoff) {\n this.records.delete(id);\n removed++;\n }\n }\n if (removed > 0) {\n log.info({ removed }, \"Cleaned up expired session records\");\n this.scheduleDiskWrite();\n }\n }\n\n private scheduleDiskWrite(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n this.flushSync();\n }, DEBOUNCE_MS);\n }\n}\n","import type { AgentManager } from \"./agents/agent-manager.js\";\nimport type { SessionManager } from \"./sessions/session-manager.js\";\nimport type { ConfigManager } from \"./config/config.js\";\nimport type { SessionBridge } from \"./sessions/session-bridge.js\";\nimport type { Session } from \"./sessions/session.js\";\nimport type { IChannelAdapter } from \"./channel.js\";\nimport type { EventBus } from \"./event-bus.js\";\nimport type { MiddlewareChain } from \"./plugin/middleware-chain.js\";\nimport type { AgentEvent } from \"./types.js\";\nimport type { ContextManager } from \"../plugins/context/context-manager.js\";\nimport { getAgentCapabilities } from \"./agents/agent-registry.js\";\nimport { createChildLogger } from \"./utils/log.js\";\n\nconst log = createChildLogger({ module: \"agent-switch\" });\n\nexport interface AgentSwitchDeps {\n sessionManager: SessionManager;\n agentManager: AgentManager;\n configManager: ConfigManager;\n eventBus: EventBus;\n adapters: Map<string, IChannelAdapter>;\n bridges: Map<string, SessionBridge>;\n createBridge: (session: Session, adapter: IChannelAdapter) => SessionBridge;\n getMiddlewareChain: () => MiddlewareChain | undefined;\n getService: <T>(name: string) => T | undefined;\n}\n\nexport class AgentSwitchHandler {\n private switchingLocks = new Set<string>();\n\n constructor(private deps: AgentSwitchDeps) {}\n\n async switch(sessionId: string, toAgent: string): Promise<{ resumed: boolean }> {\n if (this.switchingLocks.has(sessionId)) {\n throw new Error('Switch already in progress');\n }\n this.switchingLocks.add(sessionId);\n try {\n return await this.doSwitch(sessionId, toAgent);\n } finally {\n this.switchingLocks.delete(sessionId);\n }\n }\n\n private async doSwitch(sessionId: string, toAgent: string): Promise<{ resumed: boolean }> {\n const { sessionManager, agentManager, configManager, eventBus, adapters, bridges, createBridge } = this.deps;\n\n const session = sessionManager.getSession(sessionId);\n if (!session) throw new Error(`Session ${sessionId} not found`);\n\n const agentDef = agentManager.getAgent(toAgent);\n if (!agentDef) throw new Error(`Agent \"${toAgent}\" is not installed`);\n\n const fromAgent = session.agentName;\n\n // 1. Middleware: agent:beforeSwitch (blocking)\n const middlewareChain = this.deps.getMiddlewareChain();\n const result = await middlewareChain?.execute('agent:beforeSwitch', {\n sessionId,\n fromAgent,\n toAgent,\n }, async (payload) => payload);\n if (middlewareChain && !result) throw new Error('Agent switch blocked by middleware');\n\n // 2. Determine resume vs new\n const lastEntry = session.findLastSwitchEntry(toAgent);\n const caps = getAgentCapabilities(toAgent);\n const canResume = !!(lastEntry && caps.supportsResume && lastEntry.promptCount === 0);\n const resumed = canResume;\n\n // Emit \"starting\" events so UI can reflect long-running switches\n const startEvent: AgentEvent = {\n type: \"system_message\",\n message: `Switching from ${fromAgent} to ${toAgent}...`,\n };\n session.emit(\"agent_event\", startEvent);\n eventBus.emit(\"agent:event\", { sessionId, event: startEvent });\n eventBus.emit(\"session:agentSwitch\", {\n sessionId,\n fromAgent,\n toAgent,\n status: \"starting\",\n });\n\n // 3. Disconnect bridge\n const bridge = bridges.get(sessionId);\n if (bridge) bridge.disconnect();\n\n const switchAdapter = adapters.get(session.channelId);\n if (switchAdapter?.sendSkillCommands) {\n await switchAdapter.sendSkillCommands(session.id, []);\n }\n if (switchAdapter?.cleanupSessionState) {\n await switchAdapter.cleanupSessionState(session.id);\n }\n\n const fromAgentSessionId = session.agentSessionId;\n\n // 4. Switch agent on session (with rollback on failure)\n try {\n await session.switchAgent(toAgent, async () => {\n if (canResume) {\n return agentManager.resume(toAgent, session.workingDirectory, lastEntry!.agentSessionId);\n } else {\n const instance = await agentManager.spawn(toAgent, session.workingDirectory);\n try {\n const contextService = this.deps.getService<ContextManager>('context');\n if (contextService) {\n const config = configManager.get();\n const labelAgent = config.agentSwitch?.labelHistory ?? true;\n const contextResult = await contextService.buildContext(\n { type: 'session', value: sessionId, repoPath: session.workingDirectory },\n { labelAgent },\n );\n if (contextResult?.markdown) {\n session.setContext(contextResult.markdown);\n }\n }\n } catch {\n // Context injection is best-effort\n }\n return instance;\n }\n });\n\n const successEvent: AgentEvent = {\n type: \"system_message\",\n message: resumed\n ? `Switched to ${toAgent} (resumed previous session).`\n : `Switched to ${toAgent} (new session).`,\n };\n session.emit(\"agent_event\", successEvent);\n eventBus.emit(\"agent:event\", { sessionId, event: successEvent });\n eventBus.emit(\"session:agentSwitch\", {\n sessionId,\n fromAgent,\n toAgent,\n status: \"succeeded\",\n resumed,\n });\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n\n const failedEvent: AgentEvent = {\n type: \"system_message\",\n message: `Failed to switch to ${toAgent}: ${errorMessage}`,\n };\n session.emit(\"agent_event\", failedEvent);\n eventBus.emit(\"agent:event\", { sessionId, event: failedEvent });\n eventBus.emit(\"session:agentSwitch\", {\n sessionId,\n fromAgent,\n toAgent,\n status: \"failed\",\n error: errorMessage,\n });\n\n // Rollback\n try {\n let rollbackInstance;\n try {\n rollbackInstance = await agentManager.resume(fromAgent, session.workingDirectory, fromAgentSessionId);\n } catch {\n rollbackInstance = await agentManager.spawn(fromAgent, session.workingDirectory);\n }\n const oldInstance = rollbackInstance;\n session.agentSwitchHistory.pop();\n session.agentInstance = oldInstance;\n session.agentName = fromAgent;\n session.agentSessionId = oldInstance.sessionId;\n const adapter = adapters.get(session.channelId);\n if (adapter) {\n createBridge(session, adapter).connect();\n }\n log.warn({ sessionId, fromAgent, toAgent, err }, \"Agent switch failed, rolled back to previous agent\");\n } catch (rollbackErr) {\n session.fail(`Switch failed and rollback failed: ${rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr)}`);\n log.error({ sessionId, fromAgent, toAgent, err, rollbackErr }, \"Agent switch failed and rollback also failed\");\n }\n throw err;\n }\n\n // 5. Reconnect bridge\n if (bridge) {\n const adapter = adapters.get(session.channelId);\n if (adapter) {\n createBridge(session, adapter).connect();\n }\n }\n\n // 6. Persist\n await sessionManager.patchRecord(sessionId, {\n agentName: toAgent,\n agentSessionId: session.agentSessionId,\n firstAgent: session.firstAgent,\n currentPromptCount: 0,\n agentSwitchHistory: session.agentSwitchHistory,\n });\n\n // 7. Middleware: agent:afterSwitch (fire-and-forget)\n middlewareChain?.execute('agent:afterSwitch', {\n sessionId,\n fromAgent,\n toAgent,\n resumed,\n }, async (p) => p).catch(() => {});\n\n return { resumed };\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { AgentStore } from \"./agent-store.js\";\nimport { installAgent, uninstallAgent, resolveDistribution } from \"./agent-installer.js\";\nimport { getAgentAlias, checkDependencies } from \"./agent-dependencies.js\";\nimport type {\n AgentDefinition,\n RegistryAgent,\n AgentListItem,\n AvailabilityResult,\n InstallProgress,\n InstallResult,\n InstalledAgent,\n} from \"../types.js\";\nimport { createChildLogger } from \"../utils/log.js\";\n\nconst log = createChildLogger({ module: \"agent-catalog\" });\n\nconst REGISTRY_URL = \"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json\";\nconst DEFAULT_TTL_HOURS = 24;\n\ninterface RegistryCache {\n fetchedAt: string;\n ttlHours: number;\n data: { agents: RegistryAgent[] };\n}\n\nexport class AgentCatalog {\n private store: AgentStore;\n private registryAgents: RegistryAgent[] = [];\n private cachePath: string;\n private agentsDir: string | undefined;\n\n constructor(store?: AgentStore, cachePath?: string, agentsDir?: string) {\n this.store = store ?? new AgentStore();\n this.cachePath = cachePath ?? path.join(os.homedir(), \".openacp\", \"registry-cache.json\");\n this.agentsDir = agentsDir;\n }\n\n load(): void {\n this.store.load();\n this.loadRegistryFromCacheOrSnapshot();\n this.enrichInstalledFromRegistry();\n }\n\n // --- Registry ---\n\n async fetchRegistry(): Promise<void> {\n try {\n log.info(\"Fetching agent registry from CDN...\");\n const response = await fetch(REGISTRY_URL);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data = await response.json() as { agents: RegistryAgent[] };\n this.registryAgents = data.agents ?? [];\n\n const cache: RegistryCache = {\n fetchedAt: new Date().toISOString(),\n ttlHours: DEFAULT_TTL_HOURS,\n data,\n };\n fs.mkdirSync(path.dirname(this.cachePath), { recursive: true });\n fs.writeFileSync(this.cachePath, JSON.stringify(cache, null, 2));\n log.info({ count: this.registryAgents.length }, \"Registry updated\");\n } catch (err) {\n log.warn({ err }, \"Failed to fetch registry, using cached data\");\n }\n }\n\n async refreshRegistryIfStale(): Promise<void> {\n if (this.isCacheStale()) {\n await this.fetchRegistry();\n }\n }\n\n getRegistryAgents(): RegistryAgent[] {\n return this.registryAgents;\n }\n\n getRegistryAgent(registryId: string): RegistryAgent | undefined {\n return this.registryAgents.find((a) => a.id === registryId);\n }\n\n findRegistryAgent(keyOrId: string): RegistryAgent | undefined {\n const byId = this.registryAgents.find((a) => a.id === keyOrId);\n if (byId) return byId;\n return this.registryAgents.find((a) => getAgentAlias(a.id) === keyOrId);\n }\n\n // --- Installed ---\n\n getInstalled(): InstalledAgent[] {\n return Object.values(this.store.getInstalled());\n }\n\n getInstalledEntries(): Record<string, InstalledAgent> {\n return this.store.getInstalled();\n }\n\n getInstalledAgent(key: string): InstalledAgent | undefined {\n return this.store.getAgent(key);\n }\n\n // --- Discovery ---\n\n getAvailable(): AgentListItem[] {\n const installed = this.store.getInstalled();\n const items: AgentListItem[] = [];\n const seenKeys = new Set<string>();\n\n for (const [key, agent] of Object.entries(installed)) {\n seenKeys.add(key);\n const availability = agent.registryId\n ? checkDependencies(agent.registryId)\n : { available: true };\n const registryEntry = agent.registryId\n ? this.registryAgents.find((a) => a.id === agent.registryId)\n : undefined;\n items.push({\n key,\n registryId: agent.registryId ?? key,\n name: agent.name,\n version: agent.version,\n description: registryEntry?.description,\n distribution: agent.distribution,\n installed: true,\n available: availability.available,\n missingDeps: availability.missing?.map((m) => m.label),\n });\n }\n\n for (const agent of this.registryAgents) {\n const alias = getAgentAlias(agent.id);\n if (seenKeys.has(alias)) continue;\n seenKeys.add(alias);\n\n const dist = resolveDistribution(agent);\n const availability = checkDependencies(agent.id);\n\n items.push({\n key: alias,\n registryId: agent.id,\n name: agent.name,\n version: agent.version,\n description: agent.description,\n distribution: dist?.type ?? \"binary\",\n installed: false,\n available: dist !== null && availability.available,\n missingDeps: availability.missing?.map((m) => m.label),\n });\n }\n\n return items;\n }\n\n checkAvailability(keyOrId: string): AvailabilityResult {\n const agent = this.findRegistryAgent(keyOrId);\n if (!agent) return { available: false, reason: \"Not found in the agent registry.\" };\n\n const dist = resolveDistribution(agent);\n if (!dist) {\n return { available: false, reason: `Not available for your system. Check ${agent.website ?? agent.repository ?? \"their website\"} for other options.` };\n }\n\n return checkDependencies(agent.id);\n }\n\n // --- Install/Uninstall ---\n\n async install(keyOrId: string, progress?: InstallProgress, force?: boolean): Promise<InstallResult> {\n const agent = this.findRegistryAgent(keyOrId);\n if (!agent) {\n const msg = `\"${keyOrId}\" was not found in the agent registry. Run \"openacp agents\" to see what's available.`;\n await progress?.onError(msg);\n return { ok: false, agentKey: keyOrId, error: msg };\n }\n\n const agentKey = getAgentAlias(agent.id);\n if (this.store.hasAgent(agentKey) && !force) {\n const existing = this.store.getAgent(agentKey)!;\n const msg = `${agent.name} is already installed (v${existing.version}). Use --force to reinstall.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n return installAgent(agent, this.store, progress, this.agentsDir);\n }\n\n async uninstall(key: string): Promise<{ ok: boolean; error?: string }> {\n if (!this.store.hasAgent(key)) {\n return { ok: false, error: `\"${key}\" is not installed.` };\n }\n await uninstallAgent(key, this.store);\n return { ok: true };\n }\n\n // --- Resolution (for AgentManager) ---\n\n resolve(key: string): AgentDefinition | undefined {\n const agent = this.store.getAgent(key);\n if (!agent) return undefined;\n return {\n name: key,\n command: agent.command,\n args: agent.args,\n workingDirectory: agent.workingDirectory,\n env: agent.env,\n };\n }\n\n // --- Internal ---\n\n /**\n * Enrich installed agents (especially migrated ones) with registry data.\n * Fixes agents that were migrated with version:\"unknown\", distribution:\"custom\",\n * or generic names by matching them to registry entries.\n */\n private enrichInstalledFromRegistry(): void {\n const installed = this.store.getInstalled();\n let changed = false;\n\n for (const [key, agent] of Object.entries(installed)) {\n const regAgent = agent.registryId\n ? this.registryAgents.find((a) => a.id === agent.registryId)\n : this.registryAgents.find((a) => getAgentAlias(a.id) === key);\n\n if (!regAgent) continue;\n\n let updated = false;\n\n // Enrich name if it's a generic capitalized key (e.g. \"Claude\" from migration)\n if (agent.name !== regAgent.name) {\n agent.name = regAgent.name;\n updated = true;\n }\n\n // Enrich version if unknown\n if (agent.version === \"unknown\") {\n agent.version = regAgent.version;\n updated = true;\n }\n\n // Enrich registryId if missing\n if (!agent.registryId) {\n agent.registryId = regAgent.id;\n updated = true;\n }\n\n // Enrich distribution from \"custom\" to actual type\n if (agent.distribution === \"custom\") {\n const dist = resolveDistribution(regAgent);\n if (dist) {\n agent.distribution = dist.type;\n updated = true;\n }\n }\n\n if (updated) {\n this.store.addAgent(key, agent);\n changed = true;\n }\n }\n\n if (changed) {\n log.info(\"Enriched installed agents with registry data\");\n }\n }\n\n private isCacheStale(): boolean {\n if (!fs.existsSync(this.cachePath)) return true;\n try {\n const raw = JSON.parse(fs.readFileSync(this.cachePath, \"utf-8\") as string) as RegistryCache;\n const fetchedAt = new Date(raw.fetchedAt).getTime();\n const ttlMs = (raw.ttlHours ?? DEFAULT_TTL_HOURS) * 60 * 60 * 1000;\n return Date.now() - fetchedAt > ttlMs;\n } catch {\n return true;\n }\n }\n\n private loadRegistryFromCacheOrSnapshot(): void {\n // Try cache first\n if (fs.existsSync(this.cachePath)) {\n try {\n const raw = JSON.parse(fs.readFileSync(this.cachePath, \"utf-8\") as string) as RegistryCache;\n if (raw.data?.agents) {\n this.registryAgents = raw.data.agents;\n log.debug({ count: this.registryAgents.length }, \"Loaded registry from cache\");\n return;\n }\n } catch {\n log.warn(\"Failed to load registry cache\");\n }\n }\n\n // Fallback: bundled snapshot\n try {\n // Try multiple paths for tsc and tsup builds\n const candidates = [\n path.join(import.meta.dirname, \"data\", \"registry-snapshot.json\"),\n path.join(import.meta.dirname, \"..\", \"data\", \"registry-snapshot.json\"),\n path.join(import.meta.dirname, \"..\", \"..\", \"data\", \"registry-snapshot.json\"),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n const raw = JSON.parse(fs.readFileSync(candidate, \"utf-8\") as string);\n this.registryAgents = raw.agents ?? [];\n log.debug({ count: this.registryAgents.length }, \"Loaded registry from bundled snapshot\");\n return;\n }\n }\n\n log.warn(\"No registry data available (no cache, no snapshot)\");\n } catch {\n log.warn(\"Failed to load bundled registry snapshot\");\n }\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { z } from \"zod\";\nimport type { InstalledAgent } from \"../types.js\";\nimport { createChildLogger } from \"../utils/log.js\";\n\nconst log = createChildLogger({ module: \"agent-store\" });\n\nconst InstalledAgentSchema = z.object({\n registryId: z.string().nullable(),\n name: z.string(),\n version: z.string(),\n distribution: z.enum([\"npx\", \"uvx\", \"binary\", \"custom\"]),\n command: z.string(),\n args: z.array(z.string()).default([]),\n env: z.record(z.string(), z.string()).default({}),\n workingDirectory: z.string().optional(),\n installedAt: z.string(),\n binaryPath: z.string().nullable().default(null),\n});\n\nconst AgentStoreSchema = z.object({\n version: z.number().default(1),\n installed: z.record(z.string(), InstalledAgentSchema).default({}),\n});\n\ntype AgentStoreData = z.infer<typeof AgentStoreSchema>;\n\nexport class AgentStore {\n private data: AgentStoreData = { version: 1, installed: {} };\n private filePath: string;\n\n constructor(filePath?: string) {\n this.filePath = filePath ?? path.join(os.homedir(), \".openacp\", \"agents.json\");\n }\n\n load(): void {\n if (!fs.existsSync(this.filePath)) {\n this.data = { version: 1, installed: {} };\n return;\n }\n\n try {\n const raw = JSON.parse(fs.readFileSync(this.filePath, \"utf-8\") as string);\n const result = AgentStoreSchema.safeParse(raw);\n if (result.success) {\n this.data = result.data;\n } else {\n log.warn({ errors: result.error.issues }, \"Invalid agents.json, starting fresh\");\n this.data = { version: 1, installed: {} };\n }\n } catch (err) {\n log.warn({ err }, \"Failed to read agents.json, starting fresh\");\n this.data = { version: 1, installed: {} };\n }\n }\n\n exists(): boolean {\n return fs.existsSync(this.filePath);\n }\n\n getInstalled(): Record<string, InstalledAgent> {\n return this.data.installed;\n }\n\n getAgent(key: string): InstalledAgent | undefined {\n return this.data.installed[key];\n }\n\n addAgent(key: string, agent: InstalledAgent): void {\n this.data.installed[key] = agent;\n this.save();\n }\n\n removeAgent(key: string): void {\n delete this.data.installed[key];\n this.save();\n }\n\n hasAgent(key: string): boolean {\n return key in this.data.installed;\n }\n\n private save(): void {\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n const tmpPath = this.filePath + \".tmp\";\n fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2));\n fs.renameSync(tmpPath, this.filePath);\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { createChildLogger } from \"../utils/log.js\";\nimport type { InstalledAgent, RegistryAgent, InstallProgress, InstallResult } from \"../types.js\";\nimport { getAgentAlias, checkDependencies, checkRuntimeAvailable, getAgentSetup } from \"./agent-dependencies.js\";\nimport { AgentStore } from \"./agent-store.js\";\n\nconst log = createChildLogger({ module: \"agent-installer\" });\n\nconst DEFAULT_AGENTS_DIR = path.join(os.homedir(), \".openacp\", \"agents\");\n\nconst ARCH_MAP: Record<string, string> = {\n arm64: \"aarch64\",\n x64: \"x86_64\",\n};\n\nconst PLATFORM_MAP: Record<string, string> = {\n darwin: \"darwin\",\n linux: \"linux\",\n win32: \"windows\",\n};\n\nexport function getPlatformKey(): string {\n const platform = PLATFORM_MAP[process.platform] ?? process.platform;\n const arch = ARCH_MAP[process.arch] ?? process.arch;\n return `${platform}-${arch}`;\n}\n\nexport type ResolvedDistribution =\n | { type: \"npx\"; package: string; args: string[]; env?: Record<string, string> }\n | { type: \"uvx\"; package: string; args: string[]; env?: Record<string, string> }\n | { type: \"binary\"; archive: string; cmd: string; args: string[]; env?: Record<string, string> };\n\nexport function resolveDistribution(agent: RegistryAgent): ResolvedDistribution | null {\n const dist = agent.distribution;\n\n if (dist.npx) {\n return { type: \"npx\", package: dist.npx.package, args: dist.npx.args ?? [], env: dist.npx.env };\n }\n if (dist.uvx) {\n return { type: \"uvx\", package: dist.uvx.package, args: dist.uvx.args ?? [], env: dist.uvx.env };\n }\n if (dist.binary) {\n const platformKey = getPlatformKey();\n const target = dist.binary[platformKey];\n if (!target) return null;\n return { type: \"binary\", archive: target.archive, cmd: target.cmd, args: target.args ?? [], env: target.env };\n }\n return null;\n}\n\nexport function buildInstalledAgent(\n registryId: string,\n name: string,\n version: string,\n dist: ResolvedDistribution,\n binaryPath?: string,\n): InstalledAgent {\n if (dist.type === \"npx\") {\n // Use latest version: strip pinned version from package name (e.g. @google/gemini-cli@0.34.0 → @google/gemini-cli)\n const npxPackage = stripPackageVersion(dist.package);\n return {\n registryId, name, version, distribution: \"npx\",\n command: \"npx\", args: [npxPackage, ...dist.args],\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: null,\n };\n }\n if (dist.type === \"uvx\") {\n // Strip pinned version: \"fast-agent-acp==0.6.6\" → \"fast-agent-acp\", \"minion-code@0.1.44\" → \"minion-code\"\n const uvxPackage = stripPythonPackageVersion(dist.package);\n return {\n registryId, name, version, distribution: \"uvx\",\n command: \"uvx\", args: [uvxPackage, ...dist.args],\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: null,\n };\n }\n // binary\n const absCmd = path.resolve(binaryPath!, dist.cmd);\n return {\n registryId, name, version, distribution: \"binary\",\n command: absCmd, args: dist.args,\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: binaryPath!,\n };\n}\n\n/**\n * Strip pinned version from npm package name so npx always uses latest.\n * e.g. \"@google/gemini-cli@0.34.0\" → \"@google/gemini-cli\"\n * \"cline@2.9.0\" → \"cline\"\n * \"@scope/pkg\" → \"@scope/pkg\" (no version, unchanged)\n */\nfunction stripPackageVersion(pkg: string): string {\n // Scoped: @scope/name@version → find the second @\n if (pkg.startsWith(\"@\")) {\n const afterScope = pkg.indexOf(\"/\");\n if (afterScope === -1) return pkg;\n const versionAt = pkg.indexOf(\"@\", afterScope + 1);\n return versionAt === -1 ? pkg : pkg.slice(0, versionAt);\n }\n // Unscoped: name@version\n const at = pkg.indexOf(\"@\");\n return at === -1 ? pkg : pkg.slice(0, at);\n}\n\n/**\n * Strip pinned version from Python package name so uvx always uses latest.\n * e.g. \"fast-agent-acp==0.6.6\" → \"fast-agent-acp\"\n * \"minion-code@0.1.44\" → \"minion-code\"\n * \"crow-cli\" → \"crow-cli\" (no version, unchanged)\n */\nfunction stripPythonPackageVersion(pkg: string): string {\n // Python-style: name==version or name>=version\n const pyMatch = pkg.match(/^([^=@><!]+)/);\n if (pyMatch && pkg.includes(\"==\")) return pyMatch[1]!;\n // npm-style @ used in some uvx packages\n const at = pkg.indexOf(\"@\");\n return at === -1 ? pkg : pkg.slice(0, at);\n}\n\nexport async function installAgent(\n agent: RegistryAgent,\n store: AgentStore,\n progress?: InstallProgress,\n agentsDir?: string,\n): Promise<InstallResult> {\n const agentKey = getAgentAlias(agent.id);\n await progress?.onStart(agent.id, agent.name);\n\n // 1. Check dependencies\n await progress?.onStep(\"Checking requirements...\");\n const depResult = checkDependencies(agent.id);\n if (!depResult.available) {\n const hints = depResult.missing!.map((m) => ` ${m.label}: ${m.installHint}`).join(\"\\n\");\n const msg = `${agent.name} needs some tools installed first:\\n${hints}`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n // 2. Resolve distribution\n const dist = resolveDistribution(agent);\n if (!dist) {\n const platformKey = getPlatformKey();\n const msg = `${agent.name} is not available for your system (${platformKey}). Check their website for other install options.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n // 3. Check runtime\n if (dist.type === \"uvx\" && !checkRuntimeAvailable(\"uvx\")) {\n const msg = `${agent.name} requires Python's uvx tool.\\nInstall it with: pip install uv`;\n await progress?.onError(msg, \"pip install uv\");\n return { ok: false, agentKey, error: msg, hint: \"pip install uv\" };\n }\n\n // 4. Install based on type\n let binaryPath: string | undefined;\n\n if (dist.type === \"binary\") {\n try {\n binaryPath = await downloadAndExtract(agent.id, dist.archive, progress, agentsDir);\n } catch (err) {\n const msg = `Failed to download ${agent.name}. Please try again or install manually.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n } else {\n await progress?.onStep(\"Setting up... (will download on first use)\");\n }\n\n // 5. Save to store\n const installed = buildInstalledAgent(agent.id, agent.name, agent.version, dist, binaryPath);\n store.addAgent(agentKey, installed);\n\n const setup = getAgentSetup(agent.id);\n await progress?.onSuccess(agent.name);\n return { ok: true, agentKey, setupSteps: setup?.setupSteps };\n}\n\nasync function downloadAndExtract(\n agentId: string,\n archiveUrl: string,\n progress?: InstallProgress,\n agentsDir?: string,\n): Promise<string> {\n const destDir = path.join(agentsDir ?? DEFAULT_AGENTS_DIR, agentId);\n fs.mkdirSync(destDir, { recursive: true });\n\n await progress?.onStep(\"Downloading...\");\n log.info({ agentId, url: archiveUrl }, \"Downloading agent binary\");\n\n const response = await fetch(archiveUrl);\n if (!response.ok) {\n throw new Error(`Download failed: ${response.status} ${response.statusText}`);\n }\n\n const contentLength = Number(response.headers.get(\"content-length\") || 0);\n const buffer = await readResponseWithProgress(response, contentLength, progress);\n\n await progress?.onStep(\"Extracting...\");\n\n if (archiveUrl.endsWith(\".zip\")) {\n await extractZip(buffer, destDir);\n } else {\n await extractTarGz(buffer, destDir);\n }\n\n await progress?.onStep(\"Ready!\");\n return destDir;\n}\n\nasync function readResponseWithProgress(\n response: Response,\n contentLength: number,\n progress?: InstallProgress,\n): Promise<Buffer> {\n if (!response.body || contentLength === 0) {\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let received = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n received += value.length;\n if (contentLength > 0) {\n await progress?.onDownloadProgress(Math.round((received / contentLength) * 100));\n }\n }\n\n return Buffer.concat(chunks);\n}\n\nfunction validateExtractedPaths(destDir: string): void {\n const realDest = fs.realpathSync(destDir);\n const entries = fs.readdirSync(destDir, { recursive: true, withFileTypes: true });\n for (const entry of entries) {\n // Node <20.12 uses `path`, >=20.12 uses `parentPath` on Dirent with recursive readdir\n const dirent = entry as fs.Dirent & { parentPath?: string; path?: string };\n const parentPath = dirent.parentPath ?? dirent.path ?? destDir;\n const fullPath = path.join(parentPath, entry.name);\n let realPath: string;\n try {\n realPath = fs.realpathSync(fullPath);\n } catch {\n // Broken symlink — check where it points\n const linkTarget = fs.readlinkSync(fullPath);\n realPath = path.resolve(path.dirname(fullPath), linkTarget);\n }\n if (!realPath.startsWith(realDest + path.sep) && realPath !== realDest) {\n fs.rmSync(destDir, { recursive: true, force: true });\n throw new Error(`Archive contains unsafe path: ${entry.name}`);\n }\n }\n}\n\nasync function extractTarGz(buffer: Buffer, destDir: string): Promise<void> {\n const { execFileSync } = await import(\"node:child_process\");\n const tmpFile = path.join(destDir, \"_archive.tar.gz\");\n fs.writeFileSync(tmpFile, buffer);\n try {\n execFileSync(\"tar\", [\"xzf\", tmpFile, \"-C\", destDir], { stdio: \"pipe\" });\n } finally {\n fs.unlinkSync(tmpFile);\n }\n validateExtractedPaths(destDir);\n}\n\nasync function extractZip(buffer: Buffer, destDir: string): Promise<void> {\n const { execFileSync } = await import(\"node:child_process\");\n const tmpFile = path.join(destDir, \"_archive.zip\");\n fs.writeFileSync(tmpFile, buffer);\n try {\n execFileSync(\"unzip\", [\"-o\", tmpFile, \"-d\", destDir], { stdio: \"pipe\" });\n } finally {\n fs.unlinkSync(tmpFile);\n }\n validateExtractedPaths(destDir);\n}\n\nexport async function uninstallAgent(\n agentKey: string,\n store: AgentStore,\n): Promise<void> {\n const agent = store.getAgent(agentKey);\n if (!agent) return;\n\n if (agent.binaryPath && fs.existsSync(agent.binaryPath)) {\n fs.rmSync(agent.binaryPath, { recursive: true, force: true });\n log.info({ agentKey, binaryPath: agent.binaryPath }, \"Deleted agent binary\");\n }\n\n store.removeAgent(agentKey);\n}\n","import { TypedEmitter } from \"./utils/typed-emitter.js\";\nimport type { AgentEvent, PermissionRequest, SessionStatus, UsageRecordEvent } from \"./types.js\";\n\nexport interface EventBusEvents {\n \"session:created\": (data: {\n sessionId: string;\n agent: string;\n status: SessionStatus;\n }) => void;\n \"session:updated\": (data: {\n sessionId: string;\n status?: SessionStatus;\n name?: string;\n dangerousMode?: boolean;\n }) => void;\n \"session:deleted\": (data: { sessionId: string }) => void;\n \"agent:event\": (data: { sessionId: string; event: AgentEvent }) => void;\n \"permission:request\": (data: {\n sessionId: string;\n permission: PermissionRequest;\n }) => void;\n \"permission:resolved\": (data: {\n sessionId: string;\n requestId: string;\n decision: string;\n }) => void;\n\n // System lifecycle\n \"kernel:booted\": () => void;\n \"system:ready\": () => void;\n \"system:shutdown\": () => void;\n \"system:commands-ready\": (data: {\n commands: Array<{ name: string; description: string }>;\n }) => void;\n\n // Plugin lifecycle\n \"plugin:loaded\": (data: { name: string; version: string }) => void;\n \"plugin:failed\": (data: { name: string; error: string }) => void;\n \"plugin:disabled\": (data: { name: string; reason: string }) => void;\n \"plugin:unloaded\": (data: { name: string }) => void;\n\n // Session (additional)\n \"session:ended\": (data: { sessionId: string; reason: string }) => void;\n \"session:named\": (data: { sessionId: string; name: string }) => void;\n\n // Agent (additional)\n \"agent:prompt\": (data: {\n sessionId: string;\n text: string;\n attachments?: unknown[];\n }) => void;\n\n // Usage tracking (consumed by usage plugin)\n \"usage:recorded\": (data: UsageRecordEvent) => void;\n\n // Agent switch lifecycle (used by UI & dashboards)\n \"session:agentSwitch\": (data: {\n sessionId: string;\n fromAgent: string;\n toAgent: string;\n status: \"starting\" | \"succeeded\" | \"failed\";\n resumed?: boolean;\n error?: string;\n }) => void;\n}\n\nexport class EventBus extends TypedEmitter<EventBusEvents> {}\n","import { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport type { OpenACPPlugin } from './types.js'\n\n/**\n * Resolve plugin load order via topological sort.\n * - Handles `overrides` field: overridden plugins are removed before sorting.\n * - Detects circular dependencies and throws.\n * - Missing dependencies: skip plugin + all dependents (cascade).\n */\nexport function resolveLoadOrder(plugins: OpenACPPlugin[]): OpenACPPlugin[] {\n // Phase 1: Apply overrides — remove overridden plugins\n const overrideTargets = new Set<string>()\n for (const p of plugins) {\n if (p.overrides) {\n overrideTargets.add(p.overrides)\n }\n }\n let remaining = plugins.filter((p) => !overrideTargets.has(p.name))\n\n // Phase 2: Build name→plugin map\n const byName = new Map<string, OpenACPPlugin>()\n for (const p of remaining) {\n byName.set(p.name, p)\n }\n\n // Phase 3: Find missing deps and cascade-skip\n const skipped = new Set<string>()\n\n function cascadeSkip(name: string): void {\n if (skipped.has(name)) return\n skipped.add(name)\n // Skip all plugins that depend on this one\n for (const p of remaining) {\n if (p.pluginDependencies && name in p.pluginDependencies) {\n cascadeSkip(p.name)\n }\n }\n }\n\n for (const p of remaining) {\n if (p.pluginDependencies) {\n for (const dep of Object.keys(p.pluginDependencies)) {\n if (!byName.has(dep)) {\n cascadeSkip(p.name)\n }\n }\n }\n }\n\n remaining = remaining.filter((p) => !skipped.has(p.name))\n\n // Rebuild map after skipping\n byName.clear()\n for (const p of remaining) {\n byName.set(p.name, p)\n }\n\n // Phase 4: Topological sort with cycle detection (DFS)\n const visited = new Set<string>()\n const inStack = new Set<string>()\n const order: OpenACPPlugin[] = []\n\n function visit(name: string): void {\n if (visited.has(name)) return\n if (inStack.has(name)) {\n throw new Error(`Circular dependency detected: ${name}`)\n }\n\n inStack.add(name)\n const plugin = byName.get(name)!\n if (plugin.pluginDependencies) {\n for (const dep of Object.keys(plugin.pluginDependencies)) {\n visit(dep)\n }\n }\n inStack.delete(name)\n visited.add(name)\n order.push(plugin)\n }\n\n for (const p of remaining) {\n visit(p.name)\n }\n\n return order\n}\n\n/**\n * Compute SHA-256 checksum of a file, returned as 64-char hex string.\n */\nexport function computeChecksum(filePath: string): string {\n const data = readFileSync(filePath)\n return createHash('sha256').update(data).digest('hex')\n}\n\n/**\n * Verify that actual checksum matches expected.\n */\nexport function verifyChecksum(_name: string, expected: string, actual: string): boolean {\n return expected === actual\n}\n","export class ServiceRegistry {\n private services = new Map<string, { implementation: unknown; pluginName: string }>()\n\n register<T>(name: string, implementation: T, pluginName: string): void {\n if (this.services.has(name)) {\n const existing = this.services.get(name)!\n throw new Error(`Service '${name}' already registered by ${existing.pluginName}. Plugin ${pluginName} cannot register it without override.`)\n }\n this.services.set(name, { implementation, pluginName })\n }\n\n registerOverride<T>(name: string, implementation: T, pluginName: string): void {\n this.services.set(name, { implementation, pluginName })\n }\n\n get<T>(name: string): T | undefined {\n return this.services.get(name)?.implementation as T | undefined\n }\n\n has(name: string): boolean {\n return this.services.has(name)\n }\n\n list(): Array<{ name: string; pluginName: string }> {\n return [...this.services.entries()].map(([name, { pluginName }]) => ({ name, pluginName }))\n }\n\n unregister(name: string): void {\n this.services.delete(name)\n }\n\n unregisterByPlugin(pluginName: string): void {\n for (const [name, entry] of this.services) {\n if (entry.pluginName === pluginName) {\n this.services.delete(name)\n }\n }\n }\n}\n","import type { ErrorTracker } from './error-tracker.js'\n\nconst MIDDLEWARE_TIMEOUT_MS = 5000\n\ntype HandlerEntry = {\n pluginName: string\n priority: number\n handler: Function\n}\n\nexport class MiddlewareChain {\n private chains = new Map<string, Array<HandlerEntry>>()\n private errorHandler?: (pluginName: string, error: Error) => void\n private errorTracker?: ErrorTracker\n\n add(\n hook: string,\n pluginName: string,\n opts: { priority?: number; handler: Function },\n ): void {\n const entry: HandlerEntry = {\n pluginName,\n priority: opts.priority ?? 100,\n handler: opts.handler,\n }\n const existing = this.chains.get(hook)\n if (existing) {\n existing.push(entry)\n existing.sort((a, b) => a.priority - b.priority)\n } else {\n this.chains.set(hook, [entry])\n }\n }\n\n async execute<T>(\n hook: string,\n payload: T,\n coreHandler: (p: T) => T | Promise<T>,\n ): Promise<T | null> {\n const handlers = this.chains.get(hook)\n if (!handlers || handlers.length === 0) {\n return coreHandler(payload)\n }\n\n // Handlers are pre-sorted by priority at registration time\n const sorted = handlers\n\n // Build the chain\n let cachedResult: { value: T | null } | undefined = undefined\n\n const buildNext = (index: number, currentPayload: T): (() => Promise<T | null>) => {\n return async () => {\n // Return cached result on double-call\n if (cachedResult !== undefined) {\n return cachedResult.value\n }\n\n if (index >= sorted.length) {\n // End of middleware chain — call core handler\n const result = await coreHandler(currentPayload)\n cachedResult = { value: result }\n return result\n }\n\n const entry = sorted[index]\n\n // Skip disabled plugins\n if (this.errorTracker?.isDisabled(entry.pluginName)) {\n const skipFn = buildNext(index + 1, currentPayload)\n return skipFn()\n }\n\n const nextFn = buildNext(index + 1, currentPayload)\n\n // Wrap next to detect when it has been called and cache\n let nextCalled = false\n let nextResult: T | null = null\n const wrappedNext = async (newPayload?: T): Promise<T | null> => {\n if (!nextCalled) {\n nextCalled = true\n const payloadForNext = newPayload !== undefined ? newPayload : currentPayload\n // Rebuild chain from next index with potentially updated payload\n const newNextFn = buildNext(index + 1, payloadForNext)\n nextResult = await newNextFn()\n }\n return nextResult\n }\n\n let handlerResult: T | null\n let timeoutTimer: ReturnType<typeof setTimeout> | undefined\n try {\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutTimer = setTimeout(\n () => reject(new Error(`Middleware timeout: ${entry.pluginName} on hook ${hook}`)),\n MIDDLEWARE_TIMEOUT_MS,\n )\n if (typeof timeoutTimer === 'object' && timeoutTimer !== null && 'unref' in timeoutTimer) {\n ;(timeoutTimer as NodeJS.Timeout).unref()\n }\n })\n\n handlerResult = await Promise.race([\n entry.handler(currentPayload, wrappedNext),\n timeoutPromise,\n ])\n } catch (err) {\n // Report error\n if (this.errorHandler) {\n this.errorHandler(entry.pluginName, err instanceof Error ? err : new Error(String(err)))\n }\n // Track error for circuit-breaking\n this.errorTracker?.increment(entry.pluginName)\n // Skip this handler — pass ORIGINAL payload to next\n return nextFn()\n } finally {\n clearTimeout(timeoutTimer!)\n }\n\n // Handler returned null — block\n if (handlerResult === null) {\n return null\n }\n\n return handlerResult\n }\n }\n\n const start = buildNext(0, payload)\n return start()\n }\n\n removeAll(pluginName: string): void {\n for (const [hook, handlers] of this.chains.entries()) {\n const filtered = handlers.filter((h) => h.pluginName !== pluginName)\n if (filtered.length === 0) {\n this.chains.delete(hook)\n } else {\n this.chains.set(hook, filtered)\n }\n }\n }\n\n setErrorHandler(fn: (pluginName: string, error: Error) => void): void {\n this.errorHandler = fn\n }\n\n setErrorTracker(tracker: ErrorTracker): void {\n this.errorTracker = tracker\n }\n}\n","export interface ErrorBudgetConfig {\n maxErrors: number // default 10\n windowMs: number // default 3600000 (1 hour)\n}\n\nexport class ErrorTracker {\n private errors = new Map<string, { count: number; windowStart: number }>()\n private disabled = new Set<string>()\n private exempt = new Set<string>()\n private config: ErrorBudgetConfig\n\n onDisabled?: (pluginName: string, reason: string) => void\n\n constructor(config?: Partial<ErrorBudgetConfig>) {\n this.config = { maxErrors: config?.maxErrors ?? 10, windowMs: config?.windowMs ?? 3600000 }\n }\n\n increment(pluginName: string): void {\n if (this.exempt.has(pluginName)) return\n\n const now = Date.now()\n const entry = this.errors.get(pluginName)\n\n if (!entry || now - entry.windowStart >= this.config.windowMs) {\n this.errors.set(pluginName, { count: 1, windowStart: now })\n } else {\n entry.count += 1\n }\n\n const current = this.errors.get(pluginName)!\n if (current.count >= this.config.maxErrors && !this.disabled.has(pluginName)) {\n this.disabled.add(pluginName)\n const reason = `Error budget exceeded: ${current.count} errors within ${this.config.windowMs}ms window`\n this.onDisabled?.(pluginName, reason)\n }\n }\n\n isDisabled(pluginName: string): boolean {\n return this.disabled.has(pluginName)\n }\n\n reset(pluginName: string): void {\n this.disabled.delete(pluginName)\n this.errors.delete(pluginName)\n }\n\n setExempt(pluginName: string): void {\n this.exempt.add(pluginName)\n }\n}\n","import path from 'node:path'\nimport os from 'node:os'\nimport type {\n PluginContext,\n PluginPermission,\n CommandDef,\n MiddlewareHook,\n MiddlewareOptions,\n MiddlewarePayloadMap,\n PluginStorage,\n EventBus,\n Logger,\n OutgoingMessage,\n} from './types.js'\nimport { ServiceRegistry } from './service-registry.js'\nimport { MiddlewareChain } from './middleware-chain.js'\nimport { ErrorTracker } from './error-tracker.js'\nimport { PluginStorageImpl } from './plugin-storage.js'\n\ninterface CreatePluginContextOpts {\n pluginName: string\n pluginConfig: Record<string, unknown>\n permissions: PluginPermission[]\n serviceRegistry: ServiceRegistry\n middlewareChain: MiddlewareChain\n errorTracker: ErrorTracker\n eventBus: EventBus & {\n on(event: string, handler: (...args: unknown[]) => void): void\n off(event: string, handler: (...args: unknown[]) => void): void\n emit(event: string, payload: unknown): void\n }\n storagePath: string\n sessions: unknown\n config: unknown\n core?: unknown\n log?: Logger\n instanceRoot?: string\n}\n\nfunction requirePermission(permissions: PluginPermission[], required: PluginPermission, action: string): void {\n if (!permissions.includes(required)) {\n throw new Error(`Plugin does not have '${required}' permission required for ${action}`)\n }\n}\n\nexport function createPluginContext(opts: CreatePluginContextOpts): PluginContext & { cleanup(): void } {\n const {\n pluginName,\n pluginConfig,\n permissions,\n serviceRegistry,\n middlewareChain,\n eventBus,\n storagePath,\n sessions,\n config,\n core,\n } = opts\n const instanceRoot = opts.instanceRoot ?? path.join(os.homedir(), '.openacp')\n\n // Track registered items for cleanup\n const registeredListeners: Array<{ event: string; handler: (...args: unknown[]) => void }> = []\n const registeredCommands: CommandDef[] = []\n\n const noopLog: Logger = {\n trace() {},\n debug() {},\n info() {},\n warn() {},\n error() {},\n fatal() {},\n child() { return noopLog },\n }\n const baseLog: Logger = opts.log ?? noopLog\n const log: Logger = typeof baseLog.child === 'function'\n ? baseLog.child({ plugin: pluginName })\n : baseLog\n\n const storageImpl = new PluginStorageImpl(storagePath)\n\n // Create permission-guarded storage proxy\n const storage: PluginStorage = {\n async get<T>(key: string): Promise<T | undefined> {\n requirePermission(permissions, 'storage:read', 'storage.get')\n return storageImpl.get<T>(key)\n },\n async set<T>(key: string, value: T): Promise<void> {\n requirePermission(permissions, 'storage:write', 'storage.set')\n return storageImpl.set(key, value)\n },\n async delete(key: string): Promise<void> {\n requirePermission(permissions, 'storage:write', 'storage.delete')\n return storageImpl.delete(key)\n },\n async list(): Promise<string[]> {\n requirePermission(permissions, 'storage:read', 'storage.list')\n return storageImpl.list()\n },\n getDataDir(): string {\n requirePermission(permissions, 'storage:read', 'storage.getDataDir')\n return storageImpl.getDataDir()\n },\n }\n\n const ctx: PluginContext & { cleanup(): void } = {\n pluginName,\n pluginConfig,\n log,\n storage,\n\n on(event: string, handler: (...args: unknown[]) => void): void {\n requirePermission(permissions, 'events:read', 'on()')\n eventBus.on(event, handler)\n registeredListeners.push({ event, handler })\n },\n\n off(event: string, handler: (...args: unknown[]) => void): void {\n requirePermission(permissions, 'events:read', 'off()')\n eventBus.off(event, handler)\n const idx = registeredListeners.findIndex((l) => l.event === event && l.handler === handler)\n if (idx >= 0) registeredListeners.splice(idx, 1)\n },\n\n emit(event: string, payload: unknown): void {\n requirePermission(permissions, 'events:emit', 'emit()')\n eventBus.emit(event, payload)\n },\n\n registerMiddleware<H extends MiddlewareHook>(hook: H, middlewareOpts: MiddlewareOptions<MiddlewarePayloadMap[H]>): void {\n requirePermission(permissions, 'middleware:register', 'registerMiddleware()')\n middlewareChain.add(hook, pluginName, middlewareOpts as { priority?: number; handler: Function })\n },\n\n registerService<T>(name: string, implementation: T): void {\n requirePermission(permissions, 'services:register', 'registerService()')\n serviceRegistry.register(name, implementation, pluginName)\n },\n\n getService<T>(name: string): T | undefined {\n requirePermission(permissions, 'services:use', 'getService()')\n return serviceRegistry.get<T>(name)\n },\n\n registerCommand(def: CommandDef): void {\n requirePermission(permissions, 'commands:register', 'registerCommand()')\n registeredCommands.push(def)\n const registry = serviceRegistry.get<{ register(def: CommandDef, pluginName: string): void }>('command-registry')\n if (registry && typeof registry.register === 'function') {\n registry.register(def, pluginName)\n log.debug(`Command '/${def.name}' registered`)\n }\n },\n\n async sendMessage(_sessionId: string, _content: OutgoingMessage): Promise<void> {\n requirePermission(permissions, 'services:use', 'sendMessage()')\n // Delegate to message routing service\n const router = serviceRegistry.get<{ send(sessionId: string, content: OutgoingMessage): Promise<void> }>('message-router')\n if (router) {\n await router.send(_sessionId, _content)\n }\n },\n\n get sessions() {\n requirePermission(permissions, 'kernel:access', 'sessions')\n return sessions as any\n },\n\n get config() {\n requirePermission(permissions, 'kernel:access', 'config')\n return config as any\n },\n\n get eventBus() {\n requirePermission(permissions, 'kernel:access', 'eventBus')\n return eventBus as any\n },\n\n get core() {\n requirePermission(permissions, 'kernel:access', 'core')\n return core\n },\n\n instanceRoot,\n\n cleanup(): void {\n // Remove all event listeners registered by this plugin\n for (const { event, handler } of registeredListeners) {\n eventBus.off(event, handler)\n }\n registeredListeners.length = 0\n\n // Remove all middleware registered by this plugin\n middlewareChain.removeAll(pluginName)\n\n // Unregister services owned by this plugin\n serviceRegistry.unregisterByPlugin(pluginName)\n\n // Unregister commands from CommandRegistry\n const cmdRegistry = serviceRegistry.get<{ unregisterByPlugin(name: string): void }>('command-registry')\n if (cmdRegistry && typeof cmdRegistry.unregisterByPlugin === 'function') {\n cmdRegistry.unregisterByPlugin(pluginName)\n }\n\n // Clear commands\n registeredCommands.length = 0\n },\n }\n\n return ctx\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { PluginStorage } from './types.js'\n\nexport class PluginStorageImpl implements PluginStorage {\n private readonly kvPath: string\n private readonly dataDir: string\n private writeChain: Promise<void> = Promise.resolve()\n\n constructor(baseDir: string) {\n this.dataDir = path.join(baseDir, 'data')\n this.kvPath = path.join(baseDir, 'kv.json')\n fs.mkdirSync(baseDir, { recursive: true })\n }\n\n private readKv(): Record<string, unknown> {\n try {\n const raw = fs.readFileSync(this.kvPath, 'utf-8')\n return JSON.parse(raw) as Record<string, unknown>\n } catch {\n return {}\n }\n }\n\n private writeKv(data: Record<string, unknown>): void {\n fs.writeFileSync(this.kvPath, JSON.stringify(data), 'utf-8')\n }\n\n async get<T>(key: string): Promise<T | undefined> {\n const data = this.readKv()\n return key in data ? (data[key] as T) : undefined\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n this.writeChain = this.writeChain.then(() => {\n const data = this.readKv()\n data[key] = value\n this.writeKv(data)\n })\n return this.writeChain\n }\n\n async delete(key: string): Promise<void> {\n this.writeChain = this.writeChain.then(() => {\n const data = this.readKv()\n delete data[key]\n this.writeKv(data)\n })\n return this.writeChain\n }\n\n async list(): Promise<string[]> {\n return Object.keys(this.readKv())\n }\n\n getDataDir(): string {\n fs.mkdirSync(this.dataDir, { recursive: true })\n return this.dataDir\n }\n}\n","import { resolveLoadOrder } from './plugin-loader.js'\nimport { ServiceRegistry } from './service-registry.js'\nimport { MiddlewareChain } from './middleware-chain.js'\nimport { ErrorTracker } from './error-tracker.js'\nimport { createPluginContext } from './plugin-context.js'\nimport type { OpenACPPlugin, EventBus, Logger, MigrateContext } from './types.js'\nimport type { SettingsManager } from './settings-manager.js'\nimport type { PluginRegistry } from './plugin-registry.js'\n\nconst SETUP_TIMEOUT_MS = 30_000\nconst TEARDOWN_TIMEOUT_MS = 10_000\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`Timeout: ${label} exceeded ${ms}ms`)), ms)\n if (typeof timer === 'object' && timer !== null && 'unref' in timer) {\n ;(timer as NodeJS.Timeout).unref()\n }\n promise.then(resolve, reject).finally(() => clearTimeout(timer))\n })\n}\n\nfunction resolvePluginConfig(pluginName: string, configManager: unknown): Record<string, unknown> {\n try {\n const allConfig = (configManager as any)?.get?.() ?? {}\n // Try new format: plugins.builtin['@openacp/speech'].config\n const pluginEntry = allConfig.plugins?.builtin?.[pluginName]\n if (pluginEntry?.config && Object.keys(pluginEntry.config).length > 0) {\n return pluginEntry.config\n }\n // @deprecated Legacy config path mapping — kept for backward compat with pre-plugin configs.\n // New plugins should use plugins.builtin['<name>'].config format. Remove when all users have migrated.\n const legacyMap: Record<string, string> = {\n '@openacp/security': 'security',\n '@openacp/speech': 'speech',\n '@openacp/tunnel': 'tunnel',\n '@openacp/usage': 'usage',\n '@openacp/file-service': 'files',\n '@openacp/api-server': 'api',\n '@openacp/telegram': 'channels.telegram',\n '@openacp/discord': 'channels.discord',\n '@openacp/adapter-discord': 'channels.discord',\n '@openacp/plugin-discord': 'channels.discord', // alias for old name\n '@openacp/slack': 'channels.slack',\n }\n const legacyKey = legacyMap[pluginName]\n if (legacyKey) {\n const parts = legacyKey.split('.')\n let obj: any = allConfig\n for (const p of parts) obj = obj?.[p]\n if (obj && typeof obj === 'object') return { ...obj }\n }\n } catch {\n // Gracefully degrade — return empty config\n }\n return {}\n}\n\nexport interface LifecycleManagerOpts {\n serviceRegistry?: ServiceRegistry\n middlewareChain?: MiddlewareChain\n errorTracker?: ErrorTracker\n eventBus?: EventBus & {\n on(event: string, handler: (...args: unknown[]) => void): void\n off(event: string, handler: (...args: unknown[]) => void): void\n emit(event: string, payload: unknown): void\n }\n storagePath?: string\n sessions?: unknown\n config?: unknown\n core?: unknown\n log?: Logger\n settingsManager?: SettingsManager\n pluginRegistry?: PluginRegistry\n /** Root directory for this OpenACP instance (default: ~/.openacp) */\n instanceRoot?: string\n}\n\nexport class LifecycleManager {\n readonly serviceRegistry: ServiceRegistry\n readonly middlewareChain: MiddlewareChain\n readonly errorTracker: ErrorTracker\n\n private eventBus: LifecycleManagerOpts['eventBus']\n private storagePath: string\n private sessions: unknown\n private config: unknown\n private core: unknown\n private log: Logger | undefined\n settingsManager: SettingsManager | undefined\n private pluginRegistry: PluginRegistry | undefined\n private instanceRoot: string | undefined\n\n private contexts = new Map<string, ReturnType<typeof createPluginContext>>()\n private loadOrder: OpenACPPlugin[] = []\n private _loaded = new Set<string>()\n private _failed = new Set<string>()\n\n get loadedPlugins(): string[] {\n return [...this._loaded]\n }\n\n get failedPlugins(): string[] {\n return [...this._failed]\n }\n\n get registry(): PluginRegistry | undefined {\n return this.pluginRegistry\n }\n\n constructor(opts?: LifecycleManagerOpts) {\n this.serviceRegistry = opts?.serviceRegistry ?? new ServiceRegistry()\n this.middlewareChain = opts?.middlewareChain ?? new MiddlewareChain()\n this.errorTracker = opts?.errorTracker ?? new ErrorTracker()\n this.eventBus = opts?.eventBus ?? {\n on() {},\n off() {},\n emit() {},\n }\n this.storagePath = opts?.storagePath ?? '/tmp/openacp-plugins'\n this.sessions = opts?.sessions ?? {}\n this.config = opts?.config ?? {}\n this.core = opts?.core\n this.log = opts?.log\n this.settingsManager = opts?.settingsManager\n this.pluginRegistry = opts?.pluginRegistry\n this.instanceRoot = opts?.instanceRoot\n }\n\n private getPluginLogger(pluginName: string): Logger {\n if (this.log && typeof (this.log as any).child === 'function') {\n return (this.log as any).child({ plugin: pluginName })\n }\n return this.log ?? { trace() {}, debug() {}, info() {}, warn() {}, error() {}, fatal() {}, child() { return this } } as Logger\n }\n\n async boot(plugins: OpenACPPlugin[]): Promise<void> {\n // Resolve load order via topological sort.\n // resolveLoadOrder will skip plugins whose dependencies are missing entirely\n // (not present in the input list). But we also need to handle runtime setup failures.\n // Include already-loaded plugins so dependency checks pass for late-booted plugins\n // (e.g., dev plugins booted after core plugins).\n const newNames = new Set(plugins.map(p => p.name))\n const allForResolution = [...this.loadOrder.filter(p => !newNames.has(p.name)), ...plugins]\n\n let sorted: OpenACPPlugin[]\n try {\n sorted = resolveLoadOrder(allForResolution)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n this.log?.error(`Plugin dependency resolution failed: ${error.message}`)\n for (const p of plugins) {\n this._failed.add(p.name)\n }\n return\n }\n\n // Only boot new plugins (already-loaded ones were included just for dependency resolution)\n sorted = sorted.filter(p => newNames.has(p.name))\n\n // Append to existing loadOrder (don't overwrite — hot-reload boots single plugins)\n for (const p of sorted) {\n if (!this.loadOrder.some(existing => existing.name === p.name)) {\n this.loadOrder.push(p)\n } else {\n // Replace in-place (hot-reload case: plugin was unloaded then re-booted)\n const idx = this.loadOrder.findIndex(existing => existing.name === p.name)\n this.loadOrder[idx] = p\n }\n }\n\n for (const plugin of sorted) {\n // Check if any required dependency failed at runtime\n if (plugin.pluginDependencies) {\n const depFailed = Object.keys(plugin.pluginDependencies).some(\n (dep) => this._failed.has(dep),\n )\n if (depFailed) {\n this._failed.add(plugin.name)\n continue\n }\n }\n\n // Check if disabled in registry\n const registryEntry = this.pluginRegistry?.get(plugin.name)\n if (registryEntry && registryEntry.enabled === false) {\n this.eventBus?.emit('plugin:disabled', { name: plugin.name })\n continue\n }\n\n // Check version mismatch → migrate\n if (registryEntry && plugin.migrate && registryEntry.version !== plugin.version && this.settingsManager) {\n try {\n const oldSettings = await this.settingsManager.loadSettings(plugin.name)\n const pluginLog = this.getPluginLogger(plugin.name)\n const migrateCtx: MigrateContext = {\n pluginName: plugin.name,\n settings: this.settingsManager.createAPI(plugin.name),\n log: pluginLog,\n }\n const newSettings = await withTimeout(\n plugin.migrate(migrateCtx, oldSettings, registryEntry.version),\n SETUP_TIMEOUT_MS,\n `${plugin.name}.migrate()`,\n )\n if (newSettings && typeof newSettings === 'object') {\n await migrateCtx.settings.setAll(newSettings as Record<string, unknown>)\n }\n this.pluginRegistry!.updateVersion(plugin.name, plugin.version)\n await this.pluginRegistry!.save()\n } catch (err) {\n this.getPluginLogger(plugin.name).warn(`Migration failed, continuing with old settings: ${err}`)\n }\n }\n\n // Resolve config: prefer settings.json, fallback to legacy\n let pluginConfig: Record<string, unknown>\n if (this.settingsManager) {\n pluginConfig = await this.settingsManager.loadSettings(plugin.name)\n const settingsPath = this.settingsManager.getSettingsPath(plugin.name)\n this.getPluginLogger(plugin.name).debug(`Settings loaded from ${settingsPath}: ${Object.keys(pluginConfig).length} keys`)\n if (Object.keys(pluginConfig).length === 0) {\n pluginConfig = resolvePluginConfig(plugin.name, this.config)\n }\n } else {\n pluginConfig = resolvePluginConfig(plugin.name, this.config)\n this.getPluginLogger(plugin.name).debug('No settingsManager, using legacy config')\n }\n\n // Validate settings against schema if plugin provides one\n if (plugin.settingsSchema && this.settingsManager) {\n const validation = this.settingsManager.validateSettings(plugin.name, pluginConfig, plugin.settingsSchema)\n if (!validation.valid) {\n this._failed.add(plugin.name)\n this.getPluginLogger(plugin.name).error(`Settings validation failed: ${validation.errors?.join('; ')}`)\n this.eventBus?.emit('plugin:failed', { name: plugin.name, error: `Settings validation failed: ${validation.errors?.join('; ')}` })\n continue\n }\n }\n\n // Create context for this plugin\n const ctx = createPluginContext({\n pluginName: plugin.name,\n pluginConfig,\n permissions: plugin.permissions ?? [],\n serviceRegistry: this.serviceRegistry,\n middlewareChain: this.middlewareChain,\n errorTracker: this.errorTracker,\n eventBus: this.eventBus!,\n storagePath: `${this.storagePath}/${plugin.name}`,\n sessions: this.sessions,\n config: this.config,\n core: this.core,\n log: this.log,\n instanceRoot: this.instanceRoot,\n })\n\n try {\n await withTimeout(plugin.setup(ctx), SETUP_TIMEOUT_MS, `${plugin.name}.setup()`)\n this.contexts.set(plugin.name, ctx)\n this._loaded.add(plugin.name)\n this.eventBus?.emit('plugin:loaded', { name: plugin.name, version: plugin.version })\n } catch (err) {\n this._failed.add(plugin.name)\n ctx.cleanup()\n this.getPluginLogger(plugin.name).error(`setup() failed: ${err}`)\n this.eventBus?.emit('plugin:failed', { name: plugin.name, error: String(err) })\n }\n }\n }\n\n async unloadPlugin(name: string): Promise<void> {\n if (!this._loaded.has(name)) return\n\n const plugin = this.loadOrder.find(p => p.name === name)\n\n if (plugin?.teardown) {\n try {\n await withTimeout(plugin.teardown(), TEARDOWN_TIMEOUT_MS, `${name}.teardown()`)\n } catch {\n // Swallow teardown errors\n }\n }\n\n const ctx = this.contexts.get(name)\n if (ctx) {\n ctx.cleanup()\n this.contexts.delete(name)\n }\n\n this._loaded.delete(name)\n this._failed.delete(name)\n this.loadOrder = this.loadOrder.filter(p => p.name !== name)\n\n this.eventBus?.emit('plugin:unloaded', { name })\n }\n\n async shutdown(): Promise<void> {\n // Teardown in reverse load order\n const reversed = [...this.loadOrder].reverse()\n\n for (const plugin of reversed) {\n if (!this._loaded.has(plugin.name)) continue\n\n if (plugin.teardown) {\n try {\n await withTimeout(plugin.teardown(), TEARDOWN_TIMEOUT_MS, `${plugin.name}.teardown()`)\n } catch {\n // Swallow teardown errors — graceful shutdown\n }\n }\n\n // Clean up the context\n const ctx = this.contexts.get(plugin.name)\n if (ctx) {\n ctx.cleanup()\n this.contexts.delete(plugin.name)\n }\n\n this.eventBus?.emit('plugin:unloaded', { name: plugin.name })\n }\n\n this._loaded.clear()\n this.loadOrder = []\n }\n}\n","import type { CommandDef, CommandArgs, CommandResponse } from './plugin/types.js'\n\ninterface RegisteredCommand extends CommandDef {\n /** Scope extracted from pluginName, e.g. '@openacp/speech' → 'speech' */\n scope?: string\n}\n\n/**\n * Central command registry with namespace resolution and adapter-specific overrides.\n *\n * Namespace rules:\n * - System commands always own the short name.\n * - Among plugins, the first to register wins the short name.\n * - Every plugin command also gets a qualified name: `scope:name`.\n * - Adapter plugins (@openacp/telegram, @openacp/discord)\n * registering a command that already exists → stored as an override\n * keyed by `channelId:commandName`, used when channelId matches.\n */\nexport class CommandRegistry {\n /** Main registry: short names + qualified names → RegisteredCommand */\n private commands = new Map<string, RegisteredCommand>()\n\n /** Adapter-specific overrides: `channelId:commandName` → RegisteredCommand */\n private overrides = new Map<string, RegisteredCommand>()\n\n private static ADAPTER_SCOPES = new Set(['telegram', 'discord'])\n\n /**\n * Register a command definition.\n * @param def - Command definition\n * @param pluginName - Plugin that owns the command (set automatically by PluginContext)\n */\n register(def: CommandDef, pluginName?: string): void {\n const cmd: RegisteredCommand = {\n ...def,\n pluginName: pluginName ?? def.pluginName,\n }\n\n if (pluginName) {\n cmd.scope = CommandRegistry.extractScope(pluginName)\n }\n\n const qualifiedName = cmd.scope ? `${cmd.scope}:${cmd.name}` : undefined\n\n // Check if this is an adapter plugin overriding an existing command\n if (cmd.scope && CommandRegistry.ADAPTER_SCOPES.has(cmd.scope) && this.commands.has(cmd.name)) {\n // Store as adapter override\n this.overrides.set(`${cmd.scope}:${cmd.name}`, cmd)\n return\n }\n\n // Always register qualified name if available\n if (qualifiedName) {\n this.commands.set(qualifiedName, cmd)\n }\n\n // Short name logic\n if (this.commands.has(cmd.name)) {\n const existing = this.commands.get(cmd.name)!\n // System commands always win the short name\n if (existing.category === 'system') {\n // Plugin gets qualified name only (already registered above)\n return\n }\n // First plugin wins short name; later plugins get qualified only\n return\n }\n\n // No conflict — register short name\n this.commands.set(cmd.name, cmd)\n }\n\n /** Retrieve a command by name (short or qualified). */\n get(name: string): RegisteredCommand | undefined {\n return this.commands.get(name)\n }\n\n /** Remove a command by name (short or qualified). Also removes its qualified name entry. */\n unregister(name: string): void {\n const cmd = this.commands.get(name)\n if (!cmd) return\n this.commands.delete(name)\n if (cmd.scope) {\n // If we deleted by short name, also delete qualified name\n this.commands.delete(`${cmd.scope}:${cmd.name}`)\n // If we deleted by qualified name, also delete short name\n this.commands.delete(cmd.name)\n }\n }\n\n /** Remove all commands registered by a given plugin. */\n unregisterByPlugin(pluginName: string): void {\n const toDelete: string[] = []\n\n for (const [key, cmd] of this.commands) {\n if (cmd.pluginName === pluginName) {\n toDelete.push(key)\n }\n }\n\n for (const key of toDelete) {\n this.commands.delete(key)\n }\n\n // Also remove adapter overrides\n for (const [key, cmd] of this.overrides) {\n if (cmd.pluginName === pluginName) {\n this.overrides.delete(key)\n }\n }\n }\n\n /** Return all unique commands (deduplicated — each command appears once). */\n getAll(): RegisteredCommand[] {\n const seen = new Set<RegisteredCommand>()\n for (const cmd of this.commands.values()) {\n seen.add(cmd)\n }\n return [...seen]\n }\n\n /** Filter commands by category. */\n getByCategory(category: 'system' | 'plugin'): RegisteredCommand[] {\n return this.getAll().filter((cmd) => cmd.category === category)\n }\n\n /**\n * Parse and execute a command string.\n * @param commandString - Full command string, e.g. \"/greet hello world\"\n * @param baseArgs - Base arguments (channelId, userId, etc.)\n * @returns CommandResponse\n */\n async execute(commandString: string, baseArgs: CommandArgs): Promise<CommandResponse> {\n // Parse command name and raw args\n const trimmed = commandString.trim()\n const spaceIdx = trimmed.indexOf(' ')\n const rawCmd = spaceIdx === -1 ? trimmed.slice(1) : trimmed.slice(1, spaceIdx)\n const cmdName = rawCmd.split(\"@\")[0]\n const rawArgs = spaceIdx === -1 ? '' : trimmed.slice(spaceIdx + 1)\n\n // Check for adapter-specific override first\n const overrideKey = `${baseArgs.channelId}:${cmdName}`\n const override = this.overrides.get(overrideKey)\n\n const cmd = override ?? this.commands.get(cmdName)\n\n if (!cmd) {\n return { type: 'error', message: `Unknown command: /${cmdName}` }\n }\n\n const args: CommandArgs = {\n ...baseArgs,\n raw: rawArgs,\n }\n\n try {\n const result = await cmd.handler(args)\n if (result === undefined || result === null) {\n return { type: 'silent' }\n }\n return result\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return { type: 'error', message: `Command /${cmdName} failed: ${message}` }\n }\n }\n\n /** Extract scope from plugin name: '@openacp/speech' → 'speech', 'my-plugin' → 'my-plugin' */\n static extractScope(pluginName: string): string {\n const slashIdx = pluginName.lastIndexOf('/')\n if (slashIdx !== -1) {\n return pluginName.slice(slashIdx + 1)\n }\n return pluginName\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DoctorCheck, DoctorContext, DoctorReport, CategoryResult, PendingFix, CheckResult } from \"./types.js\";\nimport { ConfigManager, expandHome } from \"../config/config.js\";\nimport { getGlobalRoot } from \"../instance/instance-context.js\";\n\nimport { configCheck } from \"./checks/config.js\";\nimport { agentsCheck } from \"./checks/agents.js\";\nimport { telegramCheck } from \"./checks/telegram.js\";\nimport { storageCheck } from \"./checks/storage.js\";\nimport { workspaceCheck } from \"./checks/workspace.js\";\nimport { pluginsCheck } from \"./checks/plugins.js\";\nimport { daemonCheck } from \"./checks/daemon.js\";\nimport { tunnelCheck } from \"./checks/tunnel.js\";\n\nconst ALL_CHECKS: DoctorCheck[] = [\n configCheck,\n agentsCheck,\n telegramCheck,\n storageCheck,\n workspaceCheck,\n pluginsCheck,\n daemonCheck,\n tunnelCheck,\n];\n\nconst CHECK_TIMEOUT_MS = 10_000;\n\nexport class DoctorEngine {\n private dryRun: boolean;\n private dataDir: string;\n\n constructor(options?: { dryRun?: boolean; dataDir?: string }) {\n this.dryRun = options?.dryRun ?? false;\n this.dataDir = options?.dataDir ?? getGlobalRoot();\n }\n\n async runAll(): Promise<DoctorReport> {\n const ctx = await this.buildContext();\n const checks = [...ALL_CHECKS].sort((a, b) => a.order - b.order);\n\n const categories: CategoryResult[] = [];\n const pendingFixes: PendingFix[] = [];\n const summary = { passed: 0, warnings: 0, failed: 0, fixed: 0 };\n\n for (const check of checks) {\n let results: CheckResult[];\n try {\n results = await Promise.race([\n check.run(ctx),\n new Promise<CheckResult[]>((_, reject) =>\n setTimeout(() => reject(new Error(\"timeout\")), CHECK_TIMEOUT_MS),\n ),\n ]);\n } catch {\n results = [{ status: \"fail\", message: `${check.name} check timed out` }];\n }\n\n for (const result of results) {\n if (result.fixable && result.fix) {\n if (result.fixRisk === \"safe\" && !this.dryRun) {\n try {\n const fixResult = await result.fix();\n if (fixResult.success) {\n result.message += ` → Fixed (${fixResult.message})`;\n result.status = \"warn\";\n delete result.fix;\n summary.fixed++;\n }\n } catch {\n // Fix failed, leave as-is\n }\n } else if (result.fixRisk === \"risky\") {\n pendingFixes.push({\n category: check.name,\n message: result.message,\n fix: result.fix,\n });\n }\n }\n\n if (result.status === \"pass\") summary.passed++;\n else if (result.status === \"warn\") summary.warnings++;\n else if (result.status === \"fail\") summary.failed++;\n }\n\n categories.push({ name: check.name, results });\n }\n\n return { categories, summary, pendingFixes };\n }\n\n private async buildContext(): Promise<DoctorContext> {\n const dataDir = this.dataDir;\n const configPath = process.env.OPENACP_CONFIG_PATH || path.join(dataDir, \"config.json\");\n\n let config = null;\n let rawConfig: unknown = null;\n\n try {\n const content = fs.readFileSync(configPath, \"utf-8\");\n rawConfig = JSON.parse(content);\n const cm = new ConfigManager(configPath);\n await cm.load();\n config = cm.get();\n } catch {\n // Config may not exist or may be invalid — checks will handle this\n }\n\n const logsDir = config\n ? expandHome(config.logging.logDir)\n : path.join(dataDir, \"logs\");\n\n return {\n config,\n rawConfig,\n configPath,\n dataDir,\n sessionsPath: path.join(dataDir, \"sessions.json\"),\n pidPath: path.join(dataDir, \"openacp.pid\"),\n portFilePath: path.join(dataDir, \"api.port\"),\n pluginsDir: path.join(dataDir, \"plugins\"),\n logsDir,\n };\n }\n}\n\nexport type { DoctorReport, CategoryResult, PendingFix, CheckResult, DoctorContext } from \"./types.js\";\n","import * as fs from \"node:fs\";\nimport { ConfigSchema } from \"../../config/config.js\";\nimport { applyMigrations } from \"../../config/config-migrations.js\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const configCheck: DoctorCheck = {\n name: \"Config\",\n order: 1,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.configPath)) {\n results.push({ status: \"fail\", message: \"Config file not found\" });\n return results;\n }\n results.push({ status: \"pass\", message: \"Config file exists\" });\n\n let raw: Record<string, unknown>;\n try {\n raw = JSON.parse(fs.readFileSync(ctx.configPath, \"utf-8\"));\n } catch (err) {\n results.push({\n status: \"fail\",\n message: `Config JSON invalid: ${err instanceof Error ? err.message : String(err)}`,\n });\n return results;\n }\n results.push({ status: \"pass\", message: \"JSON valid\" });\n\n const testRaw = structuredClone(raw);\n const { changed } = applyMigrations(testRaw);\n if (changed) {\n results.push({\n status: \"warn\",\n message: \"Pending config migrations\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n applyMigrations(raw);\n fs.writeFileSync(ctx.configPath, JSON.stringify(raw, null, 2));\n return { success: true, message: \"applied migrations\" };\n },\n });\n }\n\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n for (const issue of result.error.issues) {\n results.push({\n status: \"fail\",\n message: `Validation: ${issue.path.join(\".\")} — ${issue.message}`,\n });\n }\n } else {\n results.push({ status: \"pass\", message: \"Schema valid\" });\n }\n\n return results;\n },\n};\n","import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nfunction commandExists(cmd: string): boolean {\n try {\n execFileSync(\"which\", [cmd], { stdio: \"pipe\" });\n return true;\n } catch {\n // not in PATH\n }\n let dir = process.cwd();\n while (true) {\n const binPath = path.join(dir, \"node_modules\", \".bin\", cmd);\n if (fs.existsSync(binPath)) return true;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nexport const agentsCheck: DoctorCheck = {\n name: \"Agents\",\n order: 2,\n async run(ctx) {\n const results: CheckResult[] = [];\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check agents — config not loaded\" });\n return results;\n }\n\n const agents = ctx.config.agents;\n const defaultAgent = ctx.config.defaultAgent;\n\n if (!agents[defaultAgent]) {\n results.push({\n status: \"fail\",\n message: `Default agent \"${defaultAgent}\" not found in agents config`,\n });\n }\n\n for (const [name, agent] of Object.entries(agents)) {\n const isDefault = name === defaultAgent;\n if (commandExists(agent.command)) {\n results.push({\n status: \"pass\",\n message: `${agent.command} found${isDefault ? \" (default)\" : \"\"}`,\n });\n } else {\n results.push({\n status: isDefault ? \"fail\" : \"warn\",\n message: `${agent.command} not found in PATH${isDefault ? \" (default agent!)\" : \"\"}`,\n });\n }\n }\n\n return results;\n },\n};\n","import type { DoctorCheck, CheckResult } from \"../types.js\";\n\nconst BOT_TOKEN_REGEX = /^\\d+:[A-Za-z0-9_-]{35,}$/;\n\nexport const telegramCheck: DoctorCheck = {\n name: \"Telegram\",\n order: 3,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check Telegram — config not loaded\" });\n return results;\n }\n\n const tgConfig = ctx.config.channels.telegram as Record<string, unknown> | undefined;\n if (!tgConfig || !tgConfig.enabled) {\n results.push({ status: \"pass\", message: \"Telegram not enabled (skipped)\" });\n return results;\n }\n\n const botToken = tgConfig.botToken as string | undefined;\n const chatId = tgConfig.chatId as number | undefined;\n\n if (!botToken || !BOT_TOKEN_REGEX.test(botToken)) {\n results.push({ status: \"fail\", message: \"Bot token format invalid\" });\n return results;\n }\n results.push({ status: \"pass\", message: \"Bot token format valid\" });\n\n let botId: number | undefined;\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getMe`);\n const data = (await res.json()) as { ok: boolean; result?: { id: number; username: string }; description?: string };\n if (data.ok && data.result) {\n botId = data.result.id;\n results.push({ status: \"pass\", message: `Bot token valid (@${data.result.username})` });\n } else {\n results.push({ status: \"fail\", message: `Bot token rejected: ${data.description || \"unknown error\"}` });\n return results;\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Cannot reach Telegram API: ${err instanceof Error ? err.message : String(err)}` });\n return results;\n }\n\n if (!chatId || chatId === 0) {\n results.push({ status: \"fail\", message: \"Chat ID not configured\" });\n return results;\n }\n\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { type: string; is_forum?: boolean; title: string };\n description?: string;\n };\n if (!data.ok || !data.result) {\n results.push({ status: \"fail\", message: `Chat ID invalid: ${data.description || \"unknown error\"}` });\n return results;\n }\n if (data.result.type !== \"supergroup\") {\n results.push({ status: \"fail\", message: `Chat is \"${data.result.type}\", must be a supergroup` });\n return results;\n }\n if (!data.result.is_forum) {\n results.push({ status: \"warn\", message: \"Chat does not have topics enabled\" });\n } else {\n results.push({ status: \"pass\", message: `Chat is supergroup with topics (\"${data.result.title}\")` });\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Cannot validate chat: ${err instanceof Error ? err.message : String(err)}` });\n return results;\n }\n\n try {\n const res = await fetch(`https://api.telegram.org/bot${botToken}/getChatMember`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId, user_id: botId }),\n });\n const data = (await res.json()) as { ok: boolean; result?: { status: string }; description?: string };\n if (!data.ok || !data.result) {\n results.push({ status: \"fail\", message: `Cannot check bot membership: ${data.description || \"unknown\"}` });\n } else if (data.result.status === \"administrator\" || data.result.status === \"creator\") {\n results.push({ status: \"pass\", message: \"Bot is admin in group\" });\n } else {\n results.push({\n status: \"fail\",\n message: `Bot is \"${data.result.status}\" — must be admin. Promote bot in group settings.`,\n });\n }\n } catch (err) {\n results.push({ status: \"fail\", message: `Admin check failed: ${err instanceof Error ? err.message : String(err)}` });\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const storageCheck: DoctorCheck = {\n name: \"Storage\",\n order: 4,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.dataDir)) {\n results.push({\n status: \"fail\",\n message: \"Data directory ~/.openacp does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.dataDir, { recursive: true });\n return { success: true, message: \"created directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(ctx.dataDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: \"Data directory exists and writable\" });\n } catch {\n results.push({ status: \"fail\", message: \"Data directory not writable\" });\n }\n }\n\n if (fs.existsSync(ctx.sessionsPath)) {\n try {\n const content = fs.readFileSync(ctx.sessionsPath, \"utf-8\");\n const data = JSON.parse(content);\n if (typeof data === \"object\" && data !== null && \"sessions\" in data) {\n results.push({ status: \"pass\", message: \"Sessions file valid\" });\n } else {\n results.push({\n status: \"fail\",\n message: \"Sessions file has invalid structure\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(ctx.sessionsPath, JSON.stringify({ version: 1, sessions: {} }, null, 2));\n return { success: true, message: \"reset sessions file\" };\n },\n });\n }\n } catch {\n results.push({\n status: \"fail\",\n message: \"Sessions file corrupt (invalid JSON)\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(ctx.sessionsPath, JSON.stringify({ version: 1, sessions: {} }, null, 2));\n return { success: true, message: \"reset sessions file\" };\n },\n });\n }\n } else {\n results.push({ status: \"pass\", message: \"Sessions file not present yet (created on first session)\" });\n }\n\n if (!fs.existsSync(ctx.logsDir)) {\n results.push({\n status: \"warn\",\n message: \"Log directory does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.logsDir, { recursive: true });\n return { success: true, message: \"created log directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(ctx.logsDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: \"Log directory exists and writable\" });\n } catch {\n results.push({ status: \"fail\", message: \"Log directory not writable\" });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport { expandHome } from \"../../config/config.js\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const workspaceCheck: DoctorCheck = {\n name: \"Workspace\",\n order: 5,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check workspace — config not loaded\" });\n return results;\n }\n\n const baseDir = expandHome(ctx.config.workspace.baseDir);\n\n if (!fs.existsSync(baseDir)) {\n results.push({\n status: \"warn\",\n message: `Workspace directory does not exist: ${baseDir}`,\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(baseDir, { recursive: true });\n return { success: true, message: \"created directory\" };\n },\n });\n } else {\n try {\n fs.accessSync(baseDir, fs.constants.W_OK);\n results.push({ status: \"pass\", message: `Workspace directory exists: ${baseDir}` });\n } catch {\n results.push({ status: \"fail\", message: `Workspace directory not writable: ${baseDir}` });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const pluginsCheck: DoctorCheck = {\n name: \"Plugins\",\n order: 6,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!fs.existsSync(ctx.pluginsDir)) {\n results.push({\n status: \"warn\",\n message: \"Plugins directory does not exist\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.mkdirSync(ctx.pluginsDir, { recursive: true });\n fs.writeFileSync(\n path.join(ctx.pluginsDir, \"package.json\"),\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"initialized plugins directory\" };\n },\n });\n return results;\n }\n results.push({ status: \"pass\", message: \"Plugins directory exists\" });\n\n const pkgPath = path.join(ctx.pluginsDir, \"package.json\");\n if (!fs.existsSync(pkgPath)) {\n results.push({\n status: \"warn\",\n message: \"Plugins package.json missing\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.writeFileSync(\n pkgPath,\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"created package.json\" };\n },\n });\n return results;\n }\n\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const deps = pkg.dependencies || {};\n const count = Object.keys(deps).length;\n results.push({ status: \"pass\", message: `Plugins package.json valid (${count} plugins)` });\n } catch {\n results.push({\n status: \"fail\",\n message: \"Plugins package.json is invalid JSON\",\n fixable: true,\n fixRisk: \"risky\",\n fix: async () => {\n fs.writeFileSync(\n pkgPath,\n JSON.stringify({ name: \"openacp-plugins\", private: true, dependencies: {} }, null, 2),\n );\n return { success: true, message: \"reset package.json\" };\n },\n });\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction checkPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", () => resolve(true));\n server.once(\"listening\", () => {\n server.close();\n resolve(false);\n });\n server.listen(port, \"127.0.0.1\");\n });\n}\n\nexport const daemonCheck: DoctorCheck = {\n name: \"Daemon\",\n order: 7,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (fs.existsSync(ctx.pidPath)) {\n const content = fs.readFileSync(ctx.pidPath, \"utf-8\").trim();\n const pid = parseInt(content, 10);\n if (isNaN(pid)) {\n results.push({\n status: \"warn\",\n message: \"PID file contains invalid data\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.pidPath);\n return { success: true, message: \"removed invalid PID file\" };\n },\n });\n } else if (!isProcessAlive(pid)) {\n results.push({\n status: \"warn\",\n message: `Stale PID file (PID ${pid} not running)`,\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.pidPath);\n return { success: true, message: \"removed stale PID file\" };\n },\n });\n } else {\n results.push({ status: \"pass\", message: `Daemon running (PID ${pid})` });\n }\n }\n\n if (fs.existsSync(ctx.portFilePath)) {\n const content = fs.readFileSync(ctx.portFilePath, \"utf-8\").trim();\n const port = parseInt(content, 10);\n if (isNaN(port)) {\n results.push({\n status: \"warn\",\n message: \"Port file contains invalid data\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n fs.unlinkSync(ctx.portFilePath);\n return { success: true, message: \"removed invalid port file\" };\n },\n });\n } else {\n results.push({ status: \"pass\", message: `Port file valid (port ${port})` });\n }\n }\n\n if (ctx.config) {\n const apiPort = ctx.config.api.port;\n const inUse = await checkPortInUse(apiPort);\n if (inUse) {\n if (fs.existsSync(ctx.pidPath)) {\n const pid = parseInt(fs.readFileSync(ctx.pidPath, \"utf-8\").trim(), 10);\n if (!isNaN(pid) && isProcessAlive(pid)) {\n results.push({ status: \"pass\", message: `API port ${apiPort} in use by OpenACP daemon` });\n } else {\n results.push({ status: \"warn\", message: `API port ${apiPort} in use by another process` });\n }\n } else {\n results.push({ status: \"warn\", message: `API port ${apiPort} in use by another process` });\n }\n } else {\n results.push({ status: \"pass\", message: `API port ${apiPort} available` });\n }\n }\n\n return results;\n },\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\nimport type { DoctorCheck, CheckResult } from \"../types.js\";\n\nexport const tunnelCheck: DoctorCheck = {\n name: \"Tunnel\",\n order: 8,\n async run(ctx) {\n const results: CheckResult[] = [];\n\n if (!ctx.config) {\n results.push({ status: \"fail\", message: \"Cannot check tunnel — config not loaded\" });\n return results;\n }\n\n if (!ctx.config.tunnel.enabled) {\n results.push({ status: \"pass\", message: \"Tunnel not enabled (skipped)\" });\n return results;\n }\n\n const provider = ctx.config.tunnel.provider;\n results.push({ status: \"pass\", message: `Tunnel provider: ${provider}` });\n\n if (provider === \"cloudflare\") {\n const binName = os.platform() === \"win32\" ? \"cloudflared.exe\" : \"cloudflared\";\n const binPath = path.join(ctx.dataDir, \"bin\", binName);\n let found = false;\n if (fs.existsSync(binPath)) {\n found = true;\n } else {\n try {\n execFileSync(\"which\", [\"cloudflared\"], { stdio: \"pipe\" });\n found = true;\n } catch {\n // not found\n }\n }\n\n if (found) {\n results.push({ status: \"pass\", message: \"cloudflared binary found\" });\n } else {\n results.push({\n status: \"warn\",\n message: \"cloudflared binary not found\",\n fixable: true,\n fixRisk: \"safe\",\n fix: async () => {\n try {\n const { ensureCloudflared } = await import(\"../../../plugins/tunnel/providers/install-cloudflared.js\");\n await ensureCloudflared();\n return { success: true, message: \"installed cloudflared\" };\n } catch (err) {\n return { success: false, message: err instanceof Error ? err.message : String(err) };\n }\n },\n });\n }\n }\n\n const tunnelPort = ctx.config.tunnel.port;\n if (tunnelPort < 1 || tunnelPort > 65535) {\n results.push({ status: \"fail\", message: `Invalid tunnel port: ${tunnelPort}` });\n } else {\n results.push({ status: \"pass\", message: `Tunnel port: ${tunnelPort}` });\n }\n\n return results;\n },\n};\n","import * as path from 'node:path'\nimport * as clack from '@clack/prompts'\nimport type { Config, ConfigManager } from './config.js'\n\n// Compatibility wrappers — convert @inquirer/prompts API to @clack/prompts\nasync function select<T extends string>(opts: { message: string; choices: Array<{ name: string; value: T; description?: string }>; default?: T }): Promise<T> {\n const result = await clack.select({\n message: opts.message,\n options: opts.choices.map(ch => ({ label: ch.name, value: ch.value, hint: ch.description })) as any,\n initialValue: opts.default,\n })\n if (clack.isCancel(result)) { clack.cancel('Cancelled.'); process.exit(0) }\n return result as T\n}\n\nasync function input(opts: { message: string; default?: string; validate?: (val: string) => string | boolean }): Promise<string> {\n const result = await clack.text({\n message: opts.message,\n initialValue: opts.default,\n validate: opts.validate ? (val) => {\n const r = opts.validate!((val ?? \"\") as string)\n if (r === true || r === undefined) return undefined\n if (typeof r === 'string') return r\n return undefined\n } : undefined,\n })\n if (clack.isCancel(result)) { clack.cancel('Cancelled.'); process.exit(0) }\n return result as string\n}\nimport { installAutoStart, uninstallAutoStart, isAutoStartInstalled, isAutoStartSupported } from '../../cli/autostart.js'\nimport { expandHome } from './config.js'\n\n// ANSI color helpers\nconst c = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n}\n\nconst ok = (msg: string) => `${c.green}${c.bold}✓${c.reset} ${c.green}${msg}${c.reset}`\nconst warn = (msg: string) => `${c.yellow}⚠ ${msg}${c.reset}`\nconst dim = (msg: string) => `${c.dim}${msg}${c.reset}`\nconst header = (title: string) => `\\n${c.cyan}${c.bold}[${title}]${c.reset}\\n`\n\ntype ConfigUpdates = Record<string, unknown>\n\n// --- Edit: Telegram ---\n\nasync function editTelegram(config: Config, updates: ConfigUpdates): Promise<void> {\n const tg = (config.channels?.telegram ?? {}) as Record<string, unknown>\n const currentToken = (tg.botToken as string) ?? ''\n const currentChatId = (tg.chatId as number) ?? 0\n const currentEnabled = (tg.enabled as boolean) ?? false\n\n console.log(header('Telegram'))\n console.log(` Enabled : ${currentEnabled ? ok('yes') : dim('no')}`)\n const tokenDisplay = currentToken.length > 12\n ? currentToken.slice(0, 6) + '...' + currentToken.slice(-6)\n : currentToken || dim('(not set)')\n console.log(` Bot Token : ${tokenDisplay}`)\n console.log(` Chat ID : ${currentChatId || dim('(not set)')}`)\n console.log('')\n\n const ensureTelegramUpdates = () => {\n if (!updates.channels) updates.channels = {}\n if (!(updates.channels as Record<string, unknown>).telegram) {\n (updates.channels as Record<string, unknown>).telegram = {}\n }\n return (updates.channels as Record<string, unknown>).telegram as Record<string, unknown>\n }\n\n while (true) {\n const isEnabled = (() => {\n const ch = updates.channels as Record<string, unknown> | undefined\n const tgUp = ch?.telegram as Record<string, unknown> | undefined\n if (tgUp && 'enabled' in tgUp) return tgUp.enabled as boolean\n return currentEnabled\n })()\n\n const choice = await select({\n message: 'Telegram settings:',\n choices: [\n { name: isEnabled ? 'Disable Telegram' : 'Enable Telegram', value: 'toggle' },\n { name: 'Change Bot Token', value: 'token' },\n { name: 'Change Chat ID', value: 'chatid' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'toggle') {\n const tgUp = ensureTelegramUpdates()\n tgUp.enabled = !isEnabled\n console.log(!isEnabled ? ok('Telegram enabled') : ok('Telegram disabled'))\n }\n\n if (choice === 'token') {\n const token = await input({\n message: 'New bot token:',\n default: currentToken,\n validate: (val) => val.trim().length > 0 || 'Token cannot be empty',\n })\n\n try {\n const { validateBotToken } = await import('../../plugins/telegram/validators.js')\n const result = await validateBotToken(token.trim())\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`))\n } else {\n console.log(warn(`Validation failed: ${result.error} — saving anyway`))\n }\n } catch {\n console.log(warn('Telegram validator not available — skipping validation'))\n }\n\n const tgUp = ensureTelegramUpdates()\n tgUp.botToken = token.trim()\n tgUp.enabled = true\n }\n\n if (choice === 'chatid') {\n const chatIdStr = await input({\n message: 'New chat ID (e.g. -1001234567890):',\n default: String(currentChatId),\n validate: (val) => {\n const n = Number(val.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return true\n },\n })\n\n const chatId = Number(chatIdStr.trim())\n\n // Use the current (or already-updated) token for validation\n const tokenForValidation = (() => {\n const ch = updates.channels as Record<string, unknown> | undefined\n const tgUp = ch?.telegram as Record<string, unknown> | undefined\n if (typeof tgUp?.botToken === 'string') return tgUp.botToken\n return currentToken\n })()\n\n try {\n const { validateChatId } = await import('../../plugins/telegram/validators.js')\n const result = await validateChatId(tokenForValidation, chatId)\n if (result.ok) {\n console.log(ok(`Group: ${result.title}${result.isForum ? '' : warn(' (topics not enabled)')}`))\n } else {\n console.log(warn(`Validation failed: ${result.error} — saving anyway`))\n }\n } catch {\n console.log(warn('Telegram validator not available — skipping validation'))\n }\n\n const tgUp = ensureTelegramUpdates()\n tgUp.chatId = chatId\n }\n }\n}\n\n// --- Edit: Discord (delegates to plugin's configure()) ---\n\nconst DISCORD_PACKAGE = '@openacp/adapter-discord'\n\nasync function ensureDiscordPlugin(): Promise<any | null> {\n try {\n return await import(DISCORD_PACKAGE)\n } catch {\n const shouldInstall = await select({\n message: `${DISCORD_PACKAGE} is not installed. Install it now?`,\n choices: [\n { name: 'Yes, install now', value: 'yes' },\n { name: 'No, skip', value: 'no' },\n ],\n })\n if (shouldInstall === 'no') {\n console.log(warn(`Install later with: openacp plugin add ${DISCORD_PACKAGE}`))\n return null\n }\n try {\n console.log(dim(`Installing ${DISCORD_PACKAGE}...`))\n const { installNpmPlugin } = await import('../plugin/plugin-installer.js')\n const mod = await installNpmPlugin(DISCORD_PACKAGE)\n console.log(ok(`${DISCORD_PACKAGE} installed`))\n return mod\n } catch (err) {\n console.log(warn(`Failed to install: ${(err as Error).message}`))\n return null\n }\n }\n}\n\nasync function editDiscord(_config: Config, _updates: ConfigUpdates): Promise<void> {\n const pluginModule = await ensureDiscordPlugin()\n if (!pluginModule) return\n\n const plugin = pluginModule.default\n if (plugin?.configure) {\n const { SettingsManager } = await import('../plugin/settings-manager.js')\n const { createInstallContext } = await import('../plugin/install-context.js')\n const { getGlobalRoot } = await import('../instance/instance-context.js')\n const root = getGlobalRoot()\n const basePath = path.join(root, 'plugins')\n const settingsManager = new SettingsManager(basePath)\n const ctx = createInstallContext({\n pluginName: plugin.name,\n settingsManager,\n basePath,\n instanceRoot: root,\n })\n await plugin.configure(ctx)\n } else {\n console.log(warn('This plugin does not have a configure() method yet.'))\n }\n}\n\n// --- Edit: Channels (parent menu) ---\n\nasync function editChannels(config: Config, updates: ConfigUpdates): Promise<void> {\n const tgEnabled = (config.channels?.telegram as Record<string, unknown>)?.enabled !== false && config.channels?.telegram\n const dcEnabled = (config.channels?.discord as Record<string, unknown>)?.enabled !== false && config.channels?.discord\n\n console.log(header('Channels'))\n console.log(` Telegram : ${tgEnabled ? ok('configured') : dim('not configured')}`)\n console.log(` Discord : ${dcEnabled ? ok('configured') : dim('not configured')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Channel settings:',\n choices: [\n { name: 'Telegram', value: 'telegram' },\n { name: 'Discord', value: 'discord' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'telegram') await editTelegram(config, updates)\n if (choice === 'discord') await editDiscord(config, updates)\n }\n}\n\n// --- Edit: Agent ---\n\nasync function editAgent(config: Config, updates: ConfigUpdates): Promise<void> {\n const agentNames = Object.keys(config.agents ?? {})\n const currentDefault = config.defaultAgent\n\n console.log(header('Agent'))\n console.log(` Default agent : ${c.bold}${currentDefault}${c.reset}`)\n console.log(` Available : ${agentNames.join(', ') || dim('(none)')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Agent settings:',\n choices: [\n { name: 'Change default agent', value: 'default' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'default') {\n if (agentNames.length === 0) {\n console.log(warn('No agents configured.'))\n continue\n }\n\n const chosen = await select({\n message: 'Select default agent:',\n choices: agentNames.map((name) => ({ name, value: name })),\n })\n\n updates.defaultAgent = chosen\n console.log(ok(`Default agent set to ${chosen}`))\n }\n }\n}\n\n// --- Edit: Workspace ---\n\nasync function editWorkspace(config: Config, updates: ConfigUpdates): Promise<void> {\n const currentDir = config.workspace?.baseDir ?? '~/openacp-workspace'\n\n console.log(header('Workspace'))\n console.log(` Base directory : ${currentDir}`)\n console.log('')\n\n const newDir = await input({\n message: 'Workspace base directory:',\n default: currentDir,\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n updates.workspace = { baseDir: newDir.trim() }\n console.log(ok(`Workspace set to ${newDir.trim()}`))\n}\n\n// --- Edit: Security ---\n\nasync function editSecurity(config: Config, updates: ConfigUpdates): Promise<void> {\n const sec = config.security ?? { allowedUserIds: [], maxConcurrentSessions: 20, sessionTimeoutMinutes: 60 }\n\n console.log(header('Security'))\n console.log(` Allowed user IDs : ${sec.allowedUserIds?.length ? sec.allowedUserIds.join(', ') : dim('(all users allowed)')}`)\n console.log(` Max concurrent sessions : ${sec.maxConcurrentSessions}`)\n console.log(` Session timeout (min) : ${sec.sessionTimeoutMinutes}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Security settings:',\n choices: [\n { name: 'Max concurrent sessions', value: 'maxSessions' },\n { name: 'Session timeout (minutes)', value: 'timeout' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'maxSessions') {\n const val = await input({\n message: 'Max concurrent sessions:',\n default: String(sec.maxConcurrentSessions),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1) return 'Must be a positive integer'\n return true\n },\n })\n\n if (!updates.security) updates.security = {}\n ;(updates.security as Record<string, unknown>).maxConcurrentSessions = Number(val.trim())\n console.log(ok(`Max concurrent sessions set to ${val.trim()}`))\n }\n\n if (choice === 'timeout') {\n const val = await input({\n message: 'Session timeout in minutes:',\n default: String(sec.sessionTimeoutMinutes),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1) return 'Must be a positive integer'\n return true\n },\n })\n\n if (!updates.security) updates.security = {}\n ;(updates.security as Record<string, unknown>).sessionTimeoutMinutes = Number(val.trim())\n console.log(ok(`Session timeout set to ${val.trim()} minutes`))\n }\n }\n}\n\n// --- Edit: Logging ---\n\nasync function editLogging(config: Config, updates: ConfigUpdates): Promise<void> {\n const logging = config.logging ?? { level: 'info', logDir: '~/.openacp/logs', maxFileSize: '10m', maxFiles: 7, sessionLogRetentionDays: 30 }\n\n console.log(header('Logging'))\n console.log(` Log level : ${logging.level}`)\n console.log(` Log dir : ${logging.logDir}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Logging settings:',\n choices: [\n { name: 'Log level', value: 'level' },\n { name: 'Log directory', value: 'logDir' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (choice === 'level') {\n const level = await select({\n message: 'Select log level:',\n choices: [\n { name: 'silent', value: 'silent' },\n { name: 'debug', value: 'debug' },\n { name: 'info', value: 'info' },\n { name: 'warn', value: 'warn' },\n { name: 'error', value: 'error' },\n { name: 'fatal', value: 'fatal' },\n ],\n })\n\n if (!updates.logging) updates.logging = {}\n ;(updates.logging as Record<string, unknown>).level = level\n console.log(ok(`Log level set to ${level}`))\n }\n\n if (choice === 'logDir') {\n const dir = await input({\n message: 'Log directory:',\n default: logging.logDir,\n validate: (val) => val.trim().length > 0 || 'Path cannot be empty',\n })\n\n if (!updates.logging) updates.logging = {}\n ;(updates.logging as Record<string, unknown>).logDir = dir.trim()\n console.log(ok(`Log directory set to ${dir.trim()}`))\n }\n }\n}\n\n// --- Edit: Run Mode ---\n\nasync function editRunMode(config: Config, updates: ConfigUpdates): Promise<void> {\n const currentMode = config.runMode ?? 'foreground'\n const currentAutoStart = config.autoStart ?? false\n const autoStartInstalled = isAutoStartInstalled()\n const autoStartSupported = isAutoStartSupported()\n\n console.log(header('Run Mode'))\n console.log(` Current mode : ${c.bold}${currentMode}${c.reset}`)\n console.log(` Auto-start : ${currentAutoStart ? ok('enabled') : dim('disabled')}${autoStartInstalled ? ` ${dim('(installed)')}` : ''}`)\n console.log('')\n\n while (true) {\n const isDaemon = (() => {\n if ('runMode' in updates) return updates.runMode === 'daemon'\n return currentMode === 'daemon'\n })()\n\n const choices = [\n isDaemon\n ? { name: 'Switch to foreground mode', value: 'foreground' }\n : { name: 'Switch to daemon mode', value: 'daemon' },\n ]\n\n if (autoStartSupported) {\n const autoStartCurrent = (() => {\n if ('autoStart' in updates) return updates.autoStart as boolean\n return currentAutoStart\n })()\n choices.push({\n name: autoStartCurrent ? 'Disable auto-start' : 'Enable auto-start',\n value: 'toggleAutoStart',\n })\n }\n\n choices.push({ name: 'Back', value: 'back' })\n\n const choice = await select({\n message: 'Run mode settings:',\n choices,\n })\n\n if (choice === 'back') break\n\n if (choice === 'daemon') {\n updates.runMode = 'daemon'\n const logDir = (config.logging?.logDir) ?? '~/.openacp/logs'\n const result = installAutoStart(expandHome(logDir))\n if (result.success) {\n updates.autoStart = true\n console.log(ok('Switched to daemon mode with auto-start'))\n } else {\n console.log(warn(`Switched to daemon mode (auto-start failed: ${result.error})`))\n }\n }\n\n if (choice === 'foreground') {\n updates.runMode = 'foreground'\n updates.autoStart = false\n uninstallAutoStart()\n console.log(ok('Switched to foreground mode'))\n }\n\n if (choice === 'toggleAutoStart') {\n const autoStartCurrent = (() => {\n if ('autoStart' in updates) return updates.autoStart as boolean\n return currentAutoStart\n })()\n\n if (autoStartCurrent) {\n const result = uninstallAutoStart()\n updates.autoStart = false\n if (result.success) {\n console.log(ok('Auto-start disabled'))\n } else {\n console.log(warn(`Auto-start uninstall failed: ${result.error}`))\n }\n } else {\n const logDir = (config.logging?.logDir) ?? '~/.openacp/logs'\n const result = installAutoStart(expandHome(logDir))\n updates.autoStart = result.success\n if (result.success) {\n console.log(ok('Auto-start enabled'))\n } else {\n console.log(warn(`Auto-start install failed: ${result.error}`))\n }\n }\n }\n }\n}\n\n// --- Edit: API ---\n\nasync function editApi(config: Config, updates: ConfigUpdates): Promise<void> {\n const api = config.api ?? { port: 21420, host: '127.0.0.1' }\n\n console.log(header('API'))\n console.log(` Port : ${api.port}`)\n console.log(` Host : ${api.host} ${dim('(localhost only)')}`)\n console.log('')\n\n const newPort = await input({\n message: 'API port:',\n default: String(api.port),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1 || n > 65535) return 'Must be a valid port (1-65535)'\n return true\n },\n })\n\n updates.api = { port: Number(newPort.trim()) }\n console.log(ok(`API port set to ${newPort.trim()}`))\n}\n\n// --- Edit: Tunnel ---\n\nasync function editTunnel(config: Config, updates: ConfigUpdates): Promise<void> {\n const tunnel = config.tunnel ?? { enabled: false, port: 3100, provider: 'cloudflare', options: {}, storeTtlMinutes: 60, auth: { enabled: false } }\n const currentUpdates = (updates.tunnel ?? {}) as Record<string, unknown>\n\n const getVal = <T>(key: string, fallback: T): T =>\n (key in currentUpdates ? currentUpdates[key] : (tunnel as Record<string, unknown>)[key] ?? fallback) as T\n\n console.log(header('Tunnel'))\n console.log(` Enabled : ${getVal('enabled', false) ? ok('yes') : dim('no')}`)\n console.log(` Provider : ${c.bold}${getVal('provider', 'cloudflare')}${c.reset}`)\n console.log(` Port : ${getVal('port', 3100)}`)\n const authEnabled = (getVal('auth', { enabled: false }) as { enabled: boolean }).enabled\n console.log(` Auth : ${authEnabled ? ok('enabled') : dim('disabled')}`)\n console.log('')\n\n while (true) {\n const choice = await select({\n message: 'Tunnel settings:',\n choices: [\n { name: getVal('enabled', false) ? 'Disable tunnel' : 'Enable tunnel', value: 'toggle' },\n { name: 'Change provider', value: 'provider' },\n { name: 'Change port', value: 'port' },\n { name: 'Provider options', value: 'options' },\n { name: authEnabled ? 'Disable auth' : 'Enable auth', value: 'auth' },\n { name: 'Back', value: 'back' },\n ],\n })\n\n if (choice === 'back') break\n\n if (!updates.tunnel) updates.tunnel = { ...tunnel }\n const tun = updates.tunnel as Record<string, unknown>\n\n if (choice === 'toggle') {\n const current = getVal('enabled', false)\n tun.enabled = !current\n console.log(!current ? ok('Tunnel enabled') : ok('Tunnel disabled'))\n }\n\n if (choice === 'provider') {\n const provider = await select({\n message: 'Select tunnel provider:',\n choices: [\n { name: 'Cloudflare (default)', value: 'cloudflare' },\n { name: 'ngrok', value: 'ngrok' },\n { name: 'bore', value: 'bore' },\n { name: 'Tailscale Funnel', value: 'tailscale' },\n ],\n })\n tun.provider = provider\n tun.options = {} // reset options when switching provider\n console.log(ok(`Provider set to ${provider}`))\n }\n\n if (choice === 'port') {\n const val = await input({\n message: 'Tunnel port:',\n default: String(getVal('port', 3100)),\n validate: (v) => {\n const n = Number(v.trim())\n if (!Number.isInteger(n) || n < 1 || n > 65535) return 'Must be a valid port (1-65535)'\n return true\n },\n })\n tun.port = Number(val.trim())\n console.log(ok(`Tunnel port set to ${val.trim()}`))\n }\n\n if (choice === 'options') {\n const provider = getVal('provider', 'cloudflare')\n const currentOptions = getVal('options', {}) as Record<string, unknown>\n await editProviderOptions(provider, currentOptions, tun)\n }\n\n if (choice === 'auth') {\n const currentAuth = getVal('auth', { enabled: false }) as { enabled: boolean; token?: string }\n if (currentAuth.enabled) {\n tun.auth = { enabled: false }\n console.log(ok('Tunnel auth disabled'))\n } else {\n const token = await input({\n message: 'Auth token (leave empty to auto-generate):',\n default: '',\n })\n tun.auth = token.trim()\n ? { enabled: true, token: token.trim() }\n : { enabled: true }\n console.log(ok('Tunnel auth enabled'))\n }\n }\n }\n}\n\nasync function editProviderOptions(\n provider: string,\n currentOptions: Record<string, unknown>,\n tun: Record<string, unknown>,\n): Promise<void> {\n if (provider === 'cloudflare') {\n const domain = await input({\n message: 'Custom domain (leave empty for random):',\n default: (currentOptions.domain as string) ?? '',\n })\n tun.options = domain.trim() ? { domain: domain.trim() } : {}\n if (domain.trim()) console.log(ok(`Domain set to ${domain.trim()}`))\n else console.log(dim('Using random cloudflare domain'))\n } else if (provider === 'ngrok') {\n const authtoken = await input({\n message: 'ngrok authtoken (leave empty to skip):',\n default: (currentOptions.authtoken as string) ?? '',\n })\n const domain = await input({\n message: 'ngrok domain (leave empty for random):',\n default: (currentOptions.domain as string) ?? '',\n })\n const region = await input({\n message: 'ngrok region (us, eu, ap — leave empty for default):',\n default: (currentOptions.region as string) ?? '',\n })\n const opts: Record<string, string> = {}\n if (authtoken.trim()) opts.authtoken = authtoken.trim()\n if (domain.trim()) opts.domain = domain.trim()\n if (region.trim()) opts.region = region.trim()\n tun.options = opts\n console.log(ok('ngrok options saved'))\n } else if (provider === 'bore') {\n const server = await input({\n message: 'bore server:',\n default: (currentOptions.server as string) ?? 'bore.pub',\n })\n const port = await input({\n message: 'bore port (leave empty for auto):',\n default: currentOptions.port ? String(currentOptions.port) : '',\n })\n const secret = await input({\n message: 'bore secret (leave empty to skip):',\n default: (currentOptions.secret as string) ?? '',\n })\n const opts: Record<string, unknown> = { server: server.trim() }\n if (port.trim()) opts.port = Number(port.trim())\n if (secret.trim()) opts.secret = secret.trim()\n tun.options = opts\n console.log(ok('bore options saved'))\n } else if (provider === 'tailscale') {\n const bg = await select({\n message: 'Run Tailscale Funnel in background?',\n choices: [\n { name: 'No', value: 'no' },\n { name: 'Yes', value: 'yes' },\n ],\n })\n tun.options = bg === 'yes' ? { bg: true } : {}\n console.log(ok('Tailscale options saved'))\n } else {\n console.log(dim(`No configurable options for provider \"${provider}\"`))\n }\n}\n\n// --- Main Config Editor ---\n\nexport async function runConfigEditor(\n configManager: ConfigManager,\n mode: 'file' | 'api' = 'file',\n apiPort?: number,\n): Promise<void> {\n await configManager.load()\n const config = configManager.get()\n const updates: ConfigUpdates = {}\n\n console.log(`\\n${c.cyan}${c.bold}OpenACP Config Editor${c.reset}`)\n console.log(dim(`Config: ${configManager.getConfigPath()}`))\n console.log('')\n\n try {\n while (true) {\n const hasChanges = mode === 'file' ? Object.keys(updates).length > 0 : false\n const choice = await select({\n message: `What would you like to edit?${hasChanges ? ` ${c.yellow}(unsaved changes)${c.reset}` : ''}`,\n choices: [\n { name: 'Channels', value: 'channels' },\n { name: 'Agent', value: 'agent' },\n { name: 'Workspace', value: 'workspace' },\n { name: 'Security', value: 'security' },\n { name: 'Logging', value: 'logging' },\n { name: 'Run Mode', value: 'runMode' },\n { name: 'API', value: 'api' },\n { name: 'Tunnel', value: 'tunnel' },\n { name: hasChanges ? 'Save & Exit' : 'Exit', value: 'exit' },\n ],\n })\n\n if (choice === 'exit') {\n if (mode === 'file' && hasChanges) {\n await configManager.save(updates)\n console.log(ok(`Config saved to ${configManager.getConfigPath()}`))\n } else if (mode === 'file') {\n console.log(dim('No changes made.'))\n }\n break\n }\n\n const sectionUpdates: ConfigUpdates = {}\n\n if (choice === 'channels') await editChannels(config, sectionUpdates)\n else if (choice === 'agent') await editAgent(config, sectionUpdates)\n else if (choice === 'workspace') await editWorkspace(config, sectionUpdates)\n else if (choice === 'security') await editSecurity(config, sectionUpdates)\n else if (choice === 'logging') await editLogging(config, sectionUpdates)\n else if (choice === 'runMode') await editRunMode(config, sectionUpdates)\n else if (choice === 'api') await editApi(config, sectionUpdates)\n else if (choice === 'tunnel') await editTunnel(config, sectionUpdates)\n\n if (mode === 'api' && Object.keys(sectionUpdates).length > 0) {\n await sendConfigViaApi(apiPort!, sectionUpdates)\n // Refresh in-memory config\n await configManager.load()\n Object.assign(config, configManager.get())\n } else {\n // Accumulate for file mode\n Object.assign(updates, sectionUpdates)\n }\n }\n } catch (err) {\n if ((err as Error).name === 'ExitPromptError') {\n console.log(dim('\\nConfig editor cancelled. Changes discarded.'))\n return\n }\n throw err\n }\n}\n\nasync function sendConfigViaApi(port: number, updates: ConfigUpdates): Promise<void> {\n const { apiCall: call } = await import('../../cli/api-client.js')\n\n const paths = flattenToPaths(updates)\n for (const { path, value } of paths) {\n const res = await call(port, '/api/config', {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path, value }),\n })\n const data = await res.json() as Record<string, unknown>\n if (!res.ok) {\n console.log(warn(`Failed to update ${path}: ${data.error}`))\n } else if (data.needsRestart) {\n console.log(warn(`${path} updated — restart required`))\n }\n }\n}\n\nfunction flattenToPaths(obj: Record<string, unknown>, prefix = ''): Array<{ path: string; value: unknown }> {\n const result: Array<{ path: string; value: unknown }> = []\n for (const [key, val] of Object.entries(obj)) {\n const fullPath = prefix ? `${prefix}.${key}` : key\n if (val && typeof val === 'object' && !Array.isArray(val)) {\n result.push(...flattenToPaths(val as Record<string, unknown>, fullPath))\n } else {\n result.push({ path: fullPath, value: val })\n }\n }\n return result\n}\n","import { execFileSync } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport { createChildLogger } from '../core/utils/log.js'\n\nconst log = createChildLogger({ module: 'autostart' })\n\nconst LAUNCHD_LABEL = 'com.openacp.daemon'\nconst LAUNCHD_PLIST_PATH = path.join(os.homedir(), 'Library', 'LaunchAgents', `${LAUNCHD_LABEL}.plist`)\nconst SYSTEMD_SERVICE_PATH = path.join(os.homedir(), '.config', 'systemd', 'user', 'openacp.service')\n\nexport function isAutoStartSupported(): boolean {\n return process.platform === 'darwin' || process.platform === 'linux'\n}\n\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\nexport function escapeSystemdValue(str: string): string {\n const escaped = str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\$/g, '$$$$')\n .replace(/%/g, '%%')\n return `\"${escaped}\"`\n}\n\nexport function generateLaunchdPlist(nodePath: string, cliPath: string, logDir: string): string {\n const logFile = path.join(logDir, 'openacp.log')\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${LAUNCHD_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${escapeXml(nodePath)}</string>\n <string>${escapeXml(cliPath)}</string>\n <string>--daemon-child</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>StandardOutPath</key>\n <string>${escapeXml(logFile)}</string>\n <key>StandardErrorPath</key>\n <string>${escapeXml(logFile)}</string>\n</dict>\n</plist>\n`\n}\n\nexport function generateSystemdUnit(nodePath: string, cliPath: string): string {\n return `[Unit]\nDescription=OpenACP Daemon\n\n[Service]\nExecStart=${escapeSystemdValue(nodePath)} ${escapeSystemdValue(cliPath)} --daemon-child\nRestart=on-failure\n\n[Install]\nWantedBy=default.target\n`\n}\n\nexport function installAutoStart(logDir: string): { success: boolean; error?: string } {\n if (!isAutoStartSupported()) {\n return { success: false, error: 'Auto-start not supported on this platform' }\n }\n\n const nodePath = process.execPath\n const cliPath = path.resolve(process.argv[1])\n const resolvedLogDir = logDir.startsWith('~')\n ? path.join(os.homedir(), logDir.slice(1))\n : logDir\n\n try {\n if (process.platform === 'darwin') {\n const plist = generateLaunchdPlist(nodePath, cliPath, resolvedLogDir)\n const dir = path.dirname(LAUNCHD_PLIST_PATH)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(LAUNCHD_PLIST_PATH, plist)\n execFileSync('launchctl', ['load', LAUNCHD_PLIST_PATH], { stdio: 'pipe' })\n log.info('LaunchAgent installed')\n return { success: true }\n }\n\n if (process.platform === 'linux') {\n const unit = generateSystemdUnit(nodePath, cliPath)\n const dir = path.dirname(SYSTEMD_SERVICE_PATH)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(SYSTEMD_SERVICE_PATH, unit)\n execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'pipe' })\n execFileSync('systemctl', ['--user', 'enable', 'openacp'], { stdio: 'pipe' })\n log.info('systemd user service installed')\n return { success: true }\n }\n\n return { success: false, error: 'Unsupported platform' }\n } catch (e) {\n const msg = (e as Error).message\n log.error({ err: msg }, 'Failed to install auto-start')\n return { success: false, error: msg }\n }\n}\n\nexport function uninstallAutoStart(): { success: boolean; error?: string } {\n if (!isAutoStartSupported()) {\n return { success: false, error: 'Auto-start not supported on this platform' }\n }\n\n try {\n if (process.platform === 'darwin') {\n if (fs.existsSync(LAUNCHD_PLIST_PATH)) {\n try {\n execFileSync('launchctl', ['unload', LAUNCHD_PLIST_PATH], { stdio: 'pipe' })\n } catch {\n // may already be unloaded\n }\n fs.unlinkSync(LAUNCHD_PLIST_PATH)\n log.info('LaunchAgent removed')\n }\n return { success: true }\n }\n\n if (process.platform === 'linux') {\n if (fs.existsSync(SYSTEMD_SERVICE_PATH)) {\n try {\n execFileSync('systemctl', ['--user', 'disable', 'openacp'], { stdio: 'pipe' })\n } catch {\n // may already be disabled\n }\n fs.unlinkSync(SYSTEMD_SERVICE_PATH)\n execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'pipe' })\n log.info('systemd user service removed')\n }\n return { success: true }\n }\n\n return { success: false, error: 'Unsupported platform' }\n } catch (e) {\n const msg = (e as Error).message\n log.error({ err: msg }, 'Failed to uninstall auto-start')\n return { success: false, error: msg }\n }\n}\n\nexport function isAutoStartInstalled(): boolean {\n if (process.platform === 'darwin') {\n return fs.existsSync(LAUNCHD_PLIST_PATH)\n }\n if (process.platform === 'linux') {\n return fs.existsSync(SYSTEMD_SERVICE_PATH)\n }\n return false\n}\n","import { spawn } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport { expandHome } from '../core/config/config.js'\n\nconst DEFAULT_ROOT = path.join(os.homedir(), '.openacp')\n\nexport function getPidPath(root?: string): string {\n const base = root ?? DEFAULT_ROOT\n return path.join(base, 'openacp.pid')\n}\n\nexport function getLogDir(root?: string): string {\n const base = root ?? DEFAULT_ROOT\n return path.join(base, 'logs')\n}\n\nexport function getRunningMarker(root?: string): string {\n const base = root ?? DEFAULT_ROOT\n return path.join(base, 'running')\n}\n\nexport function writePidFile(pidPath: string, pid: number): void {\n const dir = path.dirname(pidPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(pidPath, String(pid))\n}\n\nexport function readPidFile(pidPath: string): number | null {\n try {\n const content = fs.readFileSync(pidPath, 'utf-8').trim()\n const pid = parseInt(content, 10)\n return isNaN(pid) ? null : pid\n } catch {\n return null\n }\n}\n\nexport function removePidFile(pidPath: string): void {\n try {\n fs.unlinkSync(pidPath)\n } catch {\n // ignore if already gone\n }\n}\n\nexport function isProcessRunning(pidPath: string): boolean {\n const pid = readPidFile(pidPath)\n if (pid === null) return false\n try {\n process.kill(pid, 0)\n return true\n } catch {\n // Process not running, clean up stale PID file\n removePidFile(pidPath)\n return false\n }\n}\n\nexport function getStatus(pidPath: string = getPidPath()): { running: boolean; pid?: number } {\n const pid = readPidFile(pidPath)\n if (pid === null) return { running: false }\n try {\n process.kill(pid, 0)\n return { running: true, pid }\n } catch {\n removePidFile(pidPath)\n return { running: false }\n }\n}\n\nexport function startDaemon(pidPath: string = getPidPath(), logDir?: string, instanceRoot?: string): { pid: number } | { error: string } {\n // Mark as running so auto-start works on next boot\n markRunning(instanceRoot)\n\n // Check if already running\n if (isProcessRunning(pidPath)) {\n const pid = readPidFile(pidPath)!\n return { error: `Already running (PID ${pid})` }\n }\n\n const resolvedLogDir = logDir ? expandHome(logDir) : getLogDir(instanceRoot)\n fs.mkdirSync(resolvedLogDir, { recursive: true })\n const logFile = path.join(resolvedLogDir, 'openacp.log')\n\n // Find the CLI entry point\n const cliPath = path.resolve(process.argv[1])\n const nodePath = process.execPath\n\n const out = fs.openSync(logFile, 'a')\n const err = fs.openSync(logFile, 'a')\n\n const child = spawn(nodePath, [cliPath, '--daemon-child'], {\n detached: true,\n stdio: ['ignore', out, err],\n env: {\n ...process.env,\n ...(instanceRoot ? { OPENACP_INSTANCE_ROOT: instanceRoot } : {}),\n },\n })\n\n // Close file descriptors in parent — child has its own copies\n fs.closeSync(out)\n fs.closeSync(err)\n\n if (!child.pid) {\n return { error: 'Failed to spawn daemon process' }\n }\n\n // PID file is written by the child process itself (in main.ts startServer)\n // to avoid race conditions and ensure consistency with LaunchAgent/systemd starts.\n // We still write it here as a fallback in case the child hasn't written it yet\n // when the parent needs to report the PID.\n writePidFile(pidPath, child.pid)\n child.unref()\n\n return { pid: child.pid }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction isProcessAlive(pid: number): 'alive' | 'dead' | 'eperm' {\n try {\n process.kill(pid, 0)\n return 'alive'\n } catch (e) {\n const err = e as NodeJS.ErrnoException\n if (err.code === 'EPERM') return 'eperm'\n return 'dead'\n }\n}\n\nexport async function stopDaemon(pidPath: string = getPidPath(), instanceRoot?: string): Promise<{ stopped: boolean; pid?: number; error?: string }> {\n const pid = readPidFile(pidPath)\n if (pid === null) return { stopped: false, error: 'Not running (no PID file)' }\n\n const status = isProcessAlive(pid)\n if (status === 'dead') {\n removePidFile(pidPath)\n return { stopped: false, error: 'Not running (stale PID file removed)' }\n }\n if (status === 'eperm') {\n removePidFile(pidPath)\n return { stopped: false, error: 'PID belongs to another process (stale PID file removed)' }\n }\n\n try {\n process.kill(pid, 'SIGTERM')\n } catch (e) {\n return { stopped: false, error: `Failed to stop: ${(e as Error).message}` }\n }\n\n clearRunning(instanceRoot)\n\n const POLL_INTERVAL = 100\n const TIMEOUT = 5000\n const start = Date.now()\n\n while (Date.now() - start < TIMEOUT) {\n await sleep(POLL_INTERVAL)\n const s = isProcessAlive(pid)\n if (s === 'dead' || s === 'eperm') {\n removePidFile(pidPath)\n return { stopped: true, pid }\n }\n }\n\n try {\n process.kill(pid, 'SIGKILL')\n } catch (e) {\n const err = e as NodeJS.ErrnoException\n if (err.code === 'EPERM') {\n return { stopped: false, pid, error: 'PID may have been reused by another process. Run `openacp status` to verify, or manually delete the PID file.' }\n }\n }\n\n const killStart = Date.now()\n while (Date.now() - killStart < 1000) {\n await sleep(POLL_INTERVAL)\n const s = isProcessAlive(pid)\n if (s === 'dead' || s === 'eperm') {\n removePidFile(pidPath)\n return { stopped: true, pid }\n }\n }\n\n // SIGKILL sent but process still alive after 1s — extremely rare (uninterruptible I/O).\n return { stopped: false, pid, error: 'Process did not exit after SIGKILL (possible uninterruptible I/O). PID file retained.' }\n}\n\n/** Mark that the daemon should auto-start on boot */\nexport function markRunning(root?: string): void {\n const marker = getRunningMarker(root)\n fs.mkdirSync(path.dirname(marker), { recursive: true })\n fs.writeFileSync(marker, '')\n}\n\n/** Remove running marker — daemon won't auto-start on boot */\nexport function clearRunning(root?: string): void {\n try { fs.unlinkSync(getRunningMarker(root)) } catch { /* ignore */ }\n}\n\n/** Check if the daemon was running before (should auto-start on boot) */\nexport function shouldAutoStart(root?: string): boolean {\n return fs.existsSync(getRunningMarker(root))\n}\n","import type { IChannelAdapter } from '../../core/channel.js'\nimport type { NotificationMessage } from '../../core/types.js'\n\nexport class NotificationManager {\n constructor(private adapters: Map<string, IChannelAdapter>) {}\n\n async notify(channelId: string, notification: NotificationMessage): Promise<void> {\n const adapter = this.adapters.get(channelId)\n if (!adapter) return\n try {\n await adapter.sendNotification(notification)\n } catch {\n // Don't let notification failures crash the caller\n }\n }\n\n async notifyAll(notification: NotificationMessage): Promise<void> {\n for (const adapter of this.adapters.values()) {\n try {\n await adapter.sendNotification(notification)\n } catch {\n // Continue to next adapter\n }\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { OggOpusDecoder } from \"ogg-opus-decoder\";\nimport wav from \"node-wav\";\nimport type { Attachment } from \"../../core/types.js\";\n\nconst MIME_TO_EXT: Record<string, string> = {\n \"image/jpeg\": \".jpg\",\n \"image/png\": \".png\",\n \"image/gif\": \".gif\",\n \"image/webp\": \".webp\",\n \"image/svg+xml\": \".svg\",\n \"audio/ogg\": \".ogg\",\n \"audio/mpeg\": \".mp3\",\n \"audio/wav\": \".wav\",\n \"audio/webm\": \".webm\",\n \"audio/mp4\": \".m4a\",\n \"video/mp4\": \".mp4\",\n \"video/webm\": \".webm\",\n \"application/pdf\": \".pdf\",\n \"text/plain\": \".txt\",\n};\n\nconst EXT_TO_MIME: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".ogg\": \"audio/ogg\",\n \".oga\": \"audio/ogg\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".m4a\": \"audio/mp4\",\n \".mp4\": \"video/mp4\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n};\n\nfunction classifyMime(mimeType: string): Attachment[\"type\"] {\n if (mimeType.startsWith(\"image/\")) return \"image\";\n if (mimeType.startsWith(\"audio/\")) return \"audio\";\n return \"file\";\n}\n\nexport class FileService {\n constructor(private baseDir: string) {}\n\n /**\n * Remove session file directories older than maxAgeDays.\n * Called on startup to prevent unbounded disk growth.\n */\n async cleanupOldFiles(maxAgeDays: number): Promise<number> {\n const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;\n let removed = 0;\n try {\n const entries = await fs.promises.readdir(this.baseDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const dirPath = path.join(this.baseDir, entry.name);\n try {\n const stat = await fs.promises.stat(dirPath);\n if (stat.mtimeMs < cutoff) {\n await fs.promises.rm(dirPath, { recursive: true, force: true });\n removed++;\n }\n } catch {\n // Skip inaccessible directories\n }\n }\n } catch {\n // Base dir doesn't exist yet — nothing to clean\n }\n return removed;\n }\n\n async saveFile(\n sessionId: string,\n fileName: string,\n data: Buffer,\n mimeType: string,\n ): Promise<Attachment> {\n const sessionDir = path.join(this.baseDir, sessionId);\n await fs.promises.mkdir(sessionDir, { recursive: true });\n\n const safeName = `${Date.now()}-${fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\")}`;\n const filePath = path.join(sessionDir, safeName);\n await fs.promises.writeFile(filePath, data);\n\n return {\n type: classifyMime(mimeType),\n filePath,\n fileName,\n mimeType,\n size: data.length,\n };\n }\n\n async resolveFile(filePath: string): Promise<Attachment | null> {\n try {\n const stat = await fs.promises.stat(filePath);\n if (!stat.isFile()) return null;\n\n const ext = path.extname(filePath).toLowerCase();\n const mimeType = EXT_TO_MIME[ext] || \"application/octet-stream\";\n\n return {\n type: classifyMime(mimeType),\n filePath,\n fileName: path.basename(filePath),\n mimeType,\n size: stat.size,\n };\n } catch {\n return null;\n }\n }\n\n /**\n * Convert OGG Opus audio to WAV format.\n * Telegram voice messages use OGG Opus which many AI agents can't read.\n */\n async convertOggToWav(oggData: Buffer): Promise<Buffer> {\n const decoder = new OggOpusDecoder();\n await decoder.ready;\n try {\n const { channelData, sampleRate } = await decoder.decode(new Uint8Array(oggData));\n const wavData = wav.encode(channelData, { sampleRate, float: true, bitDepth: 32 });\n return Buffer.from(wavData);\n } finally {\n decoder.free();\n }\n }\n\n /** Instance method — delegates to static for FileServiceInterface compliance */\n async readTextFileWithRange(\n filePath: string,\n options?: { line?: number; limit?: number },\n ): Promise<string> {\n return FileService.readTextFileWithRange(filePath, options);\n }\n\n static async readTextFileWithRange(\n filePath: string,\n options?: { line?: number; limit?: number },\n ): Promise<string> {\n // Delegate to core utility (canonical implementation)\n const { readTextFileWithRange } = await import(\"../../core/utils/read-text-file.js\");\n return readTextFileWithRange(filePath, options);\n }\n\n /** Instance method — delegates to static for FileServiceInterface compliance */\n extensionFromMime(mimeType: string): string {\n return FileService.extensionFromMime(mimeType);\n }\n\n static extensionFromMime(mimeType: string): string {\n return MIME_TO_EXT[mimeType] || \".bin\";\n }\n}\n","import type { ConfigManager } from \"../../core/config/config.js\";\nimport type { SessionManager } from \"../../core/sessions/session-manager.js\";\nimport type { IncomingMessage } from \"../../core/types.js\";\n\nexport class SecurityGuard {\n constructor(\n private configManager: ConfigManager,\n private sessionManager: SessionManager,\n ) {}\n\n checkAccess(message: IncomingMessage):\n | { allowed: true }\n | { allowed: false; reason: string }\n {\n const config = this.configManager.get();\n if (config.security.allowedUserIds.length > 0) {\n const userId = String(message.userId);\n if (!config.security.allowedUserIds.includes(userId)) {\n return { allowed: false, reason: \"Unauthorized user\" };\n }\n }\n const active = this.sessionManager.listSessions()\n .filter(s => s.status === \"active\" || s.status === \"initializing\");\n if (active.length >= config.security.maxConcurrentSessions) {\n return { allowed: false, reason: `Session limit reached (${config.security.maxConcurrentSessions})` };\n }\n return { allowed: true };\n }\n}\n","import type { SessionManager } from '../../core/sessions/session-manager.js'\nimport type { IChannelAdapter } from '../../core/channel.js'\nimport type { SessionRecord } from '../../core/types.js'\nimport { createChildLogger } from '../../core/utils/log.js'\n\nconst log = createChildLogger({ module: 'topic-manager' })\n\nexport interface TopicInfo {\n sessionId: string\n topicId: number | null\n name: string | null\n status: string\n agentName: string\n lastActiveAt: string\n}\n\nexport interface DeleteTopicResult {\n ok: boolean\n needsConfirmation?: boolean\n topicId?: number | null\n session?: { id: string; name: string | null; status: string }\n error?: string\n}\n\nexport interface CleanupResult {\n deleted: string[]\n failed: { sessionId: string; error: string }[]\n}\n\ninterface SystemTopicIds {\n notificationTopicId: number | null\n assistantTopicId: number | null\n}\n\nexport class TopicManager {\n constructor(\n private sessionManager: SessionManager,\n private adapter: IChannelAdapter | null,\n private systemTopicIds: SystemTopicIds,\n ) {}\n\n listTopics(filter?: { statuses?: string[] }): TopicInfo[] {\n const records = this.sessionManager.listRecords(filter)\n return records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => !filter?.statuses?.length || filter.statuses.includes(r.status))\n .map(r => ({\n sessionId: r.sessionId,\n topicId: (r.platform as Record<string, unknown>)?.topicId as number ?? null,\n name: r.name ?? null,\n status: r.status,\n agentName: r.agentName,\n lastActiveAt: r.lastActiveAt,\n }))\n }\n\n async deleteTopic(sessionId: string, options?: { confirmed?: boolean }): Promise<DeleteTopicResult> {\n const records = this.sessionManager.listRecords()\n const record = records.find(r => r.sessionId === sessionId)\n if (!record) return { ok: false, error: 'Session not found' }\n\n if (this.isSystemTopic(record)) return { ok: false, error: 'Cannot delete system topic' }\n\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive && !options?.confirmed) {\n return {\n ok: false,\n needsConfirmation: true,\n session: { id: record.sessionId, name: record.name ?? null, status: record.status },\n }\n }\n\n if (isActive) {\n await this.sessionManager.cancelSession(sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number ?? null\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(sessionId)\n } catch (err) {\n log.warn({ err, sessionId, topicId }, 'Failed to delete platform thread, removing record anyway')\n }\n }\n\n await this.sessionManager.removeRecord(sessionId)\n return { ok: true, topicId }\n }\n\n async cleanup(statuses?: string[]): Promise<CleanupResult> {\n const targetStatuses = statuses?.length ? statuses : ['finished', 'error', 'cancelled']\n const records = this.sessionManager.listRecords({ statuses: targetStatuses })\n const targets = records\n .filter(r => !this.isSystemTopic(r))\n .filter(r => targetStatuses.includes(r.status))\n\n const deleted: string[] = []\n const failed: { sessionId: string; error: string }[] = []\n\n for (const record of targets) {\n try {\n // Cancel active/initializing sessions to prevent orphaned agent processes\n const isActive = record.status === 'active' || record.status === 'initializing'\n if (isActive) {\n await this.sessionManager.cancelSession(record.sessionId)\n }\n\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (this.adapter && topicId) {\n try {\n await this.adapter.deleteSessionThread?.(record.sessionId)\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId }, 'Failed to delete platform thread during cleanup')\n }\n }\n await this.sessionManager.removeRecord(record.sessionId)\n deleted.push(record.sessionId)\n } catch (err) {\n failed.push({ sessionId: record.sessionId, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n return { deleted, failed }\n }\n\n private isSystemTopic(record: SessionRecord): boolean {\n const topicId = (record.platform as Record<string, unknown>)?.topicId as number | undefined\n if (!topicId) return false\n return topicId === this.systemTopicIds.notificationTopicId\n || topicId === this.systemTopicIds.assistantTopicId\n }\n}\n","import type { STTProvider, TTSProvider, STTOptions, STTResult, TTSOptions, TTSResult, SpeechServiceConfig } from './speech-types.js';\n\nexport type ProviderFactory = (config: SpeechServiceConfig) => { stt: Map<string, STTProvider>; tts: Map<string, TTSProvider> };\n\nexport class SpeechService {\n private sttProviders = new Map<string, STTProvider>();\n private ttsProviders = new Map<string, TTSProvider>();\n private providerFactory?: ProviderFactory;\n\n constructor(private config: SpeechServiceConfig) {}\n\n /** Set a factory function that can recreate providers from config (for hot-reload) */\n setProviderFactory(factory: ProviderFactory): void {\n this.providerFactory = factory;\n }\n\n registerSTTProvider(name: string, provider: STTProvider): void {\n this.sttProviders.set(name, provider);\n }\n\n registerTTSProvider(name: string, provider: TTSProvider): void {\n this.ttsProviders.set(name, provider);\n }\n\n unregisterTTSProvider(name: string): void {\n this.ttsProviders.delete(name);\n }\n\n isSTTAvailable(): boolean {\n const { provider, providers } = this.config.stt;\n return provider !== null && providers[provider]?.apiKey !== undefined;\n }\n\n isTTSAvailable(): boolean {\n const provider = this.config.tts.provider;\n return provider !== null && this.ttsProviders.has(provider);\n }\n\n async transcribe(audioBuffer: Buffer, mimeType: string, options?: STTOptions): Promise<STTResult> {\n const providerName = this.config.stt.provider;\n if (!providerName || !this.config.stt.providers[providerName]?.apiKey) {\n throw new Error(\"STT not configured. Set speech.stt.provider and API key in config.\");\n }\n const provider = this.sttProviders.get(providerName);\n if (!provider) {\n throw new Error(`STT provider \"${providerName}\" not registered. Available: ${[...this.sttProviders.keys()].join(\", \") || \"none\"}`);\n }\n return provider.transcribe(audioBuffer, mimeType, options);\n }\n\n async synthesize(text: string, options?: TTSOptions): Promise<TTSResult> {\n const providerName = this.config.tts.provider;\n if (!providerName) {\n throw new Error(\"TTS not configured. Set speech.tts.provider in config.\");\n }\n const provider = this.ttsProviders.get(providerName);\n if (!provider) {\n throw new Error(`TTS provider \"${providerName}\" not registered. Available: ${[...this.ttsProviders.keys()].join(\", \") || \"none\"}`);\n }\n return provider.synthesize(text, options);\n }\n\n updateConfig(config: SpeechServiceConfig): void {\n this.config = config;\n }\n\n /** Re-create factory-managed providers from config. Preserves externally-registered providers (e.g. from plugins). */\n refreshProviders(newConfig: SpeechServiceConfig): void {\n this.config = newConfig;\n if (this.providerFactory) {\n const { stt, tts } = this.providerFactory(newConfig);\n // Merge: factory providers overwrite, but externally-registered providers are preserved\n for (const [name, provider] of stt) {\n this.sttProviders.set(name, provider);\n }\n for (const [name, provider] of tts) {\n this.ttsProviders.set(name, provider);\n }\n }\n }\n}\n","import type { STTProvider, STTOptions, STTResult } from '../speech-types.js';\n\nconst GROQ_API_URL = \"https://api.groq.com/openai/v1/audio/transcriptions\";\n\nexport class GroqSTT implements STTProvider {\n readonly name = \"groq\";\n\n constructor(\n private apiKey: string,\n private defaultModel: string = \"whisper-large-v3-turbo\",\n ) {}\n\n async transcribe(audioBuffer: Buffer, mimeType: string, options?: STTOptions): Promise<STTResult> {\n const ext = mimeToExt(mimeType);\n const form = new FormData();\n form.append(\"file\", new Blob([new Uint8Array(audioBuffer)], { type: mimeType }), `audio${ext}`);\n form.append(\"model\", options?.model || this.defaultModel);\n form.append(\"response_format\", \"verbose_json\");\n if (options?.language) {\n form.append(\"language\", options.language);\n }\n\n const resp = await fetch(GROQ_API_URL, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n body: form,\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n if (resp.status === 401) {\n throw new Error(\"Invalid Groq API key. Check your key at console.groq.com.\");\n }\n if (resp.status === 413) {\n throw new Error(\"Audio file too large for Groq API (max 25MB).\");\n }\n if (resp.status === 429) {\n throw new Error(\"Groq rate limit exceeded. Free tier: 28,800 seconds/day. Try again later.\");\n }\n throw new Error(`Groq STT error (${resp.status}): ${body}`);\n }\n\n const data = await resp.json() as { text: string; language?: string; duration?: number };\n return {\n text: data.text,\n language: data.language,\n duration: data.duration,\n };\n }\n}\n\nfunction mimeToExt(mimeType: string): string {\n const map: Record<string, string> = {\n \"audio/ogg\": \".ogg\",\n \"audio/wav\": \".wav\",\n \"audio/mpeg\": \".mp3\",\n \"audio/mp4\": \".m4a\",\n \"audio/webm\": \".webm\",\n \"audio/flac\": \".flac\",\n };\n return map[mimeType] || \".bin\";\n}\n","import * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ContextProvider, ContextQuery, ContextOptions, ContextResult, SessionListResult } from \"./context-provider.js\";\nimport { ContextCache } from \"./context-cache.js\";\n\nexport class ContextManager {\n private providers: ContextProvider[] = [];\n private cache: ContextCache;\n\n constructor(cachePath?: string) {\n this.cache = new ContextCache(cachePath ?? path.join(os.homedir(), \".openacp\", \"cache\", \"entire\"));\n }\n\n register(provider: ContextProvider): void {\n this.providers.push(provider);\n }\n\n async getProvider(repoPath: string): Promise<ContextProvider | null> {\n for (const provider of this.providers) {\n if (await provider.isAvailable(repoPath)) return provider;\n }\n return null;\n }\n\n async listSessions(query: ContextQuery): Promise<SessionListResult | null> {\n for (const provider of this.providers) {\n if (!(await provider.isAvailable(query.repoPath))) continue;\n const result = await provider.listSessions(query);\n if (result.sessions.length > 0) return result;\n }\n return null;\n }\n\n async buildContext(query: ContextQuery, options?: ContextOptions): Promise<ContextResult | null> {\n const queryKey = `${query.type}:${query.value}:${options?.limit ?? \"\"}:${options?.maxTokens ?? \"\"}:${options?.labelAgent ?? \"\"}`;\n const cached = this.cache.get(query.repoPath, queryKey);\n if (cached) return cached;\n\n for (const provider of this.providers) {\n if (!(await provider.isAvailable(query.repoPath))) continue;\n const result = await provider.buildContext(query, options);\n if (result && result.markdown) {\n this.cache.set(query.repoPath, queryKey, result);\n return result;\n }\n }\n return null;\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as crypto from \"node:crypto\";\nimport type { ContextResult } from \"./context-provider.js\";\n\nconst DEFAULT_TTL_MS = 60 * 60 * 1000;\n\nexport class ContextCache {\n constructor(private cacheDir: string, private ttlMs: number = DEFAULT_TTL_MS) {\n fs.mkdirSync(cacheDir, { recursive: true });\n }\n\n private keyHash(repoPath: string, queryKey: string): string {\n return crypto.createHash(\"sha256\").update(`${repoPath}:${queryKey}`).digest(\"hex\").slice(0, 16);\n }\n\n private filePath(repoPath: string, queryKey: string): string {\n return path.join(this.cacheDir, `${this.keyHash(repoPath, queryKey)}.json`);\n }\n\n get(repoPath: string, queryKey: string): ContextResult | null {\n const fp = this.filePath(repoPath, queryKey);\n try {\n const stat = fs.statSync(fp);\n if (Date.now() - stat.mtimeMs > this.ttlMs) { fs.unlinkSync(fp); return null; }\n return JSON.parse(fs.readFileSync(fp, \"utf-8\")) as ContextResult;\n } catch { return null; }\n }\n\n set(repoPath: string, queryKey: string, result: ContextResult): void {\n fs.writeFileSync(this.filePath(repoPath, queryKey), JSON.stringify(result));\n }\n}\n","// NOTE: This interface is designed around Entire as the first provider.\n// It may evolve when additional providers (Cursor history, Zed, etc.) are added.\n// Providers may only support a subset of query types and should return empty results\n// for unsupported types rather than throwing.\n\nexport interface ContextProvider {\n readonly name: string;\n isAvailable(repoPath: string): Promise<boolean>;\n listSessions(query: ContextQuery): Promise<SessionListResult>;\n buildContext(query: ContextQuery, options?: ContextOptions): Promise<ContextResult>;\n}\n\nexport interface ContextQuery {\n repoPath: string;\n type: \"branch\" | \"commit\" | \"pr\" | \"latest\" | \"checkpoint\" | \"session\";\n value: string;\n}\n\nexport interface ContextOptions {\n maxTokens?: number;\n limit?: number;\n /** When true, insert `## [agentName]` headers at agent boundaries in merged history */\n labelAgent?: boolean;\n}\n\nexport interface SessionInfo {\n checkpointId: string;\n sessionIndex: string;\n transcriptPath: string;\n createdAt: string;\n endedAt: string;\n branch: string;\n agent: string;\n turnCount: number;\n filesTouched: string[];\n sessionId: string;\n}\n\nexport interface SessionListResult {\n sessions: SessionInfo[];\n estimatedTokens: number;\n}\n\nexport type ContextMode = \"full\" | \"balanced\" | \"compact\";\n\nexport interface ContextResult {\n markdown: string;\n tokenEstimate: number;\n sessionCount: number;\n totalTurns: number;\n mode: ContextMode;\n truncated: boolean;\n timeRange: { start: string; end: string };\n}\n\nexport const DEFAULT_MAX_TOKENS = 30_000;\nexport const TOKENS_PER_TURN_ESTIMATE = 400;\n","import { execFileSync } from \"child_process\";\nimport type { SessionInfo } from \"../context-provider.js\";\n\n// ─── Internal types ────────────────────────────────────────────────────────────\n\ninterface CheckpointMeta {\n checkpoint_id?: string;\n branch?: string;\n files_touched?: string[];\n sessions: Array<{\n metadata: string;\n transcript: string;\n }>;\n}\n\ninterface SessionMeta {\n session_id?: string;\n created_at?: string;\n branch?: string;\n agent?: string;\n files_touched?: string[];\n session_metrics?: {\n turn_count?: number;\n };\n}\n\n// ─── CheckpointReader ─────────────────────────────────────────────────────────\n\nconst ENTIRE_BRANCH = \"origin/entire/checkpoints/v1\";\nconst CHECKPOINT_ID_RE = /^[0-9a-f]{12}$/;\nconst SESSION_ID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\nexport class CheckpointReader {\n constructor(private readonly repoPath: string) {}\n\n // ─── Git execution ───────────────────────────────────────────────────────────\n\n /**\n * Run a git command in the repo directory.\n * Returns trimmed stdout on success, empty string on failure.\n */\n private git(...args: string[]): string {\n try {\n return execFileSync(\"git\", [\"-C\", this.repoPath, ...args], {\n encoding: \"utf-8\",\n }).trim();\n } catch {\n return \"\";\n }\n }\n\n // ─── Static helpers ──────────────────────────────────────────────────────────\n\n /**\n * Convert a 12-char checkpoint ID to its shard path: \"f634acf05138\" → \"f6/34acf05138\"\n */\n static shardPath(cpId: string): string {\n return `${cpId.slice(0, 2)}/${cpId.slice(2)}`;\n }\n\n /**\n * Returns true when value looks like a 12-char lowercase hex checkpoint ID.\n */\n static isCheckpointId(value: string): boolean {\n return CHECKPOINT_ID_RE.test(value);\n }\n\n /**\n * Returns true when value looks like a UUID (session ID).\n */\n static isSessionId(value: string): boolean {\n return SESSION_ID_RE.test(value);\n }\n\n /**\n * Parse checkpoint-level metadata JSON. Returns null on error.\n */\n static parseCheckpointMeta(json: string): CheckpointMeta | null {\n try {\n const parsed = JSON.parse(json) as CheckpointMeta;\n if (!parsed || typeof parsed !== \"object\") return null;\n if (!Array.isArray(parsed.sessions)) return null;\n return parsed;\n } catch {\n return null;\n }\n }\n\n /**\n * Extract Entire-Checkpoint trailer IDs from `git log --format=\"%H|%(trailers:...)\"` output.\n * Each line is: `<hash>|<trailer_value_or_empty>`. Returns only non-empty trailer values.\n * Uses the last pipe on each line to locate the trailer value, to be robust against\n * subject lines that contain pipes.\n */\n static parseCheckpointTrailers(output: string): string[] {\n const ids: string[] = [];\n for (const line of output.split(\"\\n\")) {\n const pipe = line.lastIndexOf(\"|\");\n if (pipe === -1) continue;\n const trailerId = line.slice(pipe + 1).trim();\n if (trailerId) ids.push(trailerId);\n }\n return ids;\n }\n\n // ─── Branch check ────────────────────────────────────────────────────────────\n\n async hasEntireBranch(): Promise<boolean> {\n const out = this.git(\"branch\", \"-r\");\n return out.includes(\"entire/checkpoints/v1\");\n }\n\n // ─── Core session fetching ───────────────────────────────────────────────────\n\n private listAllCheckpointIds(): string[] {\n const out = this.git(\n \"ls-tree\",\n \"-r\",\n ENTIRE_BRANCH,\n \"--name-only\"\n );\n if (!out) return [];\n\n const ids = new Set<string>();\n for (const file of out.split(\"\\n\")) {\n const parts = file.split(\"/\");\n // Checkpoint-level metadata: XX/YYYYYYYYYY/metadata.json (3 parts)\n if (parts.length === 3 && parts[2] === \"metadata.json\") {\n ids.add(parts[0] + parts[1]);\n }\n }\n return [...ids];\n }\n\n private fetchCheckpointMeta(cpId: string): CheckpointMeta | null {\n const shard = CheckpointReader.shardPath(cpId);\n const raw = this.git(\"show\", `${ENTIRE_BRANCH}:${shard}/metadata.json`);\n if (!raw) return null;\n return CheckpointReader.parseCheckpointMeta(raw);\n }\n\n private fetchSessionMeta(metaPath: string): SessionMeta {\n const normalized = metaPath.startsWith(\"/\") ? metaPath.slice(1) : metaPath;\n const raw = this.git(\"show\", `${ENTIRE_BRANCH}:${normalized}`);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as SessionMeta;\n } catch {\n return {};\n }\n }\n\n /**\n * Build SessionInfo[] from a single checkpoint's metadata.\n */\n private buildSessionsForCheckpoint(\n cpId: string,\n cpMeta: CheckpointMeta\n ): SessionInfo[] {\n const sessions: SessionInfo[] = [];\n\n for (let idx = 0; idx < cpMeta.sessions.length; idx++) {\n const sess = cpMeta.sessions[idx];\n const transcriptPath = (sess.transcript ?? \"\").replace(/^\\//, \"\");\n const metaPath = sess.metadata ?? \"\";\n\n const smeta = this.fetchSessionMeta(metaPath);\n const createdAt = smeta.created_at ?? \"\";\n\n sessions.push({\n checkpointId: cpId,\n sessionIndex: String(idx),\n transcriptPath,\n createdAt,\n endedAt: createdAt, // will be filled from JSONL by conversation builder\n branch: smeta.branch ?? cpMeta.branch ?? \"\",\n agent: smeta.agent ?? \"\",\n turnCount: smeta.session_metrics?.turn_count ?? 0,\n filesTouched: smeta.files_touched ?? cpMeta.files_touched ?? [],\n sessionId: smeta.session_id ?? \"\",\n });\n }\n\n return sessions;\n }\n\n private getSessionsForCheckpoint(cpId: string): SessionInfo[] {\n const meta = this.fetchCheckpointMeta(cpId);\n if (!meta) return [];\n return this.buildSessionsForCheckpoint(cpId, meta);\n }\n\n // ─── Public resolvers ────────────────────────────────────────────────────────\n\n /**\n * All sessions recorded on a given branch, sorted by createdAt ascending.\n */\n async resolveByBranch(branchName: string): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n const sessions: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n const meta = this.fetchCheckpointMeta(cpId);\n if (!meta) continue;\n if (meta.branch !== branchName) continue;\n sessions.push(...this.buildSessionsForCheckpoint(cpId, meta));\n }\n\n sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return sessions;\n }\n\n /**\n * Sessions linked to a specific commit via the Entire-Checkpoint git trailer.\n */\n async resolveByCommit(commitHash: string): Promise<SessionInfo[]> {\n const fullHash = this.git(\"rev-parse\", commitHash);\n if (!fullHash) return [];\n\n const cpId = this.git(\n \"log\",\n \"-1\",\n \"--format=%(trailers:key=Entire-Checkpoint,valueonly)\",\n fullHash\n );\n if (!cpId) return [];\n\n return this.getSessionsForCheckpoint(cpId.trim());\n }\n\n /**\n * All sessions from a merged PR (by number or GitHub URL).\n */\n async resolveByPr(prInput: string): Promise<SessionInfo[]> {\n let prNumber: string;\n\n if (/^\\d+$/.test(prInput)) {\n prNumber = prInput;\n } else {\n const m = /\\/pull\\/(\\d+)/.exec(prInput);\n if (!m) return [];\n prNumber = m[1];\n }\n\n const mergeOut = this.git(\n \"log\",\n \"--all\",\n \"--oneline\",\n \"--grep\",\n `Merge pull request #${prNumber}`\n );\n if (!mergeOut) return [];\n\n const mergeCommit = mergeOut.split(\"\\n\")[0].split(\" \")[0];\n\n const logOut = this.git(\n \"log\",\n \"--format=%H|%(trailers:key=Entire-Checkpoint,valueonly)\",\n `${mergeCommit}^2`,\n \"--not\",\n `${mergeCommit}^1`\n );\n if (!logOut) return [];\n\n const cpIds = CheckpointReader.parseCheckpointTrailers(logOut);\n const sessions: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n sessions.push(...this.getSessionsForCheckpoint(cpId));\n }\n\n sessions.sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return sessions;\n }\n\n /**\n * Sessions matching a specific checkpoint ID.\n */\n async resolveByCheckpoint(checkpointId: string): Promise<SessionInfo[]> {\n return this.getSessionsForCheckpoint(checkpointId);\n }\n\n /**\n * Find a session by its UUID.\n */\n async resolveBySessionId(sessionId: string): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n\n for (const cpId of cpIds) {\n const sessions = this.getSessionsForCheckpoint(cpId);\n const match = sessions.find((s) => s.sessionId === sessionId);\n if (match) return [match];\n }\n\n return [];\n }\n\n /**\n * Latest N sessions across all checkpoints, sorted by createdAt descending.\n */\n async resolveLatest(count: number): Promise<SessionInfo[]> {\n const cpIds = this.listAllCheckpointIds();\n const all: SessionInfo[] = [];\n\n for (const cpId of cpIds) {\n all.push(...this.getSessionsForCheckpoint(cpId));\n }\n\n all.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n return all.slice(0, count);\n }\n\n /**\n * Read the full JSONL transcript content from the entire branch.\n */\n getTranscript(transcriptPath: string): string {\n const normalized = transcriptPath.startsWith(\"/\")\n ? transcriptPath.slice(1)\n : transcriptPath;\n return this.git(\"show\", `${ENTIRE_BRANCH}:${normalized}`);\n }\n}\n","const SYSTEM_TAG_PATTERNS: RegExp[] = [\n /<system-reminder>[\\s\\S]*?<\\/system-reminder>/g,\n /<local-command-caveat>[\\s\\S]*?<\\/local-command-caveat>/g,\n /<local-command-stdout>[\\s\\S]*?<\\/local-command-stdout>/g,\n /<command-name>[\\s\\S]*?<\\/command-name>/g,\n /<command-message>[\\s\\S]*?<\\/command-message>/g,\n /<user-prompt-submit-hook>[\\s\\S]*?<\\/user-prompt-submit-hook>/g,\n /<ide_selection>[\\s\\S]*?<\\/ide_selection>/g,\n /<ide_context>[\\s\\S]*?<\\/ide_context>/g,\n /<ide_opened_file>[\\s\\S]*?<\\/ide_opened_file>/g,\n /<cursor_context>[\\s\\S]*?<\\/cursor_context>/g,\n /<attached_files>[\\s\\S]*?<\\/attached_files>/g,\n /<repo_context>[\\s\\S]*?<\\/repo_context>/g,\n /<task-notification>[\\s\\S]*?<\\/task-notification>/g,\n];\n\nconst COMMAND_ARGS_RE = /<command-args>([\\s\\S]*?)<\\/command-args>/;\n\nexport function cleanSystemTags(text: string): string {\n const argsMatch = COMMAND_ARGS_RE.exec(text);\n const userArgs = argsMatch?.[1]?.trim() ?? \"\";\n text = text.replace(/<command-args>[\\s\\S]*?<\\/command-args>/g, \"\");\n for (const pat of SYSTEM_TAG_PATTERNS) {\n text = text.replace(new RegExp(pat.source, pat.flags), \"\");\n }\n text = text.trim();\n if (!text && userArgs) return userArgs;\n if (text && userArgs && text !== userArgs) return `${text}\\n${userArgs}`;\n return text || userArgs;\n}\n\nconst SKILL_INDICATORS = [\n \"Base directory for this skill:\",\n \"<HARD-GATE>\",\n \"## Checklist\",\n \"## Process Flow\",\n \"## Key Principles\",\n \"digraph brainstorming\",\n \"You MUST create a task for each\",\n];\n\nexport function isSkillPrompt(text: string): boolean {\n for (const indicator of SKILL_INDICATORS) {\n if (text.includes(indicator)) return true;\n }\n if (text.length > 2000) {\n const headerCount = (text.match(/## /g) || []).length;\n if (headerCount >= 3) return true;\n }\n return false;\n}\n\nexport function isNoiseMessage(text: string): boolean {\n const cleaned = cleanSystemTags(text);\n if (!cleaned) return true;\n if (/^(ready|ready\\.)$/i.test(cleaned)) return true;\n if (cleaned.includes(\"Tell your human partner that this command is deprecated\")) return true;\n if (cleaned.startsWith(\"Read the output file to retrieve the result:\")) return true;\n if (/^(opus|sonnet|haiku|claude)(\\[.*\\])?$/i.test(cleaned)) return true;\n return false;\n}\n","import type { ContextMode } from \"../context-provider.js\";\nimport { cleanSystemTags, isSkillPrompt, isNoiseMessage } from \"./message-cleaner.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface AssistantPart {\n type: \"text\" | \"edit\" | \"write\";\n content?: string;\n file?: string;\n old?: string;\n new?: string;\n fileContent?: string;\n}\n\nexport interface Turn {\n userText: string;\n userTimestamp: string;\n assistantParts: AssistantPart[];\n}\n\nexport interface ParseResult {\n turns: Turn[];\n branch: string;\n firstTimestamp: string;\n lastTimestamp: string;\n}\n\nexport interface SessionMarkdownInput {\n markdown: string;\n startTime: string;\n endTime: string;\n agent: string;\n turns: number;\n branch: string;\n files: string[];\n}\n\n// ─── Mode selection ────────────────────────────────────────────────────────────\n\n/**\n * Select rendering mode based on total turn count.\n * ≤10 → full\n * 11-25 → balanced\n * >25 → compact\n */\nexport function selectMode(totalTurns: number): ContextMode {\n if (totalTurns <= 10) return \"full\";\n if (totalTurns <= 25) return \"balanced\";\n return \"compact\";\n}\n\n// ─── Token estimation ─────────────────────────────────────────────────────────\n\nexport function estimateTokens(text: string): number {\n return Math.floor(text.length / 4);\n}\n\n// ─── Path helpers ─────────────────────────────────────────────────────────────\n\nfunction shortenPath(fp: string): string {\n const parts = fp.split(\"/\");\n if (parts.length >= 2) return parts.slice(-2).join(\"/\");\n return fp;\n}\n\nfunction countLines(s: string): number {\n const trimmed = s.trim();\n if (!trimmed) return 0;\n return trimmed.split(\"\\n\").length;\n}\n\n// ─── Content extraction ───────────────────────────────────────────────────────\n\ntype ContentBlock = { type: string; [key: string]: unknown };\n\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter((b): b is ContentBlock => typeof b === \"object\" && b !== null && (b as ContentBlock).type === \"text\")\n .map((b) => (b as unknown as { text: string }).text)\n .join(\"\\n\");\n }\n return \"\";\n}\n\nfunction extractContentBlocks(content: unknown): ContentBlock[] {\n if (typeof content === \"string\") return [{ type: \"text\", text: content }];\n if (Array.isArray(content)) {\n return content.filter((b): b is ContentBlock => typeof b === \"object\" && b !== null);\n }\n return [];\n}\n\nfunction isToolResultOnly(content: unknown): boolean {\n if (typeof content === \"string\") return false;\n if (!Array.isArray(content)) return true;\n for (const block of content) {\n if (typeof block === \"object\" && block !== null) {\n const b = block as ContentBlock;\n if (b.type === \"text\" && typeof b.text === \"string\" && (b.text as string).trim()) return false;\n if (b.type === \"image\") return false;\n }\n }\n return true;\n}\n\nfunction hasImage(content: unknown): boolean {\n if (!Array.isArray(content)) return false;\n return content.some((b) => typeof b === \"object\" && b !== null && (b as ContentBlock).type === \"image\");\n}\n\n// ─── Format functions ─────────────────────────────────────────────────────────\n\nfunction formatEditFull(filePath: string, oldStr: string, newStr: string): string {\n const lines: string[] = [];\n lines.push(`✏️ \\`${filePath}\\``);\n lines.push(\"```diff\");\n for (const line of oldStr.split(\"\\n\")) lines.push(`- ${line}`);\n for (const line of newStr.split(\"\\n\")) lines.push(`+ ${line}`);\n lines.push(\"```\");\n return lines.join(\"\\n\");\n}\n\nfunction formatEditBalanced(filePath: string, oldStr: string, newStr: string, maxDiffLines = 12): string {\n const oldLines = oldStr.split(\"\\n\");\n const newLines = newStr.split(\"\\n\");\n const total = oldLines.length + newLines.length;\n const lines: string[] = [];\n lines.push(`✏️ \\`${filePath}\\``);\n lines.push(\"```diff\");\n if (total <= maxDiffLines) {\n for (const line of oldLines) lines.push(`- ${line}`);\n for (const line of newLines) lines.push(`+ ${line}`);\n } else {\n const half = Math.floor(maxDiffLines / 2);\n for (const line of oldLines.slice(0, half)) lines.push(`- ${line}`);\n if (oldLines.length > half) lines.push(` ... (-${oldLines.length} lines total)`);\n for (const line of newLines.slice(0, half)) lines.push(`+ ${line}`);\n if (newLines.length > half) lines.push(` ... (+${newLines.length} lines total)`);\n }\n lines.push(\"```\");\n return lines.join(\"\\n\");\n}\n\nfunction formatEditCompact(filePath: string, oldStr: string, newStr: string): string {\n const oldLines = countLines(oldStr);\n const newLines = countLines(newStr);\n let firstNew = \"\";\n for (const line of newStr.split(\"\\n\")) {\n const stripped = line.trim();\n if (stripped && !stripped.startsWith(\"//\") && !stripped.startsWith(\"*\")) {\n firstNew = stripped.slice(0, 80);\n break;\n }\n }\n if (firstNew) {\n return `✏️ \\`${filePath}\\` (-${oldLines}/+${newLines} lines): \\`${firstNew}\\``;\n }\n return `✏️ \\`${filePath}\\` (-${oldLines}/+${newLines} lines)`;\n}\n\nfunction formatWriteFull(filePath: string, content: string): string {\n const lines: string[] = [];\n lines.push(`📝 \\`${filePath}\\``);\n lines.push(\"```\");\n lines.push(content);\n lines.push(\"```\");\n return lines.join(\"\\n\");\n}\n\nfunction formatWriteBalanced(filePath: string, content: string, maxLines = 15): string {\n const contentLines = content.split(\"\\n\");\n const lines: string[] = [];\n lines.push(`📝 \\`${filePath}\\` (${contentLines.length} lines)`);\n lines.push(\"```\");\n for (const line of contentLines.slice(0, maxLines)) lines.push(line);\n if (contentLines.length > maxLines) lines.push(`... (${contentLines.length - maxLines} more lines)`);\n lines.push(\"```\");\n return lines.join(\"\\n\");\n}\n\nfunction formatWriteCompact(filePath: string, content: string): string {\n const numLines = countLines(content);\n return `📝 \\`${filePath}\\` (${numLines} lines written)`;\n}\n\n// ─── Parser ───────────────────────────────────────────────────────────────────\n\ninterface RawEvent {\n type?: string;\n message?: { role?: string; content?: unknown };\n timestamp?: string;\n uuid?: string;\n parentUuid?: string | null;\n sessionId?: string;\n gitBranch?: string;\n}\n\nexport function parseJsonlToTurns(jsonl: string): ParseResult {\n const events: RawEvent[] = [];\n for (const rawLine of jsonl.split(\"\\n\")) {\n const line = rawLine.trim();\n if (!line) continue;\n try {\n events.push(JSON.parse(line) as RawEvent);\n } catch {\n // skip invalid JSON lines\n }\n }\n\n // Extract gitBranch from first event that has it\n let branch = \"unknown\";\n for (const e of events) {\n if (e.gitBranch) {\n branch = e.gitBranch;\n break;\n }\n }\n\n const convEvents = events.filter((e) => e.type === \"user\" || e.type === \"assistant\");\n\n const turns: Turn[] = [];\n let currentTurn: Turn | null = null;\n\n for (const e of convEvents) {\n const etype = e.type;\n const content = e.message?.content ?? [];\n const ts = e.timestamp ?? \"\";\n\n if (etype === \"user\") {\n if (isToolResultOnly(content)) continue;\n\n const text = extractText(content);\n\n if (isSkillPrompt(text)) continue;\n if (isNoiseMessage(text)) continue;\n\n const cleaned = cleanSystemTags(text);\n if (!cleaned) continue;\n\n // Push previous turn if any\n if (currentTurn) turns.push(currentTurn);\n\n const imgSuffix = hasImage(content) ? \" [image]\" : \"\";\n currentTurn = {\n userText: cleaned + imgSuffix,\n userTimestamp: ts,\n assistantParts: [],\n };\n } else if (etype === \"assistant\" && currentTurn) {\n const blocks = extractContentBlocks(content);\n let pendingText: string | null = null;\n\n for (const block of blocks) {\n const btype = block.type;\n\n if (btype === \"text\") {\n const text = typeof block.text === \"string\" ? (block.text as string).trim() : \"\";\n if (text) pendingText = text;\n } else if (btype === \"tool_use\") {\n const name = typeof block.name === \"string\" ? block.name : \"\";\n const inp = (typeof block.input === \"object\" && block.input !== null ? block.input : {}) as Record<string, string>;\n\n if (name === \"Edit\") {\n if (pendingText) {\n currentTurn.assistantParts.push({ type: \"text\", content: pendingText });\n pendingText = null;\n }\n currentTurn.assistantParts.push({\n type: \"edit\",\n file: shortenPath(inp.file_path ?? \"\"),\n old: inp.old_string ?? \"\",\n new: inp.new_string ?? \"\",\n });\n } else if (name === \"Write\") {\n if (pendingText) {\n currentTurn.assistantParts.push({ type: \"text\", content: pendingText });\n pendingText = null;\n }\n currentTurn.assistantParts.push({\n type: \"write\",\n file: shortenPath(inp.file_path ?? \"\"),\n fileContent: inp.content ?? \"\",\n });\n }\n // Skip Read, Bash, Grep, Glob, etc.\n }\n }\n\n if (pendingText) {\n currentTurn.assistantParts.push({ type: \"text\", content: pendingText });\n }\n }\n }\n\n if (currentTurn) turns.push(currentTurn);\n\n const firstTimestamp = turns[0]?.userTimestamp ?? \"\";\n const lastTimestamp = turns[turns.length - 1]?.userTimestamp ?? \"\";\n\n return { turns, branch, firstTimestamp, lastTimestamp };\n}\n\n// ─── Markdown builder ─────────────────────────────────────────────────────────\n\nexport function buildSessionMarkdown(turns: Turn[], mode: ContextMode): string {\n const out: string[] = [];\n\n for (let i = 0; i < turns.length; i++) {\n const turn = turns[i];\n const userText = turn.userText.trim();\n if (!userText) continue;\n\n out.push(`**User [${i + 1}]:**`);\n out.push(userText);\n out.push(\"\");\n\n let hasContent = false;\n\n for (const part of turn.assistantParts) {\n if (part.type === \"text\") {\n if (!hasContent) {\n out.push(\"**Assistant:**\");\n hasContent = true;\n }\n out.push(part.content ?? \"\");\n out.push(\"\");\n } else if (part.type === \"edit\") {\n if (!hasContent) {\n out.push(\"**Assistant:**\");\n hasContent = true;\n }\n const file = part.file ?? \"\";\n const oldStr = part.old ?? \"\";\n const newStr = part.new ?? \"\";\n if (mode === \"full\") {\n out.push(formatEditFull(file, oldStr, newStr));\n } else if (mode === \"balanced\") {\n out.push(formatEditBalanced(file, oldStr, newStr));\n } else {\n out.push(formatEditCompact(file, oldStr, newStr));\n }\n out.push(\"\");\n } else if (part.type === \"write\") {\n if (!hasContent) {\n out.push(\"**Assistant:**\");\n hasContent = true;\n }\n const file = part.file ?? \"\";\n const content = part.fileContent ?? \"\";\n if (mode === \"full\") {\n out.push(formatWriteFull(file, content));\n } else if (mode === \"balanced\") {\n out.push(formatWriteBalanced(file, content));\n } else {\n out.push(formatWriteCompact(file, content));\n }\n out.push(\"\");\n }\n }\n\n out.push(\"---\");\n out.push(\"\");\n }\n\n return out.join(\"\\n\");\n}\n\n// ─── Session merger ───────────────────────────────────────────────────────────\n\nconst DISCLAIMER = `> **Note:** This conversation history may contain outdated information. File contents, code, and project state may have changed since these sessions were recorded. Use this as context only — always verify against current files before acting.`;\n\nexport function mergeSessionsMarkdown(\n sessions: SessionMarkdownInput[],\n mode: ContextMode,\n title: string\n): string {\n // Sort sessions chronologically (oldest first)\n const sorted = [...sessions].sort((a, b) => a.startTime.localeCompare(b.startTime));\n\n const totalTurns = sorted.reduce((sum, s) => sum + s.turns, 0);\n const overallStart = sorted[0]?.startTime.slice(0, 16) ?? \"?\";\n const overallEnd = sorted[sorted.length - 1]?.endTime.slice(0, 16) ?? \"?\";\n\n const out: string[] = [];\n out.push(`# Conversation History from ${title}`);\n out.push(`${sorted.length} sessions | ${totalTurns} turns | ${overallStart} → ${overallEnd} | mode: ${mode}`);\n out.push(\"\");\n\n for (let i = 0; i < sorted.length; i++) {\n const s = sorted[i];\n const start = s.startTime.slice(0, 16);\n const end = s.endTime.slice(0, 16);\n out.push(`## Session Conversation History ${i + 1} — ${start} → ${end} (${s.agent}, ${s.turns} turns, branch: ${s.branch})`);\n out.push(\"\");\n out.push(s.markdown);\n }\n\n out.push(DISCLAIMER);\n out.push(\"\");\n\n return out.join(\"\\n\");\n}\n","import type { ContextProvider, ContextQuery, ContextOptions, ContextResult, SessionListResult, SessionInfo } from \"../context-provider.js\";\nimport type { ContextMode } from \"../context-provider.js\";\nimport { DEFAULT_MAX_TOKENS, TOKENS_PER_TURN_ESTIMATE } from \"../context-provider.js\";\nimport { CheckpointReader } from \"./checkpoint-reader.js\";\nimport { parseJsonlToTurns, buildSessionMarkdown, mergeSessionsMarkdown, selectMode, estimateTokens, type SessionMarkdownInput } from \"./conversation-builder.js\";\n\nexport class EntireProvider implements ContextProvider {\n readonly name = \"entire\";\n\n async isAvailable(repoPath: string): Promise<boolean> {\n return new CheckpointReader(repoPath).hasEntireBranch();\n }\n\n async listSessions(query: ContextQuery): Promise<SessionListResult> {\n const reader = new CheckpointReader(query.repoPath);\n const sessions = await this.resolveSessions(reader, query);\n const estimatedTokens = sessions.reduce((sum, s) => sum + s.turnCount * TOKENS_PER_TURN_ESTIMATE, 0);\n return { sessions, estimatedTokens };\n }\n\n async buildContext(query: ContextQuery, options?: ContextOptions): Promise<ContextResult> {\n const maxTokens = options?.maxTokens ?? DEFAULT_MAX_TOKENS;\n const reader = new CheckpointReader(query.repoPath);\n let sessions = await this.resolveSessions(reader, query);\n\n if (options?.limit && sessions.length > options.limit) {\n sessions = sessions.slice(-options.limit);\n }\n\n if (sessions.length === 0) {\n return { markdown: \"\", tokenEstimate: 0, sessionCount: 0, totalTurns: 0, mode: \"full\", truncated: false, timeRange: { start: \"\", end: \"\" } };\n }\n\n // Rebuild each session, cache parsed turns for potential re-render\n const parsedSessions: { session: SessionInfo; jsonl: string; }[] = [];\n for (const sess of sessions) {\n const jsonl = reader.getTranscript(sess.transcriptPath);\n if (jsonl) parsedSessions.push({ session: sess, jsonl });\n }\n\n if (parsedSessions.length === 0) {\n return { markdown: \"\", tokenEstimate: 0, sessionCount: 0, totalTurns: 0, mode: \"full\", truncated: false, timeRange: { start: \"\", end: \"\" } };\n }\n\n const totalTurns = parsedSessions.reduce((sum, ps) => {\n const parsed = parseJsonlToTurns(ps.jsonl);\n return sum + parsed.turns.length;\n }, 0);\n\n let mode = selectMode(totalTurns);\n const title = this.buildTitle(query);\n\n // Build markdown for each session\n let sessionMarkdowns = this.buildSessionMarkdowns(parsedSessions, mode);\n let merged = mergeSessionsMarkdown(sessionMarkdowns, mode, title);\n let tokens = estimateTokens(merged);\n\n // Auto-downgrade to compact if over budget\n if (tokens > maxTokens && mode !== \"compact\") {\n mode = \"compact\";\n sessionMarkdowns = this.buildSessionMarkdowns(parsedSessions, \"compact\");\n merged = mergeSessionsMarkdown(sessionMarkdowns, \"compact\", title);\n tokens = estimateTokens(merged);\n }\n\n // Truncate oldest sessions if still over budget\n let truncated = false;\n while (tokens > maxTokens && sessionMarkdowns.length > 1) {\n sessionMarkdowns = sessionMarkdowns.slice(1);\n truncated = true;\n merged = mergeSessionsMarkdown(sessionMarkdowns, mode, title);\n tokens = estimateTokens(merged);\n }\n\n const allTimes = sessionMarkdowns.flatMap(s => [s.startTime, s.endTime]).filter(Boolean).sort();\n const finalTurns = sessionMarkdowns.reduce((sum, s) => sum + s.turns, 0);\n\n return {\n markdown: merged,\n tokenEstimate: tokens,\n sessionCount: sessionMarkdowns.length,\n totalTurns: finalTurns,\n mode,\n truncated,\n timeRange: { start: allTimes[0] ?? \"\", end: allTimes[allTimes.length - 1] ?? \"\" },\n };\n }\n\n private buildSessionMarkdowns(parsedSessions: { session: SessionInfo; jsonl: string }[], mode: ContextMode): SessionMarkdownInput[] {\n return parsedSessions.map(ps => {\n const parsed = parseJsonlToTurns(ps.jsonl);\n return {\n markdown: buildSessionMarkdown(parsed.turns, mode),\n startTime: parsed.firstTimestamp,\n endTime: parsed.lastTimestamp,\n agent: ps.session.agent,\n turns: parsed.turns.length,\n branch: ps.session.branch,\n files: ps.session.filesTouched.map(f => f.split(\"/\").pop() ?? f),\n };\n });\n }\n\n private async resolveSessions(reader: CheckpointReader, query: ContextQuery): Promise<SessionInfo[]> {\n switch (query.type) {\n case \"branch\": return reader.resolveByBranch(query.value);\n case \"commit\": return reader.resolveByCommit(query.value);\n case \"pr\": return reader.resolveByPr(query.value);\n case \"checkpoint\": return reader.resolveByCheckpoint(query.value);\n case \"session\": return reader.resolveBySessionId(query.value);\n case \"latest\": return reader.resolveLatest(parseInt(query.value) || 5);\n default: return [];\n }\n }\n\n private buildTitle(query: ContextQuery): string {\n switch (query.type) {\n case \"pr\": return `PR #${query.value.replace(/.*\\/pull\\//, \"\")}`;\n case \"branch\": return `branch \\`${query.value}\\``;\n case \"commit\": return `commit \\`${query.value.slice(0, 8)}\\``;\n case \"checkpoint\": return `checkpoint \\`${query.value}\\``;\n case \"session\": return `session \\`${query.value.slice(0, 8)}...\\``;\n case \"latest\": return `latest ${query.value} sessions`;\n default: return \"unknown\";\n }\n }\n}\n","// src/adapters/shared/format-types.ts\n\nexport type OutputMode = \"low\" | \"medium\" | \"high\";\n/** @deprecated Use OutputMode instead */\nexport type DisplayVerbosity = OutputMode;\n\nexport type NoiseAction = \"hide\" | \"collapse\";\n\nexport interface NoiseRule {\n match: (name: string, kind: string, rawInput: unknown) => boolean;\n action: NoiseAction;\n}\n\nexport type MessageStyle =\n | \"text\"\n | \"thought\"\n | \"tool\"\n | \"plan\"\n | \"usage\"\n | \"system\"\n | \"error\"\n | \"attachment\";\n\nexport interface MessageMetadata {\n toolName?: string;\n toolStatus?: string;\n toolKind?: string;\n filePath?: string;\n command?: string;\n planEntries?: { content: string; status: string }[];\n tokens?: number;\n contextSize?: number;\n cost?: number;\n viewerLinks?: ViewerLinks;\n viewerFilePath?: string;\n}\n\n/** summary and detail are always plain text (never pre-escaped HTML/markdown) — renderers handle escaping */\nexport interface FormattedMessage {\n summary: string;\n detail?: string;\n viewerLinks?: ViewerLinks;\n icon: string;\n originalType: string;\n style: MessageStyle;\n metadata?: MessageMetadata;\n}\n\nexport const STATUS_ICONS: Record<string, string> = {\n pending: \"⏳\",\n in_progress: \"🔄\",\n completed: \"✅\",\n failed: \"❌\",\n cancelled: \"🚫\",\n running: \"🔄\",\n done: \"✅\",\n error: \"❌\",\n};\n\nexport const KIND_ICONS: Record<string, string> = {\n read: \"📖\",\n edit: \"✏️\",\n write: \"✏️\",\n delete: \"🗑️\",\n execute: \"▶️\",\n command: \"▶️\",\n bash: \"▶️\",\n terminal: \"▶️\",\n search: \"🔍\",\n web: \"🌐\",\n fetch: \"🌐\",\n agent: \"🧠\",\n think: \"🧠\",\n install: \"📦\",\n move: \"📦\",\n other: \"🛠️\",\n};\n\nexport const KIND_LABELS: Record<string, string> = {\n read: \"Read\",\n edit: \"Edit\",\n write: \"Write\",\n delete: \"Delete\",\n execute: \"Run\",\n bash: \"Bash\",\n command: \"Run\",\n terminal: \"Terminal\",\n search: \"Search\",\n web: \"Web\",\n fetch: \"Fetch\",\n agent: \"Agent\",\n think: \"Agent\",\n install: \"Install\",\n move: \"Move\",\n};\n\nexport interface ViewerLinks {\n file?: string;\n diff?: string;\n}\n\nexport interface ToolCallMeta {\n id: string;\n name: string;\n kind?: string;\n status?: string;\n content?: unknown;\n rawInput?: unknown;\n viewerLinks?: ViewerLinks;\n viewerFilePath?: string;\n displaySummary?: string;\n displayTitle?: string;\n displayKind?: string;\n}\n\nexport interface ToolUpdateMeta extends ToolCallMeta {\n status: string;\n}\n","import type { NoiseAction, NoiseRule } from \"./format-types.js\";\nimport { STATUS_ICONS, KIND_ICONS } from \"./format-types.js\";\n\nexport function extractContentText(content: unknown, depth = 0): string {\n if (!content || depth > 5) return \"\";\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((c) => extractContentText(c, depth + 1))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (typeof content !== \"object\") return String(content);\n\n const obj = content as Record<string, unknown>;\n if (obj.text && typeof obj.text === \"string\") return obj.text;\n if (obj.content) {\n if (typeof obj.content === \"string\") return obj.content;\n if (Array.isArray(obj.content)) {\n return obj.content\n .map((c) => extractContentText(c, depth + 1))\n .filter(Boolean)\n .join(\"\\n\");\n }\n return extractContentText(obj.content, depth + 1);\n }\n if (obj.input) return extractContentText(obj.input, depth + 1);\n if (obj.output) return extractContentText(obj.output, depth + 1);\n\n // Skip objects with only a 'type' key and no content fields\n const keys = Object.keys(obj).filter((k) => k !== \"type\");\n if (keys.length === 0) return \"\";\n\n // Fallback: serialize unrecognized objects so edge-case agent responses are not silently dropped\n try {\n return JSON.stringify(obj, null, 2);\n } catch {\n return \"\";\n }\n}\n\nfunction parseRawInput(rawInput: unknown): Record<string, unknown> {\n try {\n if (typeof rawInput === \"string\") {\n return JSON.parse(rawInput) as Record<string, unknown>;\n }\n if (typeof rawInput === \"object\" && rawInput !== null) {\n return rawInput as Record<string, unknown>;\n }\n } catch {\n // fall through\n }\n return {};\n}\n\n// --- Step 5: formatToolSummary with displaySummary override ---\n\nexport function formatToolSummary(\n name: string,\n rawInput: unknown,\n displaySummary?: string,\n): string {\n if (displaySummary && typeof displaySummary === \"string\") {\n return displaySummary;\n }\n\n const args = parseRawInput(rawInput);\n const lowerName = name.toLowerCase();\n\n if (lowerName === \"read\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n const limit = args.limit ? ` (${args.limit} lines)` : \"\";\n return fp ? `📖 Read ${fp}${limit}` : `🔧 ${name}`;\n }\n if (lowerName === \"edit\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n return fp ? `✏️ Edit ${fp}` : `🔧 ${name}`;\n }\n if (lowerName === \"write\") {\n const fp = args.file_path ?? args.filePath ?? \"\";\n return fp ? `📝 Write ${fp}` : `🔧 ${name}`;\n }\n if (lowerName === \"bash\" || lowerName === \"terminal\") {\n const cmd = String(args.command ?? args.cmd ?? \"\").slice(0, 60);\n return cmd ? `▶️ Run: ${cmd}` : `▶️ Terminal`;\n }\n if (lowerName === \"grep\") {\n const pattern = args.pattern ?? \"\";\n const path = args.path ?? \"\";\n return pattern\n ? `🔍 Grep \"${pattern}\"${path ? ` in ${path}` : \"\"}`\n : `🔧 ${name}`;\n }\n if (lowerName === \"glob\") {\n const pattern = args.pattern ?? \"\";\n return pattern ? `🔍 Glob ${pattern}` : `🔧 ${name}`;\n }\n if (lowerName === \"agent\") {\n const desc = String(args.description ?? \"\").slice(0, 60);\n return desc ? `🧠 Agent: ${desc}` : `🔧 ${name}`;\n }\n if (lowerName === \"webfetch\" || lowerName === \"web_fetch\") {\n const url = String(args.url ?? \"\").slice(0, 60);\n return url ? `🌐 Fetch ${url}` : `🔧 ${name}`;\n }\n if (lowerName === \"websearch\" || lowerName === \"web_search\") {\n const query = String(args.query ?? \"\").slice(0, 60);\n return query ? `🌐 Search \"${query}\"` : `🔧 ${name}`;\n }\n\n return `🔧 ${name}`;\n}\n\n// --- Step 6: formatToolTitle for low verbosity ---\n\nexport function formatToolTitle(\n name: string,\n rawInput: unknown,\n displayTitle?: string,\n): string {\n if (displayTitle && typeof displayTitle === \"string\") {\n return displayTitle;\n }\n\n const args = parseRawInput(rawInput);\n const lowerName = name.toLowerCase();\n\n if ([\"read\", \"edit\", \"write\"].includes(lowerName)) {\n return String(args.file_path ?? args.filePath ?? name);\n }\n if (lowerName === \"bash\" || lowerName === \"terminal\") {\n return String(args.command ?? args.cmd ?? name).slice(0, 60);\n }\n if (lowerName === \"grep\") {\n const pattern = args.pattern ?? \"\";\n const path = args.path ?? \"\";\n return pattern ? `\"${pattern}\"${path ? ` in ${path}` : \"\"}` : name;\n }\n if (lowerName === \"glob\") {\n return String(args.pattern ?? name);\n }\n if (lowerName === \"agent\") {\n return String(args.description ?? name).slice(0, 60);\n }\n if ([\"webfetch\", \"web_fetch\"].includes(lowerName)) {\n return String(args.url ?? name).slice(0, 60);\n }\n if ([\"websearch\", \"web_search\"].includes(lowerName)) {\n return String(args.query ?? name).slice(0, 60);\n }\n\n return name;\n}\n\n// --- Step 7: resolveToolIcon ---\n\nexport function resolveToolIcon(tool: {\n status?: string;\n displayKind?: string;\n kind?: string;\n}): string {\n const statusIcon = STATUS_ICONS[tool.status || \"\"];\n if (statusIcon) return statusIcon;\n const kind = tool.displayKind ?? tool.kind;\n if (kind && KIND_ICONS[kind]) return KIND_ICONS[kind];\n return \"🔧\";\n}\n\n// --- Step 8: Noise filtering ---\n\nconst NOISE_RULES: NoiseRule[] = [\n {\n match: (name) => name.toLowerCase() === \"ls\",\n action: \"hide\",\n },\n {\n match: (_name, kind, rawInput) => {\n if (kind !== \"read\") return false;\n const args = parseRawInput(rawInput);\n const p = String(args.file_path ?? args.filePath ?? args.path ?? \"\");\n return p.endsWith(\"/\");\n },\n action: \"hide\",\n },\n {\n match: (name) => name.toLowerCase() === \"glob\",\n action: \"hide\",\n },\n {\n match: (name) => name.toLowerCase() === \"grep\",\n action: \"hide\",\n },\n];\n\nexport function evaluateNoise(\n name: string,\n kind: string,\n rawInput: unknown,\n): NoiseAction | null {\n for (const rule of NOISE_RULES) {\n if (rule.match(name, kind, rawInput)) return rule.action;\n }\n return null;\n}\n","import type {\n IChannelAdapter,\n ChannelConfig,\n AdapterCapabilities,\n} from \"../channel.js\";\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from \"../types.js\";\nimport type { DisplayVerbosity, ToolCallMeta } from \"./format-types.js\";\nimport type { IRenderer } from \"./rendering/renderer.js\";\nimport { evaluateNoise } from \"./message-formatter.js\";\n\nexport interface AdapterContext {\n configManager: { get(): Record<string, unknown> };\n fileService?: unknown;\n}\n\nexport interface MessagingAdapterConfig extends ChannelConfig {\n maxMessageLength: number;\n flushInterval?: number;\n sendInterval?: number;\n thinkingRefreshInterval?: number;\n thinkingDuration?: number;\n displayVerbosity?: DisplayVerbosity;\n}\n\nexport interface SentMessage {\n messageId: string;\n}\n\nconst HIDDEN_ON_LOW = new Set([\"thought\", \"usage\"]);\n\nexport abstract class MessagingAdapter implements IChannelAdapter {\n abstract readonly name: string;\n abstract readonly renderer: IRenderer;\n abstract readonly capabilities: AdapterCapabilities;\n\n constructor(\n protected context: AdapterContext,\n protected adapterConfig: MessagingAdapterConfig,\n ) {}\n\n // === Message dispatch flow ===\n\n async sendMessage(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n const verbosity = this.getVerbosity();\n if (!this.shouldDisplay(content, verbosity)) return;\n await this.dispatchMessage(sessionId, content, verbosity);\n }\n\n protected async dispatchMessage(\n sessionId: string,\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): Promise<void> {\n switch (content.type) {\n case \"text\":\n return this.handleText(sessionId, content);\n case \"thought\":\n return this.handleThought(sessionId, content, verbosity);\n case \"tool_call\":\n return this.handleToolCall(sessionId, content, verbosity);\n case \"tool_update\":\n return this.handleToolUpdate(sessionId, content, verbosity);\n case \"plan\":\n return this.handlePlan(sessionId, content, verbosity);\n case \"usage\":\n return this.handleUsage(sessionId, content, verbosity);\n case \"error\":\n return this.handleError(sessionId, content);\n case \"attachment\":\n return this.handleAttachment(sessionId, content);\n case \"system_message\":\n return this.handleSystem(sessionId, content);\n case \"session_end\":\n return this.handleSessionEnd(sessionId, content);\n case \"mode_change\":\n return this.handleModeChange(sessionId, content);\n case \"config_update\":\n return this.handleConfigUpdate(sessionId, content);\n case \"model_update\":\n return this.handleModelUpdate(sessionId, content);\n case \"user_replay\":\n return this.handleUserReplay(sessionId, content);\n case \"resource\":\n return this.handleResource(sessionId, content);\n case \"resource_link\":\n return this.handleResourceLink(sessionId, content);\n }\n }\n\n // === Default handlers — all protected, all overridable ===\n\n protected async handleText(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleThought(\n _sessionId: string,\n _content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {}\n protected async handleToolCall(\n _sessionId: string,\n _content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {}\n protected async handleToolUpdate(\n _sessionId: string,\n _content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {}\n protected async handlePlan(\n _sessionId: string,\n _content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {}\n protected async handleUsage(\n _sessionId: string,\n _content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {}\n protected async handleError(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleAttachment(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleSystem(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleSessionEnd(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleModeChange(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleConfigUpdate(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleModelUpdate(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleUserReplay(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleResource(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n protected async handleResourceLink(\n _sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {}\n\n // === Helpers ===\n\n protected getVerbosity(): DisplayVerbosity {\n const config = this.context.configManager.get();\n const channelConfig = (config as Record<string, unknown>).channels as\n | Record<string, Record<string, unknown>>\n | undefined;\n const ch = channelConfig?.[this.name];\n const v =\n ch?.outputMode ??\n ch?.displayVerbosity ??\n (config as Record<string, unknown>).outputMode ??\n this.adapterConfig.displayVerbosity;\n if (v === \"low\" || v === \"high\") return v;\n return \"medium\";\n }\n\n protected shouldDisplay(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): boolean {\n if (verbosity === \"low\" && HIDDEN_ON_LOW.has(content.type)) return false;\n\n if (content.type === \"tool_call\") {\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>;\n const toolName = meta.name ?? content.text ?? \"\";\n const toolKind = String(meta.kind ?? \"other\");\n const noiseAction = evaluateNoise(toolName, toolKind, meta.rawInput);\n if (noiseAction === \"hide\" && verbosity !== \"high\") return false;\n if (noiseAction === \"collapse\" && verbosity === \"low\") return false;\n }\n\n return true;\n }\n\n // === Abstract — adapter MUST implement ===\n\n abstract start(): Promise<void>;\n abstract stop(): Promise<void>;\n abstract createSessionThread(\n sessionId: string,\n name: string,\n ): Promise<string>;\n abstract renameSessionThread(\n sessionId: string,\n newName: string,\n ): Promise<void>;\n abstract sendPermissionRequest(\n sessionId: string,\n request: PermissionRequest,\n ): Promise<void>;\n abstract sendNotification(notification: NotificationMessage): Promise<void>;\n}\n","import type {\n IChannelAdapter,\n AdapterCapabilities,\n} from '../channel.js'\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from '../types.js'\n\nexport interface StreamEvent {\n type: string\n sessionId?: string\n payload: unknown\n timestamp: number\n}\n\nexport abstract class StreamAdapter implements IChannelAdapter {\n abstract readonly name: string\n\n capabilities: AdapterCapabilities\n\n constructor(config?: Partial<AdapterCapabilities>) {\n this.capabilities = {\n streaming: true,\n richFormatting: false,\n threads: false,\n reactions: false,\n fileUpload: false,\n voice: false,\n ...config,\n }\n }\n\n async sendMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n await this.emit(sessionId, {\n type: content.type,\n sessionId,\n payload: content,\n timestamp: Date.now(),\n })\n }\n\n async sendPermissionRequest(sessionId: string, request: PermissionRequest): Promise<void> {\n await this.emit(sessionId, {\n type: 'permission_request',\n sessionId,\n payload: request,\n timestamp: Date.now(),\n })\n }\n\n async sendNotification(notification: NotificationMessage): Promise<void> {\n await this.broadcast({\n type: 'notification',\n payload: notification,\n timestamp: Date.now(),\n })\n }\n\n async createSessionThread(_sessionId: string, _name: string): Promise<string> {\n return ''\n }\n\n async renameSessionThread(sessionId: string, name: string): Promise<void> {\n await this.emit(sessionId, {\n type: 'session_rename',\n sessionId,\n payload: { name },\n timestamp: Date.now(),\n })\n }\n\n protected abstract emit(sessionId: string, event: StreamEvent): Promise<void>\n protected abstract broadcast(event: StreamEvent): Promise<void>\n abstract start(): Promise<void>\n abstract stop(): Promise<void>\n}\n","export function progressBar(ratio: number, length = 10): string {\n const filled = Math.round(Math.min(ratio, 1) * length);\n return \"▓\".repeat(filled) + \"░\".repeat(length - filled);\n}\n\nexport function formatTokens(n: number): string {\n if (n >= 1_000_000) {\n const m = n / 1_000_000;\n return m % 1 === 0 ? `${m}M` : `${parseFloat(m.toFixed(1))}M`;\n }\n if (n >= 1000) {\n const k = n / 1000;\n return k % 1 === 0 ? `${k}k` : `${parseFloat(k.toFixed(1))}k`;\n }\n return String(n);\n}\n\nexport function stripCodeFences(text: string): string {\n return text\n .replace(/```\\w*\\n?/g, \"\")\n .replace(/```$/gm, \"\")\n .trim();\n}\n\nexport function truncateContent(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + \"\\n… (truncated)\";\n}\n\nexport function splitMessage(text: string, maxLength: number): string[] {\n if (text.length <= maxLength) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (remaining.length <= maxLength) {\n chunks.push(remaining);\n break;\n }\n\n const wouldLeaveSmall = remaining.length < maxLength * 1.3;\n const searchLimit = wouldLeaveSmall\n ? Math.floor(remaining.length / 2) + 300\n : maxLength;\n\n const threshold = maxLength * 0.2;\n let splitAt = remaining.lastIndexOf(\"\\n\\n\", searchLimit);\n if (splitAt === -1 || splitAt < threshold) {\n splitAt = remaining.lastIndexOf(\"\\n\", searchLimit);\n }\n if (splitAt === -1 || splitAt < threshold) {\n splitAt = searchLimit;\n }\n\n const candidate = remaining.slice(0, splitAt);\n const fences = candidate.match(/```/g);\n if (fences && fences.length % 2 !== 0) {\n const closingFence = remaining.indexOf(\"```\", splitAt);\n if (closingFence !== -1) {\n const afterFence = remaining.indexOf(\"\\n\", closingFence + 3);\n const fenceSplit =\n afterFence !== -1 ? afterFence + 1 : closingFence + 3;\n // Only extend to include the closing fence if it doesn't exceed 2x maxLength\n if (fenceSplit <= maxLength * 2) {\n splitAt = fenceSplit;\n }\n }\n }\n\n chunks.push(remaining.slice(0, splitAt));\n remaining = remaining.slice(splitAt).replace(/^\\n+/, \"\");\n }\n return chunks;\n}\n","import type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from \"../../types.js\";\nimport type {\n DisplayVerbosity,\n ToolCallMeta,\n ToolUpdateMeta,\n} from \"../format-types.js\";\nimport {\n formatToolSummary,\n formatToolTitle,\n resolveToolIcon,\n} from \"../message-formatter.js\";\nimport { progressBar, formatTokens } from \"../format-utils.js\";\n\nexport interface RenderedMessage<TComponents = unknown> {\n body: string;\n format: \"html\" | \"markdown\" | \"plain\" | \"structured\";\n attachments?: RenderedAttachment[];\n components?: TComponents;\n}\n\nexport interface RenderedPermission<\n TComponents = unknown,\n> extends RenderedMessage<TComponents> {\n actions: RenderedAction[];\n}\n\nexport interface RenderedAction {\n id: string;\n label: string;\n isAllow?: boolean;\n}\n\nexport interface RenderedAttachment {\n type: \"file\" | \"image\" | \"audio\";\n data: Buffer | string;\n mimeType?: string;\n filename?: string;\n}\n\nexport interface IRenderer {\n renderText(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderToolCall(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderToolUpdate(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderPlan(content: OutgoingMessage): RenderedMessage;\n renderUsage(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderPermission(request: PermissionRequest): RenderedPermission;\n renderError(content: OutgoingMessage): RenderedMessage;\n renderNotification(notification: NotificationMessage): RenderedMessage;\n renderThought?(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderAttachment?(content: OutgoingMessage): RenderedMessage;\n renderSessionEnd?(content: OutgoingMessage): RenderedMessage;\n renderSystemMessage?(content: OutgoingMessage): RenderedMessage;\n renderModeChange?(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderConfigUpdate?(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderModelUpdate?(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage;\n renderResource?(content: OutgoingMessage): RenderedMessage;\n renderResourceLink?(content: OutgoingMessage): RenderedMessage;\n}\n\n/**\n * BaseRenderer — plain text defaults. Extend for platform-specific rendering.\n */\nexport class BaseRenderer implements IRenderer {\n renderText(content: OutgoingMessage): RenderedMessage {\n return { body: content.text, format: \"plain\" };\n }\n\n renderToolCall(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>;\n const name = meta.name ?? content.text ?? \"Tool\";\n const icon = resolveToolIcon(meta);\n const label =\n verbosity === \"low\"\n ? formatToolTitle(\n name,\n meta.rawInput,\n meta.displayTitle as string | undefined,\n )\n : formatToolSummary(\n name,\n meta.rawInput,\n meta.displaySummary as string | undefined,\n );\n return { body: `${icon} ${label}`, format: \"plain\" };\n }\n\n renderToolUpdate(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolUpdateMeta>;\n const name = meta.name ?? content.text ?? \"Tool\";\n const icon = resolveToolIcon(meta);\n const label =\n verbosity === \"low\"\n ? formatToolTitle(\n name,\n meta.rawInput,\n meta.displayTitle as string | undefined,\n )\n : formatToolSummary(\n name,\n meta.rawInput,\n meta.displaySummary as string | undefined,\n );\n return { body: `${icon} ${label}`, format: \"plain\" };\n }\n\n renderPlan(content: OutgoingMessage): RenderedMessage {\n const entries =\n (\n content.metadata as {\n entries?: Array<{ content: string; status: string }>;\n }\n )?.entries ?? [];\n const lines = entries.map((e, i) => {\n const icon =\n e.status === \"completed\"\n ? \"✅\"\n : e.status === \"in_progress\"\n ? \"🔄\"\n : \"⬜\";\n return `${icon} ${i + 1}. ${e.content}`;\n });\n return { body: `📋 Plan\\n${lines.join(\"\\n\")}`, format: \"plain\" };\n }\n\n renderUsage(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = content.metadata as\n | { tokensUsed?: number; contextSize?: number; cost?: number }\n | undefined;\n if (!meta?.tokensUsed)\n return { body: \"📊 Usage data unavailable\", format: \"plain\" };\n const costStr = meta.cost != null ? ` · $${meta.cost.toFixed(2)}` : \"\";\n if (verbosity === \"medium\") {\n return {\n body: `📊 ${formatTokens(meta.tokensUsed)} tokens${costStr}`,\n format: \"plain\",\n };\n }\n if (!meta.contextSize)\n return {\n body: `📊 ${formatTokens(meta.tokensUsed)} tokens`,\n format: \"plain\",\n };\n const ratio = meta.tokensUsed / meta.contextSize;\n const pct = Math.round(ratio * 100);\n const bar = progressBar(ratio);\n let text = `📊 ${formatTokens(meta.tokensUsed)} / ${formatTokens(meta.contextSize)} tokens\\n${bar} ${pct}%`;\n if (meta.cost != null) text += `\\n💰 $${meta.cost.toFixed(2)}`;\n return { body: text, format: \"plain\" };\n }\n\n renderPermission(request: PermissionRequest): RenderedPermission {\n return {\n body: request.description,\n format: \"plain\",\n actions: request.options.map((o) => ({\n id: o.id,\n label: o.label,\n isAllow: o.isAllow,\n })),\n };\n }\n\n renderError(content: OutgoingMessage): RenderedMessage {\n return { body: `❌ Error: ${content.text}`, format: \"plain\" };\n }\n\n renderNotification(notification: NotificationMessage): RenderedMessage {\n const emoji: Record<string, string> = {\n completed: \"✅\",\n error: \"❌\",\n permission: \"🔐\",\n input_required: \"💬\",\n budget_warning: \"⚠️\",\n };\n return {\n body: `${emoji[notification.type] || \"ℹ️\"} ${notification.sessionName || \"Session\"}\\n${notification.summary}`,\n format: \"plain\",\n };\n }\n\n renderSystemMessage(content: OutgoingMessage): RenderedMessage {\n return { body: content.text, format: \"plain\" };\n }\n\n renderModeChange(content: OutgoingMessage): RenderedMessage {\n const modeId = (content.metadata as Record<string, unknown>)?.modeId ?? \"\";\n return { body: `🔄 Mode: ${modeId}`, format: \"plain\" };\n }\n\n renderConfigUpdate(): RenderedMessage {\n return { body: \"⚙️ Config updated\", format: \"plain\" };\n }\n\n renderModelUpdate(content: OutgoingMessage): RenderedMessage {\n const modelId =\n (content.metadata as Record<string, unknown>)?.modelId ?? \"\";\n return { body: `🤖 Model: ${modelId}`, format: \"plain\" };\n }\n\n renderResource(content: OutgoingMessage): RenderedMessage {\n const uri = (content.metadata as Record<string, unknown>)?.uri ?? \"\";\n return { body: `📄 Resource: ${content.text} (${uri})`, format: \"plain\" };\n }\n\n renderResourceLink(content: OutgoingMessage): RenderedMessage {\n const uri = (content.metadata as Record<string, unknown>)?.uri ?? \"\";\n return { body: `🔗 ${content.text}: ${uri}`, format: \"plain\" };\n }\n}\n","export type QueueItemType = 'text' | 'other'\n\nexport interface SendQueueConfig {\n minInterval: number\n categoryIntervals?: Record<string, number>\n onRateLimited?: () => void\n onError?: (error: Error) => void\n}\n\nexport interface EnqueueOptions {\n type?: QueueItemType\n key?: string\n category?: string\n}\n\ninterface QueueItem<T = unknown> {\n fn: () => Promise<T>\n type: QueueItemType\n key?: string\n category?: string\n resolve: (value: T | undefined) => void\n reject: (err: unknown) => void\n promise: Promise<T | undefined>\n}\n\nexport class SendQueue {\n private items: QueueItem[] = []\n private processing = false\n private lastExec = 0\n private lastCategoryExec = new Map<string, number>()\n\n constructor(private config: SendQueueConfig) {}\n\n get pending(): number {\n return this.items.length\n }\n\n enqueue<T>(\n fn: () => Promise<T>,\n opts?: EnqueueOptions,\n ): Promise<T | undefined> {\n const type = opts?.type ?? 'other'\n const key = opts?.key\n const category = opts?.category\n\n let resolve!: (value: T | undefined) => void\n let reject!: (err: unknown) => void\n const promise = new Promise<T | undefined>((res, rej) => {\n resolve = res\n reject = rej\n })\n // Suppress unhandled rejection — callers are expected to handle via .catch or await\n promise.catch(() => {})\n\n if (type === 'text' && key) {\n const idx = this.items.findIndex(\n (item) => item.type === 'text' && item.key === key,\n )\n if (idx !== -1) {\n this.items[idx].resolve(undefined)\n this.items[idx] = { fn, type, key, category, resolve, reject, promise } as QueueItem\n this.scheduleProcess()\n return promise\n }\n }\n\n this.items.push({ fn, type, key, category, resolve, reject, promise } as QueueItem)\n this.scheduleProcess()\n return promise\n }\n\n onRateLimited(): void {\n this.config.onRateLimited?.()\n const remaining: QueueItem[] = []\n for (const item of this.items) {\n if (item.type === 'text') {\n item.resolve(undefined)\n } else {\n remaining.push(item)\n }\n }\n this.items = remaining\n }\n\n clear(): void {\n for (const item of this.items) {\n item.resolve(undefined)\n }\n this.items = []\n }\n\n private scheduleProcess(): void {\n if (this.processing) return\n if (this.items.length === 0) return\n\n const item = this.items[0]\n const interval = this.getInterval(item.category)\n const lastExec = item.category\n ? this.lastCategoryExec.get(item.category) ?? 0\n : this.lastExec\n const elapsed = Date.now() - lastExec\n const delay = Math.max(0, interval - elapsed)\n\n this.processing = true\n setTimeout(() => void this.processNext(), delay)\n }\n\n private getInterval(category?: string): number {\n if (category && this.config.categoryIntervals?.[category] != null) {\n return this.config.categoryIntervals[category]\n }\n return this.config.minInterval\n }\n\n private async processNext(): Promise<void> {\n const item = this.items.shift()\n if (!item) {\n this.processing = false\n return\n }\n\n try {\n const result = await item.fn()\n item.resolve(result)\n } catch (err) {\n this.config.onError?.(err instanceof Error ? err : new Error(String(err)))\n item.reject(err)\n } finally {\n const now = Date.now()\n this.lastExec = now\n if (item.category) {\n this.lastCategoryExec.set(item.category, now)\n }\n this.processing = false\n this.scheduleProcess()\n }\n }\n}\n","export interface DraftConfig {\n flushInterval: number\n maxLength: number\n onFlush: (sessionId: string, text: string, isEdit: boolean) => Promise<string | undefined>\n onError?: (sessionId: string, error: Error) => void\n}\n\nexport class Draft {\n private buffer = ''\n private _messageId?: string\n private firstFlushPending = false\n private flushTimer?: ReturnType<typeof setTimeout>\n private flushPromise: Promise<void> = Promise.resolve()\n\n constructor(\n private sessionId: string,\n private config: DraftConfig,\n ) {}\n\n get isEmpty(): boolean { return !this.buffer }\n get messageId(): string | undefined { return this._messageId }\n\n append(text: string): void {\n if (!text) return\n this.buffer += text\n this.scheduleFlush()\n }\n\n async finalize(): Promise<string | undefined> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n await this.flushPromise\n if (this.buffer) {\n await this.flush()\n }\n return this._messageId\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n this.buffer = ''\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined\n this.flushPromise = this.flushPromise\n .then(() => this.flush())\n .catch(() => {})\n }, this.config.flushInterval)\n }\n\n private async flush(): Promise<void> {\n if (!this.buffer || this.firstFlushPending) return\n\n const snapshot = this.buffer\n const isEdit = !!this._messageId\n\n if (!this._messageId) {\n this.firstFlushPending = true\n }\n\n try {\n const result = await this.config.onFlush(this.sessionId, snapshot, isEdit)\n if (!isEdit && result) {\n this._messageId = result\n }\n } catch (err) {\n this.config.onError?.(this.sessionId, err instanceof Error ? err : new Error(String(err)))\n } finally {\n this.firstFlushPending = false\n }\n }\n}\n\nexport class DraftManager {\n private drafts = new Map<string, Draft>()\n\n constructor(private config: DraftConfig) {}\n\n getOrCreate(sessionId: string): Draft {\n let draft = this.drafts.get(sessionId)\n if (!draft) {\n draft = new Draft(sessionId, this.config)\n this.drafts.set(sessionId, draft)\n }\n return draft\n }\n\n async finalize(sessionId: string): Promise<void> {\n const draft = this.drafts.get(sessionId)\n if (!draft) return\n await draft.finalize()\n this.drafts.delete(sessionId)\n }\n\n async finalizeAll(): Promise<void> {\n await Promise.all([...this.drafts.values()].map(d => d.finalize()))\n }\n\n destroy(sessionId: string): void {\n const draft = this.drafts.get(sessionId)\n if (draft) {\n draft.destroy()\n this.drafts.delete(sessionId)\n }\n }\n\n destroyAll(): void {\n for (const draft of this.drafts.values()) {\n draft.destroy()\n }\n this.drafts.clear()\n }\n}\n","import type { ToolCallMeta } from '../format-types.js'\n\nexport interface TrackedToolCall extends ToolCallMeta {\n messageId: string\n}\n\nexport class ToolCallTracker {\n private sessions = new Map<string, Map<string, TrackedToolCall>>()\n\n track(sessionId: string, meta: ToolCallMeta, messageId: string): void {\n if (!this.sessions.has(sessionId)) {\n this.sessions.set(sessionId, new Map())\n }\n this.sessions.get(sessionId)!.set(meta.id, { ...meta, messageId })\n }\n\n update(\n sessionId: string,\n toolId: string,\n status: string,\n patch?: Partial<Pick<ToolCallMeta, 'viewerLinks' | 'viewerFilePath' | 'name' | 'kind'>>,\n ): TrackedToolCall | null {\n const tool = this.sessions.get(sessionId)?.get(toolId)\n if (!tool) return null\n\n tool.status = status\n if (patch?.viewerLinks) tool.viewerLinks = patch.viewerLinks\n if (patch?.viewerFilePath) tool.viewerFilePath = patch.viewerFilePath\n if (patch?.name) tool.name = patch.name\n if (patch?.kind) tool.kind = patch.kind\n\n return tool\n }\n\n getActive(sessionId: string): TrackedToolCall[] {\n const session = this.sessions.get(sessionId)\n return session ? [...session.values()] : []\n }\n\n clear(sessionId: string): void {\n this.sessions.delete(sessionId)\n }\n\n clearAll(): void {\n this.sessions.clear()\n }\n}\n","export interface ActivityConfig {\n thinkingRefreshInterval: number\n maxThinkingDuration: number\n}\n\nexport interface ActivityCallbacks {\n sendThinkingIndicator(): Promise<void>\n updateThinkingIndicator(): Promise<void>\n removeThinkingIndicator(): Promise<void>\n}\n\ninterface SessionState {\n callbacks: ActivityCallbacks\n refreshTimer?: ReturnType<typeof setInterval>\n startTime: number\n dismissed: boolean\n}\n\nexport class ActivityTracker {\n private sessions = new Map<string, SessionState>()\n\n constructor(private config: ActivityConfig) {}\n\n onThinkingStart(sessionId: string, callbacks: ActivityCallbacks): void {\n this.cleanup(sessionId)\n\n const state: SessionState = {\n callbacks,\n startTime: Date.now(),\n dismissed: false,\n }\n this.sessions.set(sessionId, state)\n\n setTimeout(() => {\n if (state.dismissed) return\n callbacks.sendThinkingIndicator().catch(() => {})\n this.startRefresh(sessionId, state)\n }, 0)\n }\n\n onTextStart(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state || state.dismissed) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n }\n\n onSessionEnd(sessionId: string): void {\n this.cleanup(sessionId)\n }\n\n destroy(): void {\n for (const [id] of this.sessions) {\n this.cleanup(id)\n }\n }\n\n private cleanup(sessionId: string): void {\n const state = this.sessions.get(sessionId)\n if (!state) return\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n this.sessions.delete(sessionId)\n }\n\n private startRefresh(sessionId: string, state: SessionState): void {\n state.refreshTimer = setInterval(() => {\n if (state.dismissed) {\n this.stopRefresh(state)\n return\n }\n if (Date.now() - state.startTime >= this.config.maxThinkingDuration) {\n state.dismissed = true\n this.stopRefresh(state)\n state.callbacks.removeThinkingIndicator().catch(() => {})\n return\n }\n state.callbacks.updateThinkingIndicator().catch(() => {})\n }, this.config.thinkingRefreshInterval)\n }\n\n private stopRefresh(state: SessionState): void {\n if (state.refreshTimer) {\n clearInterval(state.refreshTimer)\n state.refreshTimer = undefined\n }\n }\n}\n","import type { ToolDisplaySpec } from \"../display-spec-builder.js\";\nimport type { PlanEntry } from \"../../types.js\";\n\nconst DEBOUNCE_MS = 500;\n\nexport type { ToolDisplaySpec };\n\nexport interface UsageData {\n tokensUsed?: number;\n contextSize?: number;\n cost?: number;\n}\n\nexport interface ToolCardSnapshot {\n specs: ToolDisplaySpec[];\n planEntries?: PlanEntry[];\n usage?: UsageData;\n totalVisible: number;\n completedVisible: number;\n allComplete: boolean;\n}\n\nexport interface ToolCardStateConfig {\n onFlush: (snapshot: ToolCardSnapshot) => void;\n}\n\nconst DONE_STATUSES = new Set([\"completed\", \"done\", \"failed\", \"error\"]);\n\nexport class ToolCardState {\n private specs: ToolDisplaySpec[] = [];\n private planEntries?: PlanEntry[];\n private usage?: UsageData;\n private finalized = false;\n private isFirstFlush = true;\n private debounceTimer?: ReturnType<typeof setTimeout>;\n private onFlush: (snapshot: ToolCardSnapshot) => void;\n\n constructor(config: ToolCardStateConfig) {\n this.onFlush = config.onFlush;\n }\n\n updateFromSpec(spec: ToolDisplaySpec): void {\n if (this.finalized) return;\n\n const existingIdx = this.specs.findIndex((s) => s.id === spec.id);\n if (existingIdx >= 0) {\n this.specs[existingIdx] = spec;\n } else {\n this.specs.push(spec);\n }\n\n if (this.isFirstFlush) {\n this.isFirstFlush = false;\n this.flush();\n } else {\n this.scheduleFlush();\n }\n }\n\n updatePlan(entries: PlanEntry[]): void {\n if (this.finalized) return;\n this.planEntries = entries;\n\n if (this.specs.length === 0 && this.isFirstFlush) {\n this.isFirstFlush = false;\n this.flush();\n } else {\n this.scheduleFlush();\n }\n }\n\n appendUsage(usage: UsageData): void {\n if (this.finalized) return;\n this.usage = usage;\n this.scheduleFlush();\n }\n\n finalize(): void {\n if (this.finalized) return;\n this.finalized = true;\n this.clearDebounce();\n this.flush();\n }\n\n destroy(): void {\n this.finalized = true;\n this.clearDebounce();\n }\n\n hasContent(): boolean {\n return this.specs.length > 0 || this.planEntries !== undefined;\n }\n\n private snapshot(): ToolCardSnapshot {\n const visible = this.specs.filter((s) => !s.isHidden);\n const completedVisible = visible.filter((s) => DONE_STATUSES.has(s.status)).length;\n const allComplete = visible.length > 0 && completedVisible === visible.length;\n return {\n specs: this.specs,\n planEntries: this.planEntries,\n usage: this.usage,\n totalVisible: visible.length,\n completedVisible,\n allComplete,\n };\n }\n\n private flush(): void {\n this.clearDebounce();\n this.onFlush(this.snapshot());\n }\n\n private scheduleFlush(): void {\n this.clearDebounce();\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = undefined;\n this.flush();\n }, DEBOUNCE_MS);\n }\n\n private clearDebounce(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = undefined;\n }\n }\n}\n","// src/core/adapter-primitives/stream-accumulator.ts\n\nimport type { ToolCallMeta, ViewerLinks } from \"./format-types.js\";\nimport { evaluateNoise } from \"./message-formatter.js\";\n\nexport interface ToolEntry {\n id: string;\n name: string;\n kind: string;\n rawInput: unknown;\n content: string | null;\n status: string;\n viewerLinks?: ViewerLinks;\n diffStats?: { added: number; removed: number };\n displaySummary?: string;\n displayTitle?: string;\n displayKind?: string;\n isNoise: boolean;\n}\n\ninterface PendingUpdate {\n status: string;\n rawInput?: unknown;\n content?: string | null;\n viewerLinks?: ViewerLinks;\n diffStats?: { added: number; removed: number };\n}\n\nexport class ToolStateMap {\n private entries: Map<string, ToolEntry> = new Map();\n private pendingUpdates: Map<string, PendingUpdate> = new Map();\n\n /**\n * Creates or updates an entry from a tool_call event.\n * If a pending update exists for this id, applies it immediately.\n */\n upsert(meta: ToolCallMeta, kind: string, rawInput: unknown): ToolEntry {\n const isNoise = evaluateNoise(meta.name, kind, rawInput) !== null;\n\n const entry: ToolEntry = {\n id: meta.id,\n name: meta.name,\n kind,\n rawInput,\n content: null,\n status: meta.status ?? \"running\",\n viewerLinks: meta.viewerLinks,\n displaySummary: meta.displaySummary,\n displayTitle: meta.displayTitle,\n displayKind: meta.displayKind,\n isNoise,\n };\n\n this.entries.set(meta.id, entry);\n\n // Apply any pending update that arrived before the initial call\n const pending = this.pendingUpdates.get(meta.id);\n if (pending) {\n this.pendingUpdates.delete(meta.id);\n this._applyUpdate(entry, pending);\n }\n\n return entry;\n }\n\n /**\n * Updates an existing entry from a tool_call_update event.\n * If the entry doesn't exist yet (out-of-order delivery), buffers the update.\n */\n merge(\n id: string,\n status: string,\n rawInput?: unknown,\n content?: string | null,\n viewerLinks?: ViewerLinks,\n diffStats?: { added: number; removed: number },\n ): ToolEntry | undefined {\n const entry = this.entries.get(id);\n\n if (!entry) {\n // Buffer the update for when upsert is called\n this.pendingUpdates.set(id, { status, rawInput, content, viewerLinks, diffStats });\n return undefined;\n }\n\n this._applyUpdate(entry, { status, rawInput, content, viewerLinks, diffStats });\n return entry;\n }\n\n private _applyUpdate(entry: ToolEntry, update: PendingUpdate): void {\n entry.status = update.status;\n if (update.rawInput !== undefined) {\n entry.rawInput = update.rawInput;\n }\n if (update.content !== undefined) {\n entry.content = update.content ?? null;\n }\n if (update.viewerLinks !== undefined) {\n entry.viewerLinks = update.viewerLinks;\n }\n if (update.diffStats !== undefined) {\n entry.diffStats = update.diffStats;\n }\n }\n\n get(id: string): ToolEntry | undefined {\n return this.entries.get(id);\n }\n\n clear(): void {\n this.entries.clear();\n this.pendingUpdates.clear();\n }\n}\n\nexport class ThoughtBuffer {\n private chunks: string[] = [];\n private sealed = false;\n\n append(chunk: string): void {\n if (this.sealed) return;\n this.chunks.push(chunk);\n }\n\n seal(): string {\n this.sealed = true;\n return this.chunks.join(\"\");\n }\n\n getText(): string {\n return this.chunks.join(\"\");\n }\n\n isSealed(): boolean {\n return this.sealed;\n }\n\n reset(): void {\n this.chunks = [];\n this.sealed = false;\n }\n}\n","// src/core/adapter-primitives/display-spec-builder.ts\n\nimport { KIND_ICONS } from \"./format-types.js\";\nimport type { OutputMode, ViewerLinks } from \"./format-types.js\";\nimport type { ToolEntry } from \"./stream-accumulator.js\";\nimport type { TunnelServiceInterface } from \"../plugin/types.js\";\n\n// ─── Output spec interfaces ────────────────────────────────────────────────\n\nexport interface ToolDisplaySpec {\n id: string;\n kind: string;\n icon: string;\n title: string;\n description: string | null;\n command: string | null;\n inputContent: string | null;\n outputSummary: string | null;\n outputContent: string | null;\n diffStats: { added: number; removed: number } | null;\n viewerLinks?: ViewerLinks;\n outputViewerLink?: string;\n outputFallbackContent?: string;\n status: string;\n isNoise: boolean;\n isHidden: boolean;\n}\n\nexport interface ThoughtDisplaySpec {\n indicator: string;\n content: string | null;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────\n\n/** Kinds that have a runnable command in rawInput.command */\nconst EXECUTE_KINDS = new Set([\"execute\", \"bash\", \"command\", \"terminal\"]);\n\nconst INLINE_MAX_LINES = 15;\nconst INLINE_MAX_CHARS = 800;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return {};\n}\n\nfunction capitalize(s: string): string {\n return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1);\n}\n\nfunction buildTitle(entry: ToolEntry, kind: string): string {\n // Explicit overrides take highest priority\n if (entry.displayTitle) return entry.displayTitle;\n if (entry.displaySummary) return entry.displaySummary;\n\n const input = asRecord(entry.rawInput);\n\n if (kind === \"read\") {\n const filePath = typeof input.file_path === \"string\" ? input.file_path : null;\n if (filePath) {\n // start_line/end_line style\n const startLine = typeof input.start_line === \"number\" ? input.start_line : null;\n const endLine = typeof input.end_line === \"number\" ? input.end_line : null;\n if (startLine !== null && endLine !== null) return `${filePath} (lines ${startLine}–${endLine})`;\n if (startLine !== null) return `${filePath} (from line ${startLine})`;\n // offset/limit style (Claude Code Read tool)\n const offset = typeof input.offset === \"number\" ? input.offset : null;\n const limit = typeof input.limit === \"number\" ? input.limit : null;\n if (offset !== null && limit !== null) return `${filePath} (lines ${offset}–${offset + limit - 1})`;\n if (offset !== null) return `${filePath} (from line ${offset})`;\n return filePath;\n }\n return capitalize(entry.name);\n }\n\n if (kind === \"edit\" || kind === \"write\" || kind === \"delete\") {\n const filePath =\n typeof input.file_path === \"string\"\n ? input.file_path\n : typeof input.path === \"string\"\n ? input.path\n : null;\n if (filePath) return filePath;\n return capitalize(entry.name);\n }\n\n if (EXECUTE_KINDS.has(kind)) {\n const description = typeof input.description === \"string\" ? input.description : null;\n if (description) return description;\n const command = typeof input.command === \"string\" ? input.command : null;\n if (command) return command.length > 60 ? command.slice(0, 57) + \"...\" : command;\n return capitalize(entry.name);\n }\n\n if (kind === \"agent\") {\n const skill = typeof input.skill === \"string\" ? input.skill : null;\n const description = typeof input.description === \"string\" ? input.description : null;\n const subtype = typeof input.subagent_type === \"string\" ? input.subagent_type : null;\n if (skill) return skill;\n if (description) return description.length > 60 ? description.slice(0, 57) + \"...\" : description;\n if (subtype) return subtype;\n return capitalize(entry.name);\n }\n\n if (kind === \"search\") {\n const pattern =\n typeof input.pattern === \"string\"\n ? input.pattern\n : typeof input.query === \"string\"\n ? input.query\n : null;\n if (pattern) {\n let title = `${capitalize(entry.name)} \"${pattern}\"`;\n const glob = typeof input.glob === \"string\" ? input.glob : null;\n const type = typeof input.type === \"string\" ? input.type : null;\n if (glob) title += ` (glob: ${glob})`;\n else if (type) title += ` (type: ${type})`;\n return title;\n }\n return capitalize(entry.name);\n }\n\n // Show skill name for Skill tool calls (e.g. Claude Code's Skill tool)\n if (entry.name.toLowerCase() === \"skill\" && typeof input.skill === \"string\" && input.skill) {\n return input.skill;\n }\n\n return entry.name;\n}\n\nfunction buildOutputSummary(content: string): string {\n const lines = content.split(\"\\n\").length;\n return `${lines} line${lines === 1 ? \"\" : \"s\"} of output`;\n}\n\nfunction isShortOutput(content: string): boolean {\n return content.split(\"\\n\").length <= INLINE_MAX_LINES && content.length <= INLINE_MAX_CHARS;\n}\n\n/** Check if title was derived from the command (exact match or truncated version) */\nfunction isTitleFromCommand(title: string, command: string): boolean {\n return title === command || (command.length > 60 && title === command.slice(0, 57) + \"...\");\n}\n\n// ─── DisplaySpecBuilder ───────────────────────────────────────────────────\n\nexport class DisplaySpecBuilder {\n constructor(private tunnelService?: TunnelServiceInterface) {}\n\n buildToolSpec(\n entry: ToolEntry,\n mode: OutputMode,\n sessionContext?: { id: string; workingDirectory: string },\n ): ToolDisplaySpec {\n const effectiveKind = entry.displayKind ?? entry.kind;\n const icon = KIND_ICONS[effectiveKind] ?? KIND_ICONS[\"other\"] ?? \"🛠️\";\n const title = buildTitle(entry, effectiveKind);\n const isHidden = entry.isNoise && mode !== \"high\";\n\n // Fields that are always null on low\n const includeMeta = mode !== \"low\";\n\n const input = asRecord(entry.rawInput);\n\n // Deduplicate: skip description if it matches title, kind label, or tool name\n const rawDescription = typeof input.description === \"string\" ? input.description : null;\n const descLower = rawDescription?.toLowerCase();\n const description =\n includeMeta && rawDescription && rawDescription !== title\n && descLower !== effectiveKind && descLower !== entry.name.toLowerCase()\n ? rawDescription : null;\n\n // Deduplicate: skip command if title was derived from it\n const rawCommand =\n EXECUTE_KINDS.has(effectiveKind) && typeof input.command === \"string\"\n ? input.command\n : null;\n const command =\n includeMeta && rawCommand && !isTitleFromCommand(title, rawCommand)\n ? rawCommand\n : null;\n\n const inputContent: string | null = null;\n\n const content = entry.content;\n\n let outputSummary: string | null = null;\n let outputContent: string | null = null;\n let outputViewerLink: string | undefined = undefined;\n let outputFallbackContent: string | undefined = undefined;\n\n if (content && content.trim().length > 0 && includeMeta) {\n outputSummary = buildOutputSummary(content);\n\n const isLong = !isShortOutput(content);\n\n if (isLong) {\n const publicUrl = this.tunnelService?.getPublicUrl();\n const hasPublicTunnel = !!publicUrl && !publicUrl.startsWith(\"http://localhost\") && !publicUrl.startsWith(\"http://127.0.0.1\");\n if (this.tunnelService && sessionContext && hasPublicTunnel) {\n const label =\n typeof input.command === \"string\" ? input.command : entry.name;\n const id = this.tunnelService.getStore().storeOutput(sessionContext.id, label, content);\n if (id !== null) {\n outputViewerLink = this.tunnelService.outputUrl(id);\n }\n } else if (mode === \"high\") {\n outputFallbackContent = content;\n }\n } else if (mode === \"high\") {\n outputContent = content;\n }\n }\n\n const diffStats = includeMeta ? (entry.diffStats ?? null) : null;\n\n return {\n id: entry.id,\n kind: effectiveKind,\n icon,\n title,\n description,\n command,\n inputContent,\n outputSummary,\n outputContent,\n diffStats,\n viewerLinks: entry.viewerLinks,\n outputViewerLink,\n outputFallbackContent,\n status: entry.status,\n isNoise: entry.isNoise,\n isHidden,\n };\n }\n\n buildThoughtSpec(content: string, mode: OutputMode): ThoughtDisplaySpec {\n const indicator = \"Thinking...\";\n return {\n indicator,\n content: mode === \"high\" ? content : null,\n };\n }\n}\n","// src/core/adapter-primitives/output-mode-resolver.ts\nimport type { OutputMode } from \"./format-types.js\";\n\ninterface ConfigManagerLike {\n get(): Record<string, unknown>;\n}\n\ninterface SessionManagerLike {\n getSessionRecord(id: string): { outputMode?: OutputMode } | undefined;\n}\n\nconst VALID_MODES = new Set<string>([\"low\", \"medium\", \"high\"]);\nfunction toOutputMode(v: unknown): OutputMode | undefined {\n return typeof v === \"string\" && VALID_MODES.has(v) ? (v as OutputMode) : undefined;\n}\n\nexport class OutputModeResolver {\n resolve(\n configManager: ConfigManagerLike,\n adapterName: string,\n sessionId?: string,\n sessionManager?: SessionManagerLike,\n ): OutputMode {\n const config = configManager.get();\n // 1. Global default\n let mode: OutputMode = toOutputMode(config.outputMode) ?? \"medium\";\n // 2. Per-adapter override\n const channels = config.channels as Record<string, unknown> | undefined;\n const channelCfg = channels?.[adapterName] as Record<string, unknown> | undefined;\n const adapterMode = toOutputMode(channelCfg?.outputMode);\n if (adapterMode) mode = adapterMode;\n // 3. Per-session override (most specific)\n if (sessionId && sessionManager) {\n const record = sessionManager.getSessionRecord(sessionId);\n const sessionMode = toOutputMode(record?.outputMode);\n if (sessionMode) mode = sessionMode;\n }\n return mode;\n }\n}\n","/**\n * OpenACP Product Guide — comprehensive reference for the AI assistant.\n * The assistant reads this at runtime to answer user questions about features.\n */\nexport const PRODUCT_GUIDE = `\n# OpenACP — Product Guide\n\nOpenACP lets you chat with AI coding agents (like Claude Code) through messaging platforms (Telegram, Discord).\nYou type messages in your chat platform, the agent reads/writes/runs code in your project folder, and results stream back in real time.\n\n---\n\n## Quick Start\n\n1. Start OpenACP: \\`openacp\\` (or \\`openacp start\\` for background daemon)\n2. Open your messaging platform (Telegram group or Discord server) — you'll see the Assistant topic/thread\n3. Tap/click 🆕 New Session or type /new\n4. Pick an agent and a project folder\n5. Chat in the session topic/thread — the agent works on your code\n\n---\n\n## Core Concepts\n\n### Sessions\nA session = one conversation with one AI agent working in one project folder.\nEach session gets its own topic (Telegram) or forum thread (Discord). Chat there to give instructions to the agent.\n\n### Agents\nAn agent is an AI coding tool (e.g., Claude Code, Gemini, Cursor, Codex, etc.).\nOpenACP supports 28+ agents from the official ACP Registry (agentclientprotocol.com).\nYou can install multiple agents and choose which one to use per session.\nThe default agent is used when you don't specify one.\n\n### Agent Management\n- Browse agents: \\`/agents\\` in your chat platform or \\`openacp agents\\` in CLI\n- Install: tap the install button in /agents, or \\`openacp agents install <name>\\`\n- Uninstall: \\`openacp agents uninstall <name>\\`\n- Setup/login: \\`openacp agents run <name> -- <args>\\` (e.g., \\`openacp agents run gemini -- auth login\\`)\n- Details: \\`openacp agents info <name>\\` shows version, dependencies, and setup steps\n\nSome agents need additional setup before they can be used:\n- Claude: requires \\`claude login\\`\n- Gemini: requires \\`openacp agents run gemini -- auth login\\`\n- Codex: requires setting \\`OPENAI_API_KEY\\` environment variable\n- GitHub Copilot: requires \\`openacp agents run copilot -- auth login\\`\n\nAgents are installed in three ways depending on the agent:\n- **npx** — Node.js agents, downloaded automatically on first use\n- **uvx** — Python agents, downloaded automatically on first use\n- **binary** — Platform-specific binaries, downloaded to \\`~/.openacp/agents/\\`\n\n### Project Folder (Workspace)\nThe directory where the agent reads, writes, and runs code.\nWhen creating a session, you choose which folder the agent works in.\nYou can type a full path like \\`~/code/my-project\\` or just a name like \\`my-project\\` (it becomes \\`<base-dir>/my-project\\`).\n\n### System Topics\n- **Assistant** — Always-on helper that can answer questions, create sessions, check status, troubleshoot\n- **Notifications** — System alerts (permission requests, session errors, completions)\n\n---\n\n## Creating Sessions\n\n### From menu\nTap 🆕 New Session → choose agent (if multiple) → choose project folder → confirm\n\n### From command\n- \\`/new\\` — Interactive flow (asks agent + folder)\n- \\`/new claude ~/code/my-project\\` — Create directly with specific agent and folder\n\n### From Assistant topic\nJust ask: \"Create a session for my-project with claude\" — the assistant handles it\n\n### Quick new chat\n\\`/newchat\\` in a session topic — creates new session with same agent and folder as current one\n\n---\n\n## Working with Sessions\n\n### Chat\nType messages in the session topic. The agent responds with code changes, explanations, tool outputs.\n\n### What you see while the agent works\n- **💭 Thinking indicator** — Shows when the agent is reasoning, with elapsed time\n- **Text responses** — Streamed in real time, updated every few seconds\n- **Tool calls** — When the agent runs commands or edits files, you see tool name, input, status, and output\n- **📋 Plan card** — Visual task progress with completed/in-progress/pending items and progress bar\n- **\"View File\" / \"View Diff\" buttons** — Opens in browser with Monaco editor (requires tunnel)\n\n### Session lifecycle\n1. **Creating** — Topic created, agent spawning\n2. **Warming up** — Agent primes its cache (happens automatically, invisible to you)\n3. **Active** — Ready for your messages\n4. **Auto-naming** — After your first message, the session gets a descriptive name (agent summarizes in ~5 words). The topic title updates automatically.\n5. **Finished/Error** — Session completed or hit an error\n\n### Agent skills\nSome agents provide slash commands (e.g., /compact, /review). Available skills are pinned in the session topic.\n\n### Permission requests\nWhen the agent wants to run a command, it asks for permission.\nYou see buttons: ✅ Allow, ❌ Reject (and sometimes \"Always Allow\").\nA notification also appears in the Notifications topic with a link to the request.\n\n### Dangerous mode\nAuto-approves ALL permission requests — the agent runs any command without asking.\n- Enable: \\`/enable_dangerous\\` or tap the ☠️ button in the session\n- Disable: \\`/disable_dangerous\\` or tap the 🔐 button\n- ⚠️ Use with caution — the agent can execute anything\n\n### Session timeout\nIdle sessions are automatically cancelled after a configurable timeout (default: 60 minutes).\nConfigure via \\`security.sessionTimeoutMinutes\\` in config.\n\n---\n\n## Session Transfer (Handoff)\n\n### Chat → Terminal\n1. Type \\`/handoff\\` in a session topic/thread\n2. You get a command like \\`claude --resume <SESSION_ID>\\`\n3. Copy and run it in your terminal — the session continues there with full conversation history\n\n### Terminal → Chat\n1. First time: run \\`openacp integrate claude\\` to install the handoff skill (one-time setup)\n2. In Claude Code, use the /openacp:handoff slash command\n3. The session appears as a new topic/thread and you can continue chatting there\n\n### How it works\n- The agent session ID is shared between platforms\n- Conversation history is preserved — pick up where you left off\n- The agent that supports resume (e.g., Claude with \\`--resume\\`) handles the actual transfer\n\n---\n\n## Managing Sessions\n\n### Status\n- \\`/status\\` — Shows active sessions count and details\n- Ask the Assistant: \"What sessions are running?\"\n\n### List all sessions\n- \\`/sessions\\` — Shows all sessions with status (active, finished, error)\n\n### Cancel\n- \\`/cancel\\` in a session topic — cancels that session\n- Ask the Assistant: \"Cancel the stuck session\"\n\n### Cleanup\n- From \\`/sessions\\` → tap cleanup buttons (finished, errors, all)\n- Ask the Assistant: \"Clean up old sessions\"\n\n---\n\n## Assistant Topic\n\nThe Assistant is an always-on AI helper in its own topic. It can:\n- Answer questions about OpenACP\n- Create sessions for you\n- Check status and health\n- Cancel sessions\n- Clean up old sessions\n- Troubleshoot issues\n- Manage configuration\n\nJust chat naturally: \"How do I create a session?\", \"What's the status?\", \"Something is stuck\"\n\n### Clear history\n\\`/clear\\` in the Assistant topic — resets the conversation\n\n---\n\n## System Commands\n\n| Command | Where | What it does |\n|---------|-------|-------------|\n| \\`/new [agent] [path]\\` | Anywhere | Create new session |\n| \\`/newchat\\` | Session topic | New session, same agent + folder |\n| \\`/cancel\\` | Session topic | Cancel current session |\n| \\`/status\\` | Anywhere | Show status |\n| \\`/sessions\\` | Anywhere | List all sessions |\n| \\`/agents\\` | Anywhere | Browse & install agents from ACP Registry |\n| \\`/install <name>\\` | Anywhere | Install an agent |\n| \\`/enable_dangerous\\` | Session topic | Auto-approve all permissions |\n| \\`/disable_dangerous\\` | Session topic | Restore permission prompts |\n| \\`/handoff\\` | Session topic | Transfer session to terminal |\n| \\`/clear\\` | Assistant topic | Clear assistant history |\n| \\`/menu\\` | Anywhere | Show action menu |\n| \\`/help\\` | Anywhere | Show help |\n| \\`/restart\\` | Anywhere | Restart OpenACP |\n| \\`/update\\` | Anywhere | Update to latest version |\n| \\`/integrate\\` | Anywhere | Manage agent integrations |\n\n---\n\n## Menu Buttons\n\n| Button | Action |\n|--------|--------|\n| 🆕 New Session | Create new session (interactive) |\n| 📋 Sessions | List all sessions with cleanup options |\n| 📊 Status | Show active/total session count |\n| 🤖 Agents | List available agents |\n| 🔗 Integrate | Manage agent integrations |\n| ❓ Help | Show help text |\n| 🔄 Restart | Restart OpenACP |\n| ⬆️ Update | Check and install updates |\n\n---\n\n## CLI Commands\n\n### Server\n- \\`openacp\\` — Start (uses configured mode: foreground or daemon)\n- \\`openacp start\\` — Start as background daemon\n- \\`openacp stop\\` — Stop daemon\n- \\`openacp status\\` — Show daemon status\n- \\`openacp logs\\` — Tail daemon logs\n- \\`openacp --foreground\\` — Force foreground mode (useful for debugging or containers)\n\n### Auto-start (run on boot)\n- macOS: installs a LaunchAgent in \\`~/Library/LaunchAgents/\\`\n- Linux: installs a systemd user service in \\`~/.config/systemd/user/\\`\n- Enabled automatically when you start the daemon. Remove with \\`openacp stop\\`.\n\n### Configuration\n- \\`openacp config\\` — Interactive config editor\n- \\`openacp reset\\` — Delete all data and start fresh\n\n### Agent Management (CLI)\n- \\`openacp agents\\` — List all agents (installed + available from ACP Registry)\n- \\`openacp agents install <name>\\` — Install an agent\n- \\`openacp agents uninstall <name>\\` — Remove an agent\n- \\`openacp agents info <name>\\` — Show details, dependencies, and setup guide\n- \\`openacp agents run <name> [-- args]\\` — Run agent CLI directly (for login, config, etc.)\n- \\`openacp agents refresh\\` — Force-refresh registry cache\n\n### Plugins\n- \\`openacp install <package>\\` — Install adapter plugin\n- \\`openacp uninstall <package>\\` — Remove adapter plugin\n- \\`openacp plugins\\` — List installed plugins\n\n### Integration\n- \\`openacp integrate <agent>\\` — Install agent integration (e.g., Claude handoff skill)\n- \\`openacp integrate <agent> --uninstall\\` — Remove integration\n\n### API (requires running daemon)\n\\`openacp api <command>\\` — Interact with running daemon:\n\n| Command | Description |\n|---------|-------------|\n| \\`status\\` | List active sessions |\n| \\`session <id>\\` | Session details |\n| \\`new <agent> <path>\\` | Create session |\n| \\`send <id> \"text\"\\` | Send prompt |\n| \\`cancel <id>\\` | Cancel session |\n| \\`dangerous <id> on/off\\` | Toggle dangerous mode |\n| \\`topics [--status x,y]\\` | List topics |\n| \\`delete-topic <id> [--force]\\` | Delete topic |\n| \\`cleanup [--status x,y]\\` | Cleanup old topics |\n| \\`agents\\` | List agents |\n| \\`health\\` | System health |\n| \\`config\\` | Show config |\n| \\`config set <key> <value>\\` | Update config |\n| \\`adapters\\` | List adapters |\n| \\`tunnel\\` | Tunnel status |\n| \\`notify \"message\"\\` | Send notification |\n| \\`version\\` | Daemon version |\n| \\`restart\\` | Restart daemon |\n\n---\n\n## File Viewer (Tunnel)\n\nWhen tunnel is enabled, file edits and diffs get \"View\" buttons that open in your browser:\n- **Monaco Editor** — Full VS Code editor with syntax highlighting\n- **Diff viewer** — Side-by-side or inline comparison\n- **Line highlighting** — Click lines to highlight\n- Dark/light theme toggle\n\n### Setup\nEnable in config: set \\`tunnel.enabled\\` to \\`true\\`.\nProviders: Cloudflare (default, free), ngrok, bore, Tailscale Funnel.\n\n### Port Tunneling\n\nExpose any local port (dev servers, APIs, etc.) to the internet:\n\n**CLI commands** (agent can call these directly):\n- \\`openacp tunnel add <port> --label <name>\\` — Create tunnel to a local port\n- \\`openacp tunnel list\\` — List active tunnels\n- \\`openacp tunnel stop <port>\\` — Stop a tunnel\n- \\`openacp tunnel stop-all\\` — Stop all user tunnels\n\n**Telegram commands**:\n- \\`/tunnel <port> [label]\\` — Create tunnel\n- \\`/tunnels\\` — List active tunnels\n- \\`/tunnel stop <port>\\` — Stop tunnel\n\nExample: after starting a dev server on port 3000, run \\`openacp tunnel add 3000 --label my-app\\` to get a public URL.\n\n---\n\n## Configuration\n\nConfig file: \\`~/.openacp/config.json\\`\n\n### Channels\n- **channels.telegram.botToken** — Your Telegram bot token\n- **channels.telegram.chatId** — Your Telegram supergroup ID\n- **channels.discord.botToken** — Your Discord bot token\n- **channels.discord.guildId** — Your Discord server (guild) ID\n\n### Agents\n- **defaultAgent** — Which agent to use by default\n- Agents are managed via \\`/agents\\` (Telegram) or \\`openacp agents\\` (CLI)\n- Installed agents are stored in \\`~/.openacp/agents.json\\`\n- Agent list is fetched from the ACP Registry CDN and cached locally (24h)\n\n### Workspace\n- **workspace.baseDir** — Base directory for project folders (default: \\`~/openacp-workspace\\`)\n\n### Security\n- **security.allowedUserIds** — Restrict who can use the bot (empty = everyone)\n- **security.maxConcurrentSessions** — Max parallel sessions (default: 5)\n- **security.sessionTimeoutMinutes** — Auto-cancel idle sessions (default: 60)\n\n### Tunnel / File Viewer\n- **tunnel.enabled** — Enable file viewer tunnel\n- **tunnel.provider** — Tunnel provider: cloudflare (default, free), ngrok, bore, tailscale\n- **tunnel.port** — Local port for tunnel server (default: 3100)\n- **tunnel.auth.enabled** — Enable authentication for tunnel URLs\n- **tunnel.auth.token** — Auth token for tunnel access\n- **tunnel.storeTtlMinutes** — How long viewer links stay cached (default: 60)\n\n### Logging\n- **logging.level** — Log level: silent, debug, info, warn, error, fatal (default: info)\n- **logging.logDir** — Log directory (default: \\`~/.openacp/logs\\`)\n- **logging.maxFileSize** — Max log file size before rotation\n- **logging.maxFiles** — Max number of rotated log files\n- **logging.sessionLogRetentionDays** — Auto-delete old session logs (default: 30)\n\n### Data Retention\n- **sessionStore.ttlDays** — How long session records persist (default: 30). Old records are cleaned up automatically.\n\n### Environment variables\nOverride config with env vars:\n- \\`OPENACP_TELEGRAM_BOT_TOKEN\\`\n- \\`OPENACP_TELEGRAM_CHAT_ID\\`\n- \\`OPENACP_DISCORD_BOT_TOKEN\\`\n- \\`OPENACP_DISCORD_GUILD_ID\\`\n- \\`OPENACP_DEFAULT_AGENT\\`\n- \\`OPENACP_RUN_MODE\\` — foreground or daemon\n- \\`OPENACP_API_PORT\\` — API server port (default: 21420)\n- \\`OPENACP_TUNNEL_ENABLED\\`\n- \\`OPENACP_TUNNEL_PORT\\`\n- \\`OPENACP_TUNNEL_PROVIDER\\`\n- \\`OPENACP_LOG_LEVEL\\`\n- \\`OPENACP_LOG_DIR\\`\n- \\`OPENACP_DEBUG\\` — Sets log level to debug\n\n---\n\n## Troubleshooting\n\n### Session stuck / not responding\n- Check status: ask Assistant \"Is anything stuck?\"\n- Cancel and create new: \\`/cancel\\` then \\`/new\\`\n- Check system health: Assistant can run health check\n\n### Agent not found\n- Check available agents: \\`/agents\\` or \\`openacp agents\\`\n- Install missing agent: \\`openacp agents install <name>\\`\n- Some agents need login first: \\`openacp agents info <name>\\` to see setup steps\n- Run agent CLI for setup: \\`openacp agents run <name> -- <args>\\`\n\n### Permission request not showing\n- Check Notifications topic for the alert\n- Try \\`/enable_dangerous\\` to auto-approve (if you trust the agent)\n\n### Session disappeared after restart\n- Sessions persist across restarts\n- Send a message in the old topic — it auto-resumes\n- If topic was deleted, the session record may still exist in status\n\n### Bot not responding at all\n- Check daemon: \\`openacp status\\`\n- Check logs: \\`openacp logs\\`\n- Restart: \\`openacp start\\` or \\`/restart\\`\n\n### Messages going to wrong topic\n- Each session is bound to a specific topic/thread\n- If you see messages appearing in the Assistant topic instead of the session topic, try creating a new session\n\n### Viewing logs\n- Session-specific logs: \\`~/.openacp/logs/sessions/\\`\n- System logs: \\`openacp logs\\` to tail live\n- Set \\`OPENACP_DEBUG=true\\` for verbose output\n\n---\n\n## Data & Storage\n\nAll data is stored in \\`~/.openacp/\\`:\n- \\`config.json\\` — Configuration\n- \\`agents.json\\` — Installed agents (managed by AgentCatalog)\n- \\`registry-cache.json\\` — Cached ACP Registry data (refreshes every 24h)\n- \\`agents/\\` — Downloaded binary agents\n- \\`sessions/\\` — Session records and state\n- \\`topics/\\` — Topic-to-session mappings\n- \\`logs/\\` — System and session logs\n- \\`plugins/\\` — Installed adapter plugins\n- \\`openacp.pid\\` — Daemon PID file\n\nSession records auto-cleanup: 30 days (configurable via \\`sessionStore.ttlDays\\`).\nSession logs auto-cleanup: 30 days (configurable via \\`logging.sessionLogRetentionDays\\`).\n`;\n","import { Bot, InputFile } from \"grammy\";\nimport path from \"node:path\";\nimport type {\n OpenACPCore,\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n Session,\n AgentCommand,\n FileServiceInterface,\n} from \"../../core/index.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nimport type { DebugTracer } from \"../../core/utils/debug-tracer.js\";\nconst log = createChildLogger({ module: \"telegram\" });\nimport type { TelegramChannelConfig } from \"./types.js\";\nimport type { CommandRegistry } from \"../../core/command-registry.js\";\nimport type { CommandResponse } from \"../../core/plugin/types.js\";\nimport {\n ensureTopics,\n createSessionTopic,\n renameSessionTopic,\n deleteSessionTopic,\n} from \"./topics.js\";\nimport {\n setupCommands,\n setupMenuCallbacks,\n setupDangerousModeCallbacks,\n setupTTSCallbacks,\n setupVerbosityCallbacks,\n setupIntegrateCallbacks,\n buildMenuKeyboard,\n handlePendingWorkspaceInput,\n handlePendingResumeInput,\n STATIC_COMMANDS,\n} from \"./commands/index.js\";\nimport { PermissionHandler } from \"./permissions.js\";\nimport {\n spawnAssistant,\n handleAssistantMessage,\n redirectToAssistant,\n buildWelcomeMessage,\n type SpawnAssistantResult,\n} from \"./assistant.js\";\nimport { escapeHtml, formatUsage } from \"./formatting.js\";\nimport { ActivityTracker } from \"./activity.js\";\nimport { SendQueue } from \"../../core/adapter-primitives/primitives/send-queue.js\";\nimport { setupActionCallbacks } from \"./action-detect.js\";\nimport { DraftManager } from \"./draft-manager.js\";\nimport { SkillCommandManager } from \"./skill-command-manager.js\";\nimport {\n MessagingAdapter,\n type MessagingAdapterConfig,\n} from \"../../core/adapter-primitives/messaging-adapter.js\";\nimport type { IRenderer } from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport { TelegramRenderer } from \"./renderer.js\";\nimport type { AdapterCapabilities } from \"../../core/channel.js\";\nimport type {\n DisplayVerbosity,\n ToolCallMeta,\n ToolUpdateMeta,\n OutputMode,\n} from \"../../core/adapter-primitives/format-types.js\";\nimport { OutputModeResolver } from \"../../core/adapter-primitives/output-mode-resolver.js\";\nimport type { TunnelServiceInterface } from \"../../core/plugin/types.js\";\n// evaluateNoise is handled by MessagingAdapter.shouldDisplay()\n\ninterface PlanMetadata {\n entries: Array<{ content: string; status: string; priority: string }>;\n}\n\ninterface UsageMetadata {\n tokensUsed?: number;\n contextSize?: number;\n}\n\n/**\n * Wraps native fetch to work around grammY's polyfilled AbortController.\n * grammY uses abort-controller polyfill whose AbortSignal fails instanceof\n * checks in Node 24+ native fetch. This wrapper re-creates a native\n * AbortSignal from the polyfilled one before passing it to fetch.\n */\nfunction patchedFetch(\n input: RequestInfo | URL,\n init?: RequestInit,\n): Promise<Response> {\n if (init?.signal && !(init.signal instanceof AbortSignal)) {\n const nativeController = new AbortController();\n const polyfillSignal = init.signal as unknown as {\n aborted: boolean;\n addEventListener: (event: string, fn: () => void) => void;\n };\n if (polyfillSignal.aborted) {\n nativeController.abort();\n } else {\n polyfillSignal.addEventListener(\"abort\", () => nativeController.abort());\n }\n init = { ...init, signal: nativeController.signal };\n }\n return fetch(input, init);\n}\n\nexport class TelegramAdapter extends MessagingAdapter {\n readonly name = \"telegram\";\n readonly renderer: IRenderer = new TelegramRenderer();\n readonly capabilities: AdapterCapabilities = {\n streaming: true,\n richFormatting: true,\n threads: true,\n reactions: true,\n fileUpload: true,\n voice: true,\n };\n\n private core: OpenACPCore;\n private bot!: Bot;\n private telegramConfig: TelegramChannelConfig;\n private saveTopicIds?: (updates: { notificationTopicId?: number; assistantTopicId?: number }) => Promise<void>;\n private permissionHandler!: PermissionHandler;\n private assistantSession: Session | null = null;\n private assistantInitializing = false;\n private notificationTopicId!: number;\n private assistantTopicId!: number;\n private sendQueue = new SendQueue({ minInterval: 3000 });\n private _sessionThreadIds = new Map<string, number>();\n private outputModeResolver = new OutputModeResolver();\n\n // Extracted managers\n private draftManager!: DraftManager;\n private skillManager!: SkillCommandManager;\n private fileService!: FileServiceInterface;\n private sessionTrackers: Map<string, ActivityTracker> = new Map();\n private callbackCache = new Map<string, string>();\n private callbackCounter = 0;\n /** Pending skill commands queued when session.threadId was not yet set */\n private _pendingSkillCommands = new Map<string, AgentCommand[]>();\n\n private getThreadId(sessionId: string): number {\n const threadId = this._sessionThreadIds.get(sessionId);\n if (threadId === undefined) {\n throw new Error(`No threadId stored for session ${sessionId}`);\n }\n return threadId;\n }\n\n private getOrCreateTracker(\n sessionId: string,\n threadId: number,\n outputMode: OutputMode = \"medium\",\n ): ActivityTracker {\n let tracker = this.sessionTrackers.get(sessionId);\n if (!tracker) {\n const tunnelService = this.core.lifecycleManager?.serviceRegistry?.get(\"tunnel\") as TunnelServiceInterface | undefined;\n const session = this.core.sessionManager.getSession(sessionId);\n const sessionContext = session ? {\n id: sessionId,\n workingDirectory: session.workingDirectory,\n } : undefined;\n tracker = new ActivityTracker(\n this.bot.api,\n this.telegramConfig.chatId,\n threadId,\n this.sendQueue,\n outputMode,\n sessionId,\n this.getTracer(sessionId),\n tunnelService,\n sessionContext,\n );\n this.sessionTrackers.set(sessionId, tracker);\n } else {\n tracker.setOutputMode(outputMode);\n }\n return tracker;\n }\n\n constructor(\n core: OpenACPCore,\n config: TelegramChannelConfig,\n saveTopicIds?: (updates: { notificationTopicId?: number; assistantTopicId?: number }) => Promise<void>,\n ) {\n super({ configManager: core.configManager }, {\n ...(config as Record<string, unknown>),\n maxMessageLength: 4096,\n enabled: config.enabled ?? true,\n } as MessagingAdapterConfig);\n this.core = core;\n this.telegramConfig = config;\n this.saveTopicIds = saveTopicIds;\n }\n\n async start(): Promise<void> {\n this.bot = new Bot(this.telegramConfig.botToken, {\n client: {\n baseFetchConfig: { duplex: \"half\" } as RequestInit,\n fetch: patchedFetch,\n },\n });\n this.fileService = this.core.fileService;\n\n // Initialize extracted managers\n this.draftManager = new DraftManager(\n this.bot,\n this.telegramConfig.chatId,\n this.sendQueue,\n );\n this.skillManager = new SkillCommandManager(\n this.bot,\n this.telegramConfig.chatId,\n this.sendQueue,\n this.core.sessionManager,\n );\n\n // Global error handler — prevent unhandled errors from crashing the bot\n this.bot.catch((err) => {\n const rootCause = err.error instanceof Error ? err.error : err;\n log.error({ err: rootCause }, \"Telegram bot error\");\n });\n\n // Auto-retry on 429 (Too Many Requests)\n this.bot.api.config.use(async (prev, method, payload, signal) => {\n const maxRetries = 3;\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const result = await prev(method, payload, signal);\n if (\n result.ok ||\n (result as { error_code?: number }).error_code !== 429 ||\n attempt === maxRetries\n ) {\n return result;\n }\n const retryAfter =\n ((result as { parameters?: { retry_after?: number } }).parameters\n ?.retry_after ?? 5) + 1;\n const rateLimitedMethods = [\n \"sendMessage\",\n \"editMessageText\",\n \"editMessageReplyMarkup\",\n ];\n if (rateLimitedMethods.includes(method)) {\n this.sendQueue.onRateLimited();\n }\n log.warn(\n { method, retryAfter, attempt: attempt + 1 },\n \"Rate limited by Telegram, retrying\",\n );\n await new Promise((r) => setTimeout(r, retryAfter * 1000));\n }\n return prev(method, payload, signal);\n });\n\n // Ensure allowed_updates includes callback_query on every poll\n this.bot.api.config.use((prev, method, payload, signal) => {\n if (method === \"getUpdates\") {\n const p = payload as Record<string, unknown>;\n p.allowed_updates = (p.allowed_updates as string[] | undefined) ?? [\n \"message\",\n \"callback_query\",\n ];\n }\n return prev(method, payload, signal);\n });\n\n // Register static commands for Telegram autocomplete (non-critical, retry in background)\n this.registerCommandsWithRetry();\n\n // Middleware: only accept updates from configured chatId\n this.bot.use((ctx, next) => {\n const chatId = ctx.chat?.id ?? ctx.callbackQuery?.message?.chat?.id;\n if (chatId !== this.telegramConfig.chatId) return;\n return next();\n });\n\n // Ensure system topics exist (retry on transient network failures)\n const topics = await this.retryWithBackoff(\n () => ensureTopics(\n this.bot,\n this.telegramConfig.chatId,\n this.telegramConfig,\n async (updates) => {\n if (this.saveTopicIds) {\n await this.saveTopicIds(updates);\n } else {\n // Fallback for legacy usage without plugin settings\n await this.core.configManager.save({\n channels: { telegram: updates },\n });\n }\n },\n ),\n \"ensureTopics\",\n );\n this.notificationTopicId = topics.notificationTopicId;\n this.assistantTopicId = topics.assistantTopicId;\n\n // Setup permission handler\n this.permissionHandler = new PermissionHandler(\n this.bot,\n this.telegramConfig.chatId,\n (sessionId) => this.core.sessionManager.getSession(sessionId),\n (notification) => this.sendNotification(notification),\n );\n\n // Generic CommandRegistry dispatch — handles any command registered via plugin system.\n // Must be early so registry commands run before legacy bot.command() handlers.\n this.bot.on(\"message:text\", async (ctx, next) => {\n const text = ctx.message?.text;\n if (!text?.startsWith(\"/\")) return next();\n\n const registry =\n this.core.lifecycleManager?.serviceRegistry?.get<CommandRegistry>(\n \"command-registry\",\n );\n if (!registry) return next();\n\n // Extract command name (remove / and @botname suffix)\n const rawCommand = text.split(\" \")[0].slice(1);\n const atIdx = rawCommand.indexOf(\"@\");\n // If command is directed at another bot, ignore it\n if (\n atIdx !== -1 &&\n rawCommand.slice(atIdx + 1).toLowerCase() !==\n ctx.me.username.toLowerCase()\n ) {\n return next();\n }\n const commandName =\n atIdx === -1 ? rawCommand : rawCommand.slice(0, atIdx);\n const def = registry.get(commandName);\n if (!def) return next(); // not in registry, fall through to existing handlers\n\n const chatId = ctx.chat.id;\n const topicId = ctx.message.message_thread_id;\n\n try {\n const sessionId =\n topicId != null\n ? (this.core.sessionManager.getSessionByThread(\n \"telegram\",\n String(topicId),\n )?.id ?? null)\n : null;\n\n const response = await registry.execute(text, {\n raw: \"\",\n sessionId,\n channelId: \"telegram\",\n userId: String(ctx.from?.id),\n reply: async (content) => {\n if (typeof content === \"string\") {\n await ctx.reply(content);\n } else if (\n typeof content === \"object\" &&\n content !== null &&\n \"type\" in content\n ) {\n await this.renderCommandResponse(\n content as CommandResponse,\n chatId,\n topicId,\n );\n }\n },\n });\n\n if (response.type === \"silent\") {\n // Silent means the registry has no UI for this command — pass through\n // to adapter-specific handlers (e.g. handleNewChat, handleCancel).\n return next();\n }\n await this.renderCommandResponse(response, chatId, topicId);\n } catch (err) {\n await ctx.reply(`\\u26a0\\ufe0f Command failed: ${String(err)}`);\n }\n });\n\n // Callback query handler for command buttons (c/ prefix)\n this.bot.callbackQuery(/^c\\//, async (ctx) => {\n const data = ctx.callbackQuery.data;\n const command = this.fromCallbackData(data);\n\n const registry =\n this.core.lifecycleManager?.serviceRegistry?.get<CommandRegistry>(\n \"command-registry\",\n );\n if (!registry) return;\n\n const chatId = ctx.chat!.id;\n const topicId = ctx.callbackQuery.message?.message_thread_id;\n\n try {\n const sessionId =\n topicId != null\n ? (this.core.sessionManager.getSessionByThread(\n \"telegram\",\n String(topicId),\n )?.id ?? null)\n : null;\n\n const response = await registry.execute(command, {\n raw: \"\",\n sessionId,\n channelId: \"telegram\",\n userId: String(ctx.from?.id),\n reply: async (content) => {\n if (typeof content === \"string\") {\n await ctx.editMessageText(content).catch(() => {});\n }\n },\n });\n\n await ctx.answerCallbackQuery();\n if (response.type !== \"silent\") {\n await this.renderCommandResponse(response, chatId, topicId);\n }\n } catch {\n await ctx.answerCallbackQuery({ text: \"Command failed\" });\n }\n });\n\n // Callback registration order matters!\n setupDangerousModeCallbacks(this.bot, this.core as OpenACPCore);\n setupTTSCallbacks(this.bot, this.core as OpenACPCore);\n setupVerbosityCallbacks(this.bot, this.core as OpenACPCore);\n setupActionCallbacks(\n this.bot,\n this.core as OpenACPCore,\n this.telegramConfig.chatId,\n () => this.assistantSession?.id,\n );\n setupIntegrateCallbacks(this.bot, this.core as OpenACPCore);\n setupMenuCallbacks(\n this.bot,\n this.core as OpenACPCore,\n this.telegramConfig.chatId,\n {\n notificationTopicId: this.notificationTopicId,\n assistantTopicId: this.assistantTopicId,\n },\n () => {\n if (!this.assistantSession) return undefined;\n return {\n topicId: this.assistantTopicId,\n enqueuePrompt: (p: string) => this.assistantSession!.enqueuePrompt(p),\n };\n },\n );\n setupCommands(\n this.bot,\n this.core as OpenACPCore,\n this.telegramConfig.chatId,\n {\n topicId: this.assistantTopicId,\n getSession: () => this.assistantSession,\n respawn: async () => {\n if (this.assistantSession) {\n await this.assistantSession.destroy();\n this.assistantSession = null;\n }\n const { session, ready } = await spawnAssistant(\n this.core as OpenACPCore,\n this,\n this.assistantTopicId,\n );\n this.assistantSession = session;\n this.assistantInitializing = true;\n ready.then(() => {\n this.assistantInitializing = false;\n });\n },\n },\n );\n this.permissionHandler.setupCallbackHandler();\n\n // /handoff command\n this.bot.command(\"handoff\", async (ctx) => {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) return;\n\n if (\n threadId === this.notificationTopicId ||\n threadId === this.assistantTopicId\n ) {\n await ctx.reply(\"This command only works in session topics.\", {\n message_thread_id: threadId,\n });\n return;\n }\n\n const session = this.core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n const record = session\n ? undefined\n : this.core.sessionManager.getRecordByThread(\n \"telegram\",\n String(threadId),\n );\n\n const agentName = session?.agentName ?? record?.agentName;\n const agentSessionId = session?.agentSessionId ?? record?.agentSessionId;\n\n if (!agentName || !agentSessionId) {\n await ctx.reply(\"No session found for this topic.\", {\n message_thread_id: threadId,\n });\n return;\n }\n\n const { getAgentCapabilities } =\n await import(\"../../core/agents/agent-registry.js\");\n const caps = getAgentCapabilities(agentName);\n\n if (!caps.supportsResume || !caps.resumeCommand) {\n await ctx.reply(\"This agent does not support session transfer.\", {\n message_thread_id: threadId,\n });\n return;\n }\n\n const command = caps.resumeCommand(agentSessionId);\n\n await ctx.reply(\n `Run this in your terminal to continue the session:\\n\\n<code>${command}</code>`,\n {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n },\n );\n });\n\n // Setup message routing\n this.setupRoutes();\n\n // Start bot polling\n this.bot.start({\n allowed_updates: [\"message\", \"callback_query\"],\n onStart: () =>\n log.info(\n { chatId: this.telegramConfig.chatId },\n \"Telegram bot started\",\n ),\n });\n\n // Send welcome message\n try {\n const config = this.core.configManager.get();\n const agents = this.core.agentManager.getAvailableAgents();\n const allRecords = this.core.sessionManager.listRecords();\n\n const welcomeText = buildWelcomeMessage({\n activeCount: allRecords.filter(\n (r) => r.status === \"active\" || r.status === \"initializing\",\n ).length,\n errorCount: allRecords.filter((r) => r.status === \"error\").length,\n totalCount: allRecords.length,\n agents: agents.map((a) => a.name),\n defaultAgent: config.defaultAgent,\n });\n\n await this.bot.api.sendMessage(this.telegramConfig.chatId, welcomeText, {\n message_thread_id: this.assistantTopicId,\n parse_mode: \"HTML\",\n reply_markup: buildMenuKeyboard(),\n });\n } catch (err) {\n log.warn({ err }, \"Failed to send welcome message\");\n }\n\n // Spawn assistant in background\n try {\n log.info(\"Spawning assistant session...\");\n const { session, ready } = await spawnAssistant(\n this.core as OpenACPCore,\n this,\n this.assistantTopicId,\n );\n this.assistantSession = session;\n this.assistantInitializing = true;\n log.info(\n { sessionId: session.id },\n \"Assistant session ready, system prompt running in background\",\n );\n ready.then(() => {\n this.assistantInitializing = false;\n log.info(\n { sessionId: session.id },\n \"Assistant ready for user messages\",\n );\n });\n } catch (err) {\n log.error({ err }, \"Failed to spawn assistant\");\n this.bot.api\n .sendMessage(\n this.telegramConfig.chatId,\n `⚠️ <b>Failed to start assistant session.</b>\\n\\n<code>${err instanceof Error ? err.message : String(err)}</code>`,\n { message_thread_id: this.assistantTopicId, parse_mode: \"HTML\" },\n )\n .catch(() => {});\n }\n }\n\n /**\n * Retry an async operation with exponential backoff.\n * Used for Telegram API calls that may fail due to transient network issues.\n */\n private async retryWithBackoff<T>(\n fn: () => Promise<T>,\n label: string,\n maxRetries = 5,\n baseDelayMs = 2000,\n ): Promise<T> {\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (attempt === maxRetries) throw err;\n const delay = baseDelayMs * Math.pow(2, attempt - 1);\n log.warn(\n { err, attempt, maxRetries, delayMs: delay, operation: label },\n `${label} failed, retrying in ${delay}ms`,\n );\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n throw new Error(\"unreachable\");\n }\n\n /**\n * Register Telegram commands in the background with retries.\n * Non-critical — bot works fine without autocomplete commands.\n */\n private registerCommandsWithRetry(): void {\n this.retryWithBackoff(\n () => this.bot.api.setMyCommands(STATIC_COMMANDS, {\n scope: { type: \"chat\", chat_id: this.telegramConfig.chatId },\n }),\n \"setMyCommands\",\n ).catch((err) => {\n log.warn({ err }, \"Failed to register Telegram commands after retries (non-critical)\");\n });\n }\n\n async stop(): Promise<void> {\n // Cleanup activity trackers (interval timers)\n for (const tracker of this.sessionTrackers.values()) {\n tracker.destroy();\n }\n this.sessionTrackers.clear();\n\n // Clear send queue\n this.sendQueue.clear();\n\n // Destroy assistant session\n if (this.assistantSession) {\n await this.assistantSession.destroy();\n }\n\n await this.bot.stop();\n log.info(\"Telegram bot stopped\");\n }\n\n // --- CommandRegistry response rendering ---\n\n private async renderCommandResponse(\n response: CommandResponse,\n chatId: number,\n topicId?: number,\n ): Promise<void> {\n switch (response.type) {\n case \"text\":\n await this.bot.api.sendMessage(chatId, response.text, {\n message_thread_id: topicId,\n });\n break;\n case \"error\":\n await this.bot.api.sendMessage(\n chatId,\n `\\u26a0\\ufe0f ${response.message}`,\n { message_thread_id: topicId },\n );\n break;\n case \"menu\": {\n const keyboard = response.options.map((opt) => [\n {\n text: `${opt.label}${opt.hint ? ` \\u2014 ${opt.hint}` : \"\"}`,\n callback_data: this.toCallbackData(opt.command),\n },\n ]);\n await this.bot.api.sendMessage(chatId, response.title, {\n message_thread_id: topicId,\n reply_markup: { inline_keyboard: keyboard },\n });\n break;\n }\n case \"list\": {\n const lines = response.items.map(\n (i) => `\\u2022 ${i.label}${i.detail ? ` \\u2014 ${i.detail}` : \"\"}`,\n );\n const text = `${response.title}\\n${lines.join(\"\\n\")}`;\n await this.bot.api.sendMessage(chatId, text, {\n message_thread_id: topicId,\n });\n break;\n }\n case \"confirm\": {\n const buttons = [\n [\n {\n text: \"\\u2705 Yes\",\n callback_data: this.toCallbackData(response.onYes),\n },\n ],\n ];\n if (response.onNo) {\n buttons[0].push({\n text: \"\\u274c No\",\n callback_data: this.toCallbackData(response.onNo),\n });\n }\n await this.bot.api.sendMessage(chatId, response.question, {\n message_thread_id: topicId,\n reply_markup: { inline_keyboard: buttons },\n });\n break;\n }\n case \"silent\":\n break;\n }\n }\n\n private toCallbackData(command: string): string {\n const data = `c/${command}`;\n if (data.length <= 64) return data;\n const id = String(++this.callbackCounter);\n this.callbackCache.set(id, command);\n if (this.callbackCache.size > 1000) {\n const first = this.callbackCache.keys().next().value;\n if (first) this.callbackCache.delete(first);\n }\n return `c/#${id}`;\n }\n\n private fromCallbackData(data: string): string {\n if (data.startsWith(\"c/#\")) {\n return this.callbackCache.get(data.slice(3)) ?? data.slice(2);\n }\n return data.slice(2);\n }\n\n private setupRoutes(): void {\n this.bot.on(\"message:text\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n const text = ctx.message.text;\n\n // Check for pending workspace input from interactive /new flow\n if (\n await handlePendingWorkspaceInput(\n ctx,\n this.core,\n this.telegramConfig.chatId,\n this.assistantTopicId,\n )\n ) {\n return;\n }\n\n // Check for pending workspace input from interactive /resume flow\n if (\n await handlePendingResumeInput(\n ctx,\n this.core,\n this.telegramConfig.chatId,\n this.assistantTopicId,\n )\n ) {\n return;\n }\n\n // General topic or no thread → redirect to assistant\n if (!threadId) {\n const html = redirectToAssistant(\n this.telegramConfig.chatId,\n this.assistantTopicId,\n );\n await ctx.reply(html, { parse_mode: \"HTML\" });\n return;\n }\n\n // Notification topic → ignore\n if (threadId === this.notificationTopicId) return;\n\n // Strip leading \"/\" from unrecognized commands — registered commands\n // (e.g. /new, /cancel) are already handled by bot.command() above.\n // Unrecognized slash commands can cause agent subprocesses to hang.\n const forwardText = text.startsWith(\"/\") ? text.slice(1) : text;\n\n // Assistant topic → forward to assistant session\n if (threadId === this.assistantTopicId) {\n if (!this.assistantSession) {\n await ctx.reply(\n \"⚠️ Assistant is not available yet. Please try again shortly.\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n await this.draftManager.finalize(\n this.assistantSession.id,\n this.assistantSession.id,\n );\n ctx.replyWithChatAction(\"typing\").catch(() => {});\n handleAssistantMessage(this.assistantSession, forwardText).catch(\n (err) => log.error({ err }, \"Assistant error\"),\n );\n return;\n }\n\n // Session topic → forward to core\n const sessionId = this.core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n )?.id;\n if (sessionId) {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"incoming:message\", sessionId, userId: String(ctx.from?.id), text: ctx.message?.text });\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n }\n if (sessionId) {\n const tracker = this.sessionTrackers.get(sessionId);\n if (tracker) await tracker.onNewPrompt();\n }\n ctx.replyWithChatAction(\"typing\").catch(() => {});\n this.core\n .handleMessage({\n channelId: \"telegram\",\n threadId: String(threadId),\n userId: String(ctx.from.id),\n text: forwardText,\n })\n .catch((err) => log.error({ err }, \"handleMessage error\"));\n });\n\n // --- Incoming media handlers ---\n\n this.bot.on(\"message:photo\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n if (!threadId || threadId === this.notificationTopicId) return;\n\n const photos = ctx.message.photo;\n const largest = photos[photos.length - 1];\n const ext = \".jpg\";\n await this.handleIncomingMedia(\n threadId,\n ctx.from.id,\n largest.file_id,\n `photo${ext}`,\n \"image/jpeg\",\n ctx.message.caption || undefined,\n );\n });\n\n this.bot.on(\"message:document\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n if (!threadId || threadId === this.notificationTopicId) return;\n\n const doc = ctx.message.document;\n await this.handleIncomingMedia(\n threadId,\n ctx.from.id,\n doc.file_id,\n doc.file_name || \"document\",\n doc.mime_type || \"application/octet-stream\",\n ctx.message.caption || undefined,\n );\n });\n\n this.bot.on(\"message:voice\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n if (!threadId || threadId === this.notificationTopicId) return;\n\n const voice = ctx.message.voice;\n await this.handleIncomingMedia(\n threadId,\n ctx.from.id,\n voice.file_id,\n \"voice.wav\",\n \"audio/wav\",\n undefined,\n true,\n );\n });\n\n this.bot.on(\"message:audio\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n if (!threadId || threadId === this.notificationTopicId) return;\n\n const audio = ctx.message.audio;\n await this.handleIncomingMedia(\n threadId,\n ctx.from.id,\n audio.file_id,\n audio.file_name || \"audio.mp3\",\n audio.mime_type || \"audio/mpeg\",\n ctx.message.caption || undefined,\n );\n });\n\n this.bot.on(\"message:video_note\", async (ctx) => {\n const threadId = ctx.message.message_thread_id;\n if (!threadId || threadId === this.notificationTopicId) return;\n\n const videoNote = ctx.message.video_note;\n await this.handleIncomingMedia(\n threadId,\n ctx.from.id,\n videoNote.file_id,\n \"video_note.mp4\",\n \"video/mp4\",\n );\n });\n }\n\n // --- MessagingAdapter overrides ---\n\n /**\n * Per-session serial dispatch queues.\n * SessionBridge fires sendMessage() as fire-and-forget, so multiple events\n * (tool_call, tool_update, text) can arrive concurrently. Without serialization,\n * fast handlers (tool_update) overtake slow ones (tool_call with draftManager.finalize),\n * causing out-of-order processing where a tool's completion update is processed before\n * its creation event. This queue ensures events are processed in the order they arrive.\n */\n private _dispatchQueues = new Map<string, Promise<void>>();\n\n private getTracer(sessionId: string): DebugTracer | null {\n return this.core.sessionManager.getSession(sessionId)?.agentInstance?.debugTracer ?? null;\n }\n\n async sendMessage(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n // Suppress assistant messages during system prompt\n if (this.assistantInitializing && sessionId === this.assistantSession?.id)\n return;\n\n const session = this.core.sessionManager.getSession(sessionId);\n if (!session) return;\n\n // Drop messages while topic is being recreated (archive in progress)\n if (session.archiving) return;\n const threadId = Number(session.threadId);\n if (!threadId || isNaN(threadId)) {\n log.warn(\n { sessionId, threadId: session.threadId },\n \"Session has no valid threadId, skipping message\",\n );\n return;\n }\n\n // Serialize dispatch per session to preserve event ordering\n const prev = this._dispatchQueues.get(sessionId) ?? Promise.resolve();\n const next = prev.then(async () => {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"dispatch:enter\", sessionId, message: content });\n this._sessionThreadIds.set(sessionId, threadId);\n try {\n await super.sendMessage(sessionId, content);\n } finally {\n this._sessionThreadIds.delete(sessionId);\n }\n }).catch((err) => {\n log.warn({ err, sessionId }, \"Dispatch queue error\");\n });\n this._dispatchQueues.set(sessionId, next);\n await next;\n }\n\n protected async handleThought(\n sessionId: string,\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:thought\", sessionId, text: content.text });\n const threadId = this.getThreadId(sessionId);\n const mode = this.outputModeResolver.resolve(\n this.context.configManager,\n this.name,\n sessionId,\n this.core.sessionManager,\n );\n const tracker = this.getOrCreateTracker(sessionId, threadId, mode);\n await tracker.onThought(content.text);\n }\n\n protected async handleText(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:text\", sessionId, text: content.text });\n const threadId = this.getThreadId(sessionId);\n // Per-session dispatch queue serializes all events, so we can safely await here.\n if (!this.draftManager.hasDraft(sessionId)) {\n const mode = this.outputModeResolver.resolve(\n this.context.configManager,\n this.name,\n sessionId,\n this.core.sessionManager,\n );\n const tracker = this.getOrCreateTracker(sessionId, threadId, mode);\n await tracker.onTextStart();\n }\n const draft = this.draftManager.getOrCreate(sessionId, threadId, this.getTracer(sessionId));\n draft.append(content.text);\n this.draftManager.appendText(sessionId, content.text);\n }\n\n protected async handleToolCall(\n sessionId: string,\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {\n const threadId = this.getThreadId(sessionId);\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>;\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:toolCall\", sessionId, toolId: meta.id, toolName: meta.name, kind: meta.kind, status: meta.status, displaySummary: meta.displaySummary, rawInput: meta.rawInput });\n\n const mode = this.outputModeResolver.resolve(\n this.context.configManager,\n this.name,\n sessionId,\n this.core.sessionManager,\n );\n const tracker = this.getOrCreateTracker(sessionId, threadId, mode);\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n await tracker.onToolCall(\n {\n id: meta.id ?? \"\",\n name: meta.name ?? content.text ?? \"Tool\",\n kind: meta.kind,\n status: meta.status,\n content: meta.content,\n rawInput: meta.rawInput,\n viewerLinks: meta.viewerLinks,\n viewerFilePath: meta.viewerFilePath,\n displaySummary: meta.displaySummary as string | undefined,\n displayTitle: meta.displayTitle as string | undefined,\n displayKind: meta.displayKind as string | undefined,\n },\n String(meta.kind ?? \"\"),\n meta.rawInput,\n );\n }\n\n protected async handleToolUpdate(\n sessionId: string,\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {\n const threadId = this.getThreadId(sessionId);\n const meta = (content.metadata ?? {}) as Partial<ToolUpdateMeta>;\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:toolUpdate\", sessionId, toolId: meta.id, name: meta.name, kind: meta.kind, status: meta.status, viewerLinks: meta.viewerLinks, viewerFilePath: meta.viewerFilePath });\n const mode = this.outputModeResolver.resolve(\n this.context.configManager,\n this.name,\n sessionId,\n this.core.sessionManager,\n );\n const tracker = this.getOrCreateTracker(sessionId, threadId, mode);\n await tracker.onToolUpdate(\n meta.id ?? \"\",\n meta.status ?? \"completed\",\n meta.viewerLinks as { file?: string; diff?: string } | undefined,\n meta.viewerFilePath as string | undefined,\n typeof meta.content === \"string\" ? meta.content : null,\n meta.rawInput ?? undefined,\n (meta as any).diffStats as { added: number; removed: number } | undefined,\n );\n }\n\n protected async handlePlan(\n sessionId: string,\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): Promise<void> {\n const threadId = this.getThreadId(sessionId);\n const meta = (content.metadata ?? {}) as Partial<PlanMetadata>;\n const entries = meta.entries ?? [];\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:plan\", sessionId, entryCount: entries.length });\n const mode = this.outputModeResolver.resolve(\n this.context.configManager,\n this.name,\n sessionId,\n this.core.sessionManager,\n );\n const tracker = this.getOrCreateTracker(sessionId, threadId, mode);\n await tracker.onPlan(\n entries.map((e) => ({\n content: e.content,\n status: e.status as \"pending\" | \"in_progress\" | \"completed\",\n priority: (e.priority ?? \"medium\") as \"high\" | \"medium\" | \"low\",\n })),\n );\n }\n\n protected async handleUsage(\n sessionId: string,\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): Promise<void> {\n const threadId = this.getThreadId(sessionId);\n const meta = content.metadata as UsageMetadata | undefined;\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:usage\", sessionId, tokensUsed: meta?.tokensUsed, contextSize: meta?.contextSize, cost: (meta as Record<string, unknown>)?.cost });\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n\n // Send usage as a separate message (not part of the tool card)\n const usageText = formatUsage(meta ?? {}, verbosity);\n let usageMsgId: number | undefined;\n try {\n const result = await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(this.telegramConfig.chatId, usageText, {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n usageMsgId = result?.message_id;\n } catch (err) {\n log.warn({ err, sessionId }, \"Failed to send usage message\");\n }\n\n // Notify the Notifications topic that a prompt has completed\n if (this.notificationTopicId && sessionId !== this.assistantSession?.id) {\n const sess = this.core.sessionManager.getSession(sessionId);\n const sessionName = sess?.name || \"Session\";\n const chatIdStr = String(this.telegramConfig.chatId);\n const numericId = chatIdStr.startsWith(\"-100\")\n ? chatIdStr.slice(4)\n : chatIdStr.replace(\"-\", \"\");\n const deepLink = usageMsgId\n ? `https://t.me/c/${numericId}/${threadId}/${usageMsgId}`\n : `https://t.me/c/${numericId}/${threadId}`;\n const text = `✅ <b>${escapeHtml(sessionName)}</b>\\nTask completed.\\n\\n<a href=\"${deepLink}\">→ Go to topic</a>`;\n this.sendQueue\n .enqueue(() =>\n this.bot.api.sendMessage(this.telegramConfig.chatId, text, {\n message_thread_id: this.notificationTopicId,\n parse_mode: \"HTML\",\n disable_notification: false,\n }),\n )\n .catch(() => {});\n }\n }\n\n protected async handleAttachment(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:attachment\", sessionId, type: content.attachment?.type, fileName: content.attachment?.fileName });\n const threadId = this.getThreadId(sessionId);\n if (!content.attachment) return;\n const { attachment } = content;\n\n // Telegram bot API upload limit: 50MB\n if (attachment.size > 50 * 1024 * 1024) {\n log.warn(\n {\n sessionId,\n fileName: attachment.fileName,\n size: attachment.size,\n },\n \"File too large for Telegram (>50MB)\",\n );\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(\n this.telegramConfig.chatId,\n `⚠️ File too large to send (${Math.round(attachment.size / 1024 / 1024)}MB): ${escapeHtml(attachment.fileName)}`,\n { message_thread_id: threadId, parse_mode: \"HTML\" },\n ),\n );\n return;\n }\n\n try {\n const inputFile = new InputFile(attachment.filePath);\n if (attachment.type === \"image\") {\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendPhoto(this.telegramConfig.chatId, inputFile, {\n message_thread_id: threadId,\n }),\n );\n } else if (attachment.type === \"audio\") {\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendVoice(this.telegramConfig.chatId, inputFile, {\n message_thread_id: threadId,\n }),\n );\n // Strip [TTS]...[/TTS] block from the text message after voice is sent\n const draft = this.draftManager.getDraft(sessionId);\n if (draft) {\n draft.stripPattern(/\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/g).catch(() => {});\n }\n } else {\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendDocument(this.telegramConfig.chatId, inputFile, {\n message_thread_id: threadId,\n }),\n );\n }\n } catch (err) {\n log.error(\n { err, sessionId, fileName: attachment.fileName },\n \"Failed to send attachment\",\n );\n }\n }\n\n protected async handleSessionEnd(\n sessionId: string,\n _content: OutgoingMessage,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:sessionEnd\", sessionId });\n const threadId = this.getThreadId(sessionId);\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n this.draftManager.cleanup(sessionId);\n await this.skillManager.cleanup(sessionId);\n const tracker = this.sessionTrackers.get(sessionId);\n if (tracker) {\n await tracker.cleanup();\n this.sessionTrackers.delete(sessionId);\n } else {\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(this.telegramConfig.chatId, `✅ <b>Done</b>`, {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n }\n }\n\n protected async handleError(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:error\", sessionId, text: content.text });\n const threadId = this.getThreadId(sessionId);\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n const tracker = this.sessionTrackers.get(sessionId);\n if (tracker) {\n tracker.destroy();\n this.sessionTrackers.delete(sessionId);\n }\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(\n this.telegramConfig.chatId,\n `❌ <b>Error:</b> ${escapeHtml(content.text)}`,\n {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n },\n ),\n );\n }\n\n protected async handleSystem(\n sessionId: string,\n content: OutgoingMessage,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"handle:system\", sessionId, text: content.text });\n const threadId = this.getThreadId(sessionId);\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(\n this.telegramConfig.chatId,\n escapeHtml(content.text),\n {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n },\n ),\n );\n }\n\n async sendPermissionRequest(\n sessionId: string,\n request: PermissionRequest,\n ): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"permission:send\", sessionId, requestId: request.id, description: request.description });\n log.info({ sessionId, requestId: request.id }, \"Permission request sent\");\n const session = this.core.sessionManager.getSession(sessionId);\n if (!session) return;\n\n await this.sendQueue.enqueue(() =>\n this.permissionHandler.sendPermissionRequest(session, request),\n );\n }\n\n async sendNotification(notification: NotificationMessage): Promise<void> {\n this.getTracer(notification.sessionId)?.log(\"telegram\", { action: \"notification:send\", sessionId: notification.sessionId, type: notification.type });\n if (notification.sessionId === this.assistantSession?.id) return;\n\n log.info(\n { sessionId: notification.sessionId, type: notification.type },\n \"Notification sent\",\n );\n if (!this.notificationTopicId) return;\n const emoji: Record<string, string> = {\n completed: \"✅\",\n error: \"❌\",\n permission: \"🔐\",\n input_required: \"💬\",\n };\n let text = `${emoji[notification.type] || \"ℹ️\"} <b>${escapeHtml(notification.sessionName || \"New session\")}</b>\\n`;\n text += escapeHtml(notification.summary);\n\n const deepLink =\n notification.deepLink ??\n (() => {\n const session = this.core.sessionManager.getSession(\n notification.sessionId,\n );\n const threadId = session?.threadId;\n if (!threadId) return undefined;\n const chatIdStr = String(this.telegramConfig.chatId);\n const numericId = chatIdStr.startsWith(\"-100\")\n ? chatIdStr.slice(4)\n : chatIdStr.replace(\"-\", \"\");\n return `https://t.me/c/${numericId}/${threadId}`;\n })();\n\n if (deepLink) {\n text += `\\n\\n<a href=\"${deepLink}\">→ Go to topic</a>`;\n }\n\n await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(this.telegramConfig.chatId, text, {\n message_thread_id: this.notificationTopicId,\n parse_mode: \"HTML\",\n disable_notification: false,\n }),\n );\n }\n\n async createSessionThread(sessionId: string, name: string): Promise<string> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"thread:create\", sessionId, name });\n log.info({ sessionId, name }, \"Session topic created\");\n return String(\n await createSessionTopic(this.bot, this.telegramConfig.chatId, name),\n );\n }\n\n async renameSessionThread(sessionId: string, newName: string): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"thread:rename\", sessionId, newName });\n const session = this.core.sessionManager.getSession(sessionId);\n if (!session) return;\n const threadId = Number(session.threadId);\n if (!threadId) {\n log.debug({ sessionId, newName }, \"Cannot rename thread — threadId not set yet\");\n return;\n }\n await renameSessionTopic(\n this.bot,\n this.telegramConfig.chatId,\n threadId,\n newName,\n );\n await this.core.sessionManager.patchRecord(sessionId, { name: newName });\n }\n\n async deleteSessionThread(sessionId: string): Promise<void> {\n const record = this.core.sessionManager.getSessionRecord(sessionId);\n const platform = record?.platform as\n | import(\"../../core/types.js\").TelegramPlatformData\n | undefined;\n const topicId = platform?.topicId;\n if (!topicId) return;\n\n try {\n await this.bot.api.deleteForumTopic(this.telegramConfig.chatId, topicId);\n } catch (err) {\n log.warn(\n { err, sessionId, topicId },\n \"Failed to delete forum topic (may already be deleted)\",\n );\n }\n }\n\n async sendSkillCommands(\n sessionId: string,\n commands: AgentCommand[],\n ): Promise<void> {\n if (sessionId === this.assistantSession?.id) return;\n\n const session = this.core.sessionManager.getSession(sessionId);\n if (!session) return;\n const threadId = Number(session.threadId);\n if (!threadId) {\n // Queue for later — flushed when threadId is assigned via flushPendingSkillCommands()\n this._pendingSkillCommands.set(sessionId, commands);\n return;\n }\n\n await this.skillManager.send(sessionId, threadId, commands);\n }\n\n /** Flush any skill commands that were queued before threadId was available */\n async flushPendingSkillCommands(sessionId: string): Promise<void> {\n const commands = this._pendingSkillCommands.get(sessionId);\n if (!commands) return;\n this._pendingSkillCommands.delete(sessionId);\n const session = this.core.sessionManager.getSession(sessionId);\n if (!session) return;\n const threadId = Number(session.threadId);\n if (!threadId) return;\n await this.skillManager.send(sessionId, threadId, commands);\n }\n\n private resolveSessionId(threadId: number): string | undefined {\n return this.core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n )?.id;\n }\n\n private async downloadTelegramFile(\n fileId: string,\n ): Promise<{ buffer: Buffer; filePath: string } | null> {\n try {\n const file = await this.bot.api.getFile(fileId);\n if (!file.file_path) return null;\n const url = `https://api.telegram.org/file/bot${this.telegramConfig.botToken}/${file.file_path}`;\n const response = await fetch(url);\n if (!response.ok) return null;\n const buffer = Buffer.from(await response.arrayBuffer());\n return { buffer, filePath: file.file_path };\n } catch (err) {\n log.error({ err }, \"Failed to download file from Telegram\");\n return null;\n }\n }\n\n private async handleIncomingMedia(\n threadId: number,\n userId: number,\n fileId: string,\n fileName: string,\n mimeType: string,\n caption?: string,\n convertOggToWav?: boolean,\n ): Promise<void> {\n const downloaded = await this.downloadTelegramFile(fileId);\n if (!downloaded) return;\n\n let buffer = downloaded.buffer;\n let originalFilePath: string | undefined;\n const sessionId = this.resolveSessionId(threadId) || \"unknown\";\n\n if (convertOggToWav) {\n // Save original OGG for STT (smaller, API-compatible)\n const oggAtt = await this.fileService.saveFile(\n sessionId,\n \"voice.ogg\",\n downloaded.buffer,\n \"audio/ogg\",\n );\n originalFilePath = oggAtt.filePath;\n\n try {\n buffer = await this.fileService.convertOggToWav(buffer);\n } catch (err) {\n log.warn({ err }, \"OGG→WAV conversion failed, saving original OGG\");\n fileName = \"voice.ogg\";\n mimeType = \"audio/ogg\";\n originalFilePath = undefined;\n }\n }\n\n const att = await this.fileService.saveFile(\n sessionId,\n fileName,\n buffer,\n mimeType,\n );\n if (originalFilePath) {\n att.originalFilePath = originalFilePath;\n }\n\n const rawText =\n caption ||\n `[${att.type === \"image\" ? \"Photo\" : att.type === \"audio\" ? \"Audio\" : \"File\"}: ${att.fileName}]`;\n const text = rawText.startsWith(\"/\") ? rawText.slice(1) : rawText;\n\n // Assistant topic\n if (threadId === this.assistantTopicId) {\n if (this.assistantSession) {\n await this.assistantSession.enqueuePrompt(text, [att]);\n }\n return;\n }\n\n // Session topic\n const sid = this.resolveSessionId(threadId);\n if (sid) await this.draftManager.finalize(sid, this.assistantSession?.id);\n this.core\n .handleMessage({\n channelId: \"telegram\",\n threadId: String(threadId),\n userId: String(userId),\n text,\n attachments: [att],\n })\n .catch((err) => log.error({ err }, \"handleMessage error\"));\n }\n\n async cleanupSkillCommands(sessionId: string): Promise<void> {\n this._pendingSkillCommands.delete(sessionId);\n await this.skillManager.cleanup(sessionId);\n }\n\n async cleanupSessionState(sessionId: string): Promise<void> {\n this._pendingSkillCommands.delete(sessionId);\n // Finalize and clean up draft state\n await this.draftManager.finalize(sessionId, this.assistantSession?.id);\n this.draftManager.cleanup(sessionId);\n\n // Destroy activity tracker (stops ThinkingIndicator timers, finalizes ToolCard)\n const tracker = this.sessionTrackers.get(sessionId);\n if (tracker) {\n tracker.destroy();\n this.sessionTrackers.delete(sessionId);\n }\n }\n\n async stripTTSBlock(sessionId: string): Promise<void> {\n await this.draftManager.stripPattern(sessionId, /\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/g);\n }\n\n async archiveSessionTopic(sessionId: string): Promise<void> {\n this.getTracer(sessionId)?.log(\"telegram\", { action: \"thread:archive\", sessionId });\n const core = this.core as OpenACPCore;\n const session = core.sessionManager.getSession(sessionId);\n if (!session) throw new Error(\"Session not found\");\n\n const chatId = this.telegramConfig.chatId;\n const oldTopicId = Number(session.threadId);\n\n // Set archiving flag — sendMessage will skip while this is true.\n session.archiving = true;\n\n // Finalize any pending draft\n await this.draftManager.finalize(session.id, this.assistantSession?.id);\n\n // Cleanup all trackers\n this.draftManager.cleanup(session.id);\n await this.skillManager.cleanup(session.id);\n const tracker = this.sessionTrackers.get(session.id);\n if (tracker) {\n tracker.destroy();\n this.sessionTrackers.delete(session.id);\n }\n\n // Delete topic (removes all messages) — no recreation\n await deleteSessionTopic(this.bot, chatId, oldTopicId);\n }\n}\n","import type { Bot } from 'grammy'\n\n// Ensure notification and assistant topics exist, create if needed\n// Returns updated topic IDs\nexport async function ensureTopics(\n bot: Bot,\n chatId: number,\n config: { notificationTopicId: number | null; assistantTopicId: number | null },\n saveConfig: (updates: { notificationTopicId?: number; assistantTopicId?: number }) => Promise<void>,\n): Promise<{ notificationTopicId: number; assistantTopicId: number }> {\n let notificationTopicId = config.notificationTopicId\n let assistantTopicId = config.assistantTopicId\n\n if (notificationTopicId === null) {\n const topic = await bot.api.createForumTopic(chatId, '📋 Notifications')\n notificationTopicId = topic.message_thread_id\n await saveConfig({ notificationTopicId })\n }\n\n if (assistantTopicId === null) {\n const topic = await bot.api.createForumTopic(chatId, '🤖 Assistant')\n assistantTopicId = topic.message_thread_id\n await saveConfig({ assistantTopicId })\n }\n\n return { notificationTopicId, assistantTopicId }\n}\n\n// Create a new forum topic for a session\nexport async function createSessionTopic(\n bot: Bot,\n chatId: number,\n name: string,\n): Promise<number> {\n const topic = await bot.api.createForumTopic(chatId, name)\n return topic.message_thread_id\n}\n\n// Rename an existing forum topic\nexport async function renameSessionTopic(\n bot: Bot,\n chatId: number,\n threadId: number,\n name: string,\n): Promise<void> {\n try {\n await bot.api.editForumTopic(chatId, threadId, { name })\n } catch {\n // Ignore rename failures (topic may be closed/deleted)\n }\n}\n\n// Delete a forum topic and all its messages\nexport async function deleteSessionTopic(\n bot: Bot,\n chatId: number,\n threadId: number,\n): Promise<void> {\n await bot.api.deleteForumTopic(chatId, threadId);\n}\n\n// Build a Telegram deep link to a specific message in a forum topic\nexport function buildDeepLink(chatId: number, threadId: number, messageId?: number): string {\n // chatId for supergroups starts with -100, need to strip it for the link\n const cleanId = String(chatId).replace('-100', '')\n // For forum groups: c/{chatId}/{threadId}/{messageId} links to a specific message\n // Without messageId: c/{chatId}/{threadId} links to the topic itself\n if (messageId && messageId !== threadId) {\n return `https://t.me/c/${cleanId}/${threadId}/${messageId}`\n }\n return `https://t.me/c/${cleanId}/${threadId}`\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport type { Session } from \"../../../core/sessions/session.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createSessionTopic, renameSessionTopic, buildDeepLink } from \"../topics.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\nimport { buildSessionControlKeyboard } from \"./admin.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\nconst log = createChildLogger({ module: \"telegram-cmd-new-session\" });\n\ninterface PendingNewSession {\n agentName?: string;\n workspace?: string;\n step: \"agent\" | \"workspace\" | \"workspace_input\" | \"confirm\";\n messageId: number;\n threadId?: number;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst pendingNewSessions = new Map<number, PendingNewSession>();\n\nconst PENDING_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\n\nfunction cleanupPending(userId: number): void {\n const pending = pendingNewSessions.get(userId);\n if (pending) {\n clearTimeout(pending.timer);\n pendingNewSessions.delete(userId);\n }\n}\n\nfunction botFromCtx(ctx: Context): Bot {\n // createSessionTopic only uses bot.api.createForumTopic\n return { api: ctx.api } as unknown as Bot;\n}\n\nexport async function handleNew(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n assistant?: CommandsAssistantContext,\n): Promise<void> {\n const rawMatch = (ctx as Context & { match: unknown }).match;\n const matchStr = typeof rawMatch === \"string\" ? rawMatch : \"\";\n const args = matchStr.split(\" \").filter(Boolean);\n const agentName = args[0];\n const workspace = args[1];\n\n // Full args → create directly\n if (agentName && workspace) {\n await createSessionDirect(ctx, core, chatId, agentName, workspace);\n return;\n }\n\n // In assistant topic → forward to assistant for conversational handling\n const currentThreadId = ctx.message?.message_thread_id;\n if (assistant && currentThreadId === assistant.topicId) {\n const assistantSession = assistant.getSession();\n if (assistantSession) {\n const prompt = agentName\n ? `User wants to create a new session with agent \"${agentName}\" but didn't specify a workspace. Ask them which project directory to use as workspace.`\n : `User wants to create a new session. Guide them through choosing an agent and workspace (project directory).`;\n await assistantSession.enqueuePrompt(prompt);\n return;\n }\n }\n\n // Outside assistant topic → interactive agent picker flow\n await showAgentPicker(ctx, core, chatId, agentName);\n}\n\nasync function startWorkspaceStep(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n userId: number,\n agentName: string,\n): Promise<void> {\n const config = core.configManager.get();\n const baseDir = config.workspace.baseDir;\n\n const keyboard = new InlineKeyboard()\n .text(`📁 Use ${baseDir}`, \"m:new:ws:default\")\n .row()\n .text(\"✏️ Enter project path\", \"m:new:ws:custom\");\n\n const text =\n `📁 <b>Where should ${escapeHtml(agentName)} work?</b>\\n\\n` +\n `Enter the path to your project folder — the agent will read, write, and run code there.\\n\\n` +\n `Or use the default directory below:`;\n\n let msg;\n try {\n const pending = pendingNewSessions.get(userId);\n if (pending?.messageId) {\n await ctx.api.editMessageText(chatId, pending.messageId, text, {\n parse_mode: \"HTML\",\n reply_markup: keyboard,\n });\n msg = { message_id: pending.messageId };\n } else {\n msg = await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n }\n } catch {\n msg = await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n }\n\n cleanupPending(userId);\n pendingNewSessions.set(userId, {\n agentName,\n step: \"workspace\",\n messageId: msg.message_id,\n threadId: ctx.message?.message_thread_id ?? (ctx.callbackQuery?.message as { message_thread_id?: number } | undefined)?.message_thread_id,\n timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS),\n });\n}\n\nasync function startConfirmStep(\n ctx: Context,\n chatId: number,\n userId: number,\n agentName: string,\n workspace: string,\n): Promise<void> {\n const keyboard = new InlineKeyboard()\n .text(\"✅ Create\", \"m:new:confirm\")\n .text(\"❌ Cancel\", \"m:new:cancel\");\n\n const text =\n `✅ <b>Ready to create session?</b>\\n\\n` +\n `<b>Agent:</b> ${escapeHtml(agentName)}\\n` +\n `<b>Project:</b> <code>${escapeHtml(workspace)}</code>`;\n\n let msg;\n try {\n const pending = pendingNewSessions.get(userId);\n if (pending?.messageId) {\n await ctx.api.editMessageText(chatId, pending.messageId, text, {\n parse_mode: \"HTML\",\n reply_markup: keyboard,\n });\n msg = { message_id: pending.messageId };\n } else {\n msg = await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n }\n } catch {\n msg = await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n }\n\n cleanupPending(userId);\n pendingNewSessions.set(userId, {\n agentName,\n workspace,\n step: \"confirm\",\n messageId: msg.message_id,\n threadId: ctx.message?.message_thread_id ?? (ctx.callbackQuery?.message as { message_thread_id?: number } | undefined)?.message_thread_id,\n timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS),\n });\n}\n\nexport async function createSessionDirect(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n agentName: string,\n workspace: string,\n): Promise<number | null> {\n log.info({ userId: ctx.from?.id, agentName, workspace }, \"New session command (direct)\");\n\n let threadId: number | undefined;\n try {\n const topicName = `🔄 New Session`;\n threadId = await createSessionTopic(botFromCtx(ctx), chatId, topicName);\n\n await ctx.api.sendMessage(chatId, `⏳ Setting up session, please wait...`, {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n });\n\n const session = await core.handleNewSession(\"telegram\", agentName, workspace);\n session.threadId = String(threadId);\n\n await core.sessionManager.patchRecord(session.id, { platform: { topicId: threadId } });\n\n const finalName = `🔄 ${session.agentName} — New Session`;\n try {\n await ctx.api.editForumTopic(chatId, threadId, { name: finalName });\n } catch { /* ignore rename failures */ }\n\n await ctx.api.sendMessage(\n chatId,\n `✅ <b>Session started</b>\\n` +\n `<b>Agent:</b> ${escapeHtml(session.agentName)}\\n` +\n `<b>Workspace:</b> <code>${escapeHtml(session.workingDirectory)}</code>\\n\\n` +\n `This is your coding session — chat here to work with the agent.`,\n {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n reply_markup: buildSessionControlKeyboard(session.id, false, false),\n },\n );\n\n session.warmup().catch((err) => log.error({ err }, \"Warm-up error\"));\n return threadId ?? null;\n } catch (err) {\n log.error({ err }, \"Session creation failed\");\n if (threadId) {\n try { await ctx.api.deleteForumTopic(chatId, threadId); } catch { /* ignore */ }\n }\n const message = err instanceof Error ? err.message : (typeof err === 'object' ? JSON.stringify(err) : String(err));\n await ctx.reply(`❌ ${escapeHtml(message)}`, { parse_mode: \"HTML\" });\n return null;\n }\n}\n\nexport async function handleNewChat(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) {\n await ctx.reply(\n \"Use /newchat inside a session topic to inherit its config.\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n // Resolve agent config from existing session/record BEFORE spawning\n const currentSession = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n let agentName: string | undefined;\n let workspace: string | undefined;\n\n if (currentSession) {\n agentName = currentSession.agentName;\n workspace = currentSession.workingDirectory;\n } else {\n const record = core.sessionManager.getRecordByThread(\"telegram\", String(threadId));\n if (!record || record.status === \"cancelled\" || record.status === \"error\") {\n await ctx.reply(\"No active session in this topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n agentName = record.agentName;\n workspace = record.workingDir;\n }\n\n let newThreadId: number | undefined;\n try {\n // Create topic FIRST so threadId is ready before session events fire\n const topicName = `🔄 ${agentName} — New Chat`;\n newThreadId = await createSessionTopic(\n botFromCtx(ctx),\n chatId,\n topicName,\n );\n\n // Notify in the original topic immediately with a deep link to the new one\n const topicLink = buildDeepLink(chatId, newThreadId);\n await ctx.reply(\n `✅ New chat created → <a href=\"${topicLink}\">Open topic</a>`,\n { parse_mode: \"HTML\" },\n );\n\n await ctx.api.sendMessage(chatId, `⏳ Setting up session, please wait...`, {\n message_thread_id: newThreadId,\n parse_mode: \"HTML\",\n });\n\n const session = await core.handleNewSession(\n \"telegram\",\n agentName,\n workspace,\n );\n session.threadId = String(newThreadId);\n\n // Persist platform mapping for new chat\n await core.sessionManager.patchRecord(session.id, { platform: {\n topicId: newThreadId,\n } });\n\n await ctx.api.sendMessage(\n chatId,\n `✅ New chat (same agent & workspace)\\n` +\n `<b>Agent:</b> ${escapeHtml(session.agentName)}\\n` +\n `<b>Workspace:</b> <code>${escapeHtml(session.workingDirectory)}</code>`,\n {\n message_thread_id: newThreadId,\n parse_mode: \"HTML\",\n reply_markup: buildSessionControlKeyboard(session.id, false, false),\n },\n );\n\n // Warm up model cache in background while user types\n session.warmup().catch((err) => log.error({ err }, \"Warm-up error\"));\n } catch (err) {\n // Clean up orphaned topic if session creation failed\n if (newThreadId) {\n try {\n await ctx.api.deleteForumTopic(chatId, newThreadId);\n } catch {\n /* ignore cleanup failures */\n }\n }\n const message = err instanceof Error ? err.message : String(err);\n await ctx.reply(`❌ ${escapeHtml(message)}`, { parse_mode: \"HTML\" });\n }\n}\n\nexport async function executeNewSession(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n agentName?: string,\n workspace?: string,\n): Promise<{ session: Session; threadId: number; firstMsgId: number }> {\n // Create topic with generic name first (same as original handleNew)\n const threadId = await createSessionTopic(bot, chatId, \"🔄 New Session\");\n\n const setupMsg = await bot.api.sendMessage(chatId, \"⏳ Setting up session, please wait...\", {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n });\n const firstMsgId = setupMsg.message_id;\n\n try {\n // core.handleNewSession() already wires events internally — do NOT call wireSessionEvents again\n const session = await core.handleNewSession(\n \"telegram\",\n agentName,\n workspace,\n );\n session.threadId = String(threadId);\n\n await core.sessionManager.patchRecord(session.id, { platform: {\n topicId: threadId,\n } });\n\n // Rename topic with agent name after session is created\n const finalName = `🔄 ${session.agentName} — New Session`;\n await renameSessionTopic(bot, chatId, threadId, finalName);\n\n // Warm up model cache in background while user types\n session.warmup().catch((err) => log.error({ err }, \"Warm-up error\"));\n\n return { session, threadId, firstMsgId };\n } catch (err) {\n // Clean up orphaned topic on failure\n try {\n await bot.api.deleteForumTopic(chatId, threadId);\n } catch {\n /* best effort */\n }\n throw err;\n }\n}\n\n/**\n * Check if a text message is a workspace path input for the interactive new session flow.\n * Returns true if the message was handled (caller should not process further).\n */\nexport async function handlePendingWorkspaceInput(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n assistantTopicId?: number,\n): Promise<boolean> {\n const userId = ctx.from?.id;\n if (!userId) return false;\n const pending = pendingNewSessions.get(userId);\n if (!pending || !ctx.message?.text) return false;\n // Accept text input at both \"workspace\" step (user types directly instead of pressing buttons)\n // and \"workspace_input\" step (user pressed \"Custom path\" button)\n if (pending.step !== \"workspace_input\" && pending.step !== \"workspace\") return false;\n\n // Only intercept in assistant topic (or no-thread/general) — never in session topics\n const threadId = ctx.message.message_thread_id;\n if (threadId && threadId !== assistantTopicId) return false;\n\n let workspace = ctx.message.text.trim();\n if (!workspace || !pending.agentName) {\n await ctx.reply(\"⚠️ Please enter a valid directory path.\", { parse_mode: \"HTML\" });\n return true;\n }\n\n // Relative path (no / or ~ prefix) → resolve against baseDir\n if (!workspace.startsWith(\"/\") && !workspace.startsWith(\"~\")) {\n const baseDir = core.configManager.get().workspace.baseDir;\n workspace = `${baseDir.replace(/\\/$/, \"\")}/${workspace}`;\n }\n\n await startConfirmStep(ctx, chatId, userId, pending.agentName, workspace);\n return true;\n}\n\n/**\n * Start the interactive new session flow (agent → workspace → confirm).\n * Used by action-detect when workspace is not provided.\n */\nexport async function startInteractiveNewSession(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n agentName?: string,\n): Promise<void> {\n await showAgentPicker(ctx, core, chatId, agentName);\n}\n\n/**\n * Shared agent picker logic used by both handleNew and startInteractiveNewSession.\n * Shows agent selection keyboard if multiple agents installed, otherwise skips to workspace step.\n */\nasync function showAgentPicker(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n agentName?: string,\n): Promise<void> {\n const userId = ctx.from?.id;\n if (!userId) return;\n\n const installedEntries = core.agentCatalog.getInstalledEntries();\n const agentKeys = Object.keys(installedEntries);\n const config = core.configManager.get();\n\n // If agent provided or only 1 agent → skip to workspace step\n if (agentName || agentKeys.length === 1) {\n const selectedAgent = agentName || config.defaultAgent;\n await startWorkspaceStep(ctx, core, chatId, userId, selectedAgent);\n return;\n }\n\n // Multiple agents → show agent selection\n const keyboard = new InlineKeyboard();\n for (const key of agentKeys) {\n const agent = installedEntries[key]!;\n const label = key === config.defaultAgent\n ? `${agent.name} (default)`\n : agent.name;\n keyboard.text(label, `m:new:agent:${key}`).row();\n }\n\n const msg = await ctx.reply(\n `🤖 <b>Choose an agent:</b>`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n\n cleanupPending(userId);\n const threadId = ctx.message?.message_thread_id\n ?? (ctx.callbackQuery?.message as { message_thread_id?: number } | undefined)?.message_thread_id;\n pendingNewSessions.set(userId, {\n step: \"agent\",\n messageId: msg.message_id,\n threadId,\n timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS),\n });\n}\n\nexport function setupNewSessionCallbacks(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n): void {\n bot.callbackQuery(/^m:new:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n try {\n await ctx.answerCallbackQuery();\n } catch { /* expired or network — ignore */ }\n\n if (data.startsWith(\"m:new:agent:\")) {\n const agentName = data.replace(\"m:new:agent:\", \"\");\n const userId = ctx.from?.id;\n if (userId) await startWorkspaceStep(ctx, core, chatId, userId, agentName);\n return;\n }\n if (data === \"m:new:ws:default\") {\n const userId = ctx.from?.id;\n if (!userId) return;\n const pending = pendingNewSessions.get(userId);\n if (!pending?.agentName) return;\n const workspace = core.configManager.get().workspace.baseDir;\n await startConfirmStep(ctx, chatId, userId, pending.agentName, workspace);\n return;\n }\n if (data === \"m:new:ws:custom\") {\n const userId = ctx.from?.id;\n if (!userId) return;\n const pending = pendingNewSessions.get(userId);\n if (!pending?.agentName) return;\n try {\n await ctx.api.editMessageText(\n chatId,\n pending.messageId,\n `✏️ <b>Enter your project path:</b>\\n\\n` +\n `Full path like <code>~/code/my-project</code>\\n` +\n `Or just the folder name like <code>my-project</code> (will use ${core.configManager.get().workspace.baseDir}/)`,\n { parse_mode: \"HTML\" },\n );\n } catch {\n await ctx.reply(\n `✏️ <b>Enter your project path:</b>`,\n { parse_mode: \"HTML\" },\n );\n }\n clearTimeout(pending.timer);\n pending.step = \"workspace_input\";\n pending.timer = setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS);\n return;\n }\n if (data === \"m:new:confirm\") {\n const userId = ctx.from?.id;\n if (!userId) return;\n const pending = pendingNewSessions.get(userId);\n if (!pending?.agentName || !pending?.workspace) return;\n cleanupPending(userId);\n const confirmMsgId = pending.messageId;\n try {\n await ctx.api.editMessageText(chatId, confirmMsgId, `⏳ Creating session...`, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n const resultThreadId = await createSessionDirect(ctx, core, chatId, pending.agentName, pending.workspace);\n try {\n if (resultThreadId) {\n const link = buildDeepLink(chatId, resultThreadId);\n await ctx.api.editMessageText(chatId, confirmMsgId, `✅ Session created → <a href=\"${link}\">Open topic</a>`, { parse_mode: \"HTML\" });\n } else {\n await ctx.api.editMessageText(chatId, confirmMsgId, `❌ Session creation failed.`, { parse_mode: \"HTML\" });\n }\n } catch { /* ignore */ }\n return;\n }\n if (data === \"m:new:cancel\") {\n const userId = ctx.from?.id;\n if (userId) cleanupPending(userId);\n try {\n await ctx.editMessageText(\"❌ Session creation cancelled.\", { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n return;\n }\n });\n}\n","import type {\n ToolCallMeta,\n ToolUpdateMeta,\n ViewerLinks,\n} from \"../../core/adapter-primitives/format-types.js\";\nimport type { ToolCardSnapshot } from \"../../core/adapter-primitives/primitives/tool-card-state.js\";\nimport type { ToolDisplaySpec } from \"../../core/adapter-primitives/display-spec-builder.js\";\nimport {\n STATUS_ICONS,\n KIND_ICONS,\n KIND_LABELS,\n} from \"../../core/adapter-primitives/format-types.js\";\nimport {\n progressBar,\n formatTokens,\n truncateContent,\n stripCodeFences,\n splitMessage as sharedSplitMessage,\n} from \"../../core/adapter-primitives/format-utils.js\";\nimport {\n extractContentText,\n formatToolSummary,\n formatToolTitle,\n resolveToolIcon,\n} from \"../../core/adapter-primitives/message-formatter.js\";\nimport type { DisplayVerbosity } from \"../../core/adapter-primitives/format-types.js\";\n\nexport function escapeHtml(text: string | undefined | null): string {\n if (!text) return \"\";\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nexport function markdownToTelegramHtml(md: string): string {\n // Step 1: Extract code blocks and inline code into placeholders\n const codeBlocks: string[] = [];\n const inlineCodes: string[] = [];\n\n // Extract fenced code blocks (```lang\\n...\\n```)\n let text = md.replace(\n /```(\\w*)\\n?([\\s\\S]*?)```/g,\n (_match, lang: string, code: string) => {\n const index = codeBlocks.length;\n const escapedCode = escapeHtml(code);\n const langAttr = lang ? ` class=\"language-${escapeHtml(lang)}\"` : \"\";\n codeBlocks.push(`<pre><code${langAttr}>${escapedCode}</code></pre>`);\n return `\\x00CODE_BLOCK_${index}\\x00`;\n },\n );\n\n // Extract inline code (`...`)\n text = text.replace(/`([^`]+)`/g, (_match, code: string) => {\n const index = inlineCodes.length;\n inlineCodes.push(`<code>${escapeHtml(code)}</code>`);\n return `\\x00INLINE_CODE_${index}\\x00`;\n });\n\n // Step 2: Escape HTML in remaining text\n text = escapeHtml(text);\n\n // Step 3: Apply markdown transformations\n // Bold: **text** → <b>text</b>\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, \"<b>$1</b>\");\n\n // Italic: *text* → <i>text</i> (but not the ** used for bold)\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, \"<i>$1</i>\");\n\n // Links: [text](url) → <a href=\"url\">text</a>\n // Note: after escapeHtml, parentheses are not affected, but we need to handle\n // the escaped brackets properly. Since [ ] and ( ) are not escaped, this works directly.\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\">$1</a>');\n\n // Step 4: Restore fenced code blocks\n text = text.replace(/\\x00CODE_BLOCK_(\\d+)\\x00/g, (_match, idx: string) => {\n return codeBlocks[parseInt(idx, 10)];\n });\n\n // Step 5: Restore inline code\n text = text.replace(/\\x00INLINE_CODE_(\\d+)\\x00/g, (_match, idx: string) => {\n return inlineCodes[parseInt(idx, 10)];\n });\n\n return text;\n}\n\nexport function formatToolCall(\n tool: ToolCallMeta,\n verbosity: DisplayVerbosity = \"medium\",\n): string {\n const si = resolveToolIcon(tool);\n const name = tool.name || \"Tool\";\n const label =\n verbosity === \"low\"\n ? formatToolTitle(name, tool.rawInput, tool.displayTitle)\n : formatToolSummary(name, tool.rawInput, tool.displaySummary);\n let text = `${si} <b>${escapeHtml(label)}</b>`;\n // viewer links always shown regardless of verbosity\n text += formatViewerLinks(tool.viewerLinks, tool.viewerFilePath);\n // high only: rawInput + content\n if (verbosity === \"high\") {\n text += formatHighDetails(tool.rawInput, tool.content, 3800);\n }\n return text;\n}\n\nexport function formatToolUpdate(\n update: ToolUpdateMeta,\n verbosity: DisplayVerbosity = \"medium\",\n): string {\n return formatToolCall(update, verbosity);\n}\n\nfunction formatHighDetails(\n rawInput: unknown,\n content: unknown,\n maxLen: number,\n): string {\n let text = \"\";\n if (rawInput) {\n const inputStr =\n typeof rawInput === \"string\"\n ? rawInput\n : JSON.stringify(rawInput, null, 2);\n if (inputStr && inputStr !== \"{}\") {\n text += `\\n<b>Input:</b>\\n<pre>${escapeHtml(truncateContent(inputStr, maxLen))}</pre>`;\n }\n }\n const details = stripCodeFences(extractContentText(content));\n if (details) {\n text += `\\n<b>Output:</b>\\n<pre>${escapeHtml(truncateContent(details, maxLen))}</pre>`;\n }\n return text;\n}\n\nfunction formatViewerLinks(links?: ViewerLinks, filePath?: string): string {\n if (!links) return \"\";\n const fileName = filePath ? filePath.split(\"/\").pop() || filePath : \"\";\n let text = \"\\n\";\n if (links.file)\n text += `\\n📄 <a href=\"${escapeHtml(links.file)}\">View ${escapeHtml(fileName || \"file\")}</a>`;\n if (links.diff)\n text += `\\n📝 <a href=\"${escapeHtml(links.diff)}\">View diff${fileName ? ` — ${escapeHtml(fileName)}` : \"\"}</a>`;\n return text;\n}\n\nexport function formatPlan(plan: {\n entries: Array<{ content: string; status: string }>;\n}): string {\n const { entries } = plan;\n const statusIcon: Record<string, string> = {\n pending: \"⬜\",\n in_progress: \"🔄\",\n completed: \"✅\",\n };\n const lines = entries.map(\n (e, i) =>\n `${statusIcon[e.status] || \"⬜\"} ${i + 1}. ${escapeHtml(e.content)}`,\n );\n return `<b>Plan:</b>\\n${lines.join(\"\\n\")}`;\n}\n\nexport function formatUsage(\n usage: { tokensUsed?: number; contextSize?: number; cost?: number },\n _verbosity: DisplayVerbosity = \"medium\",\n): string {\n const { tokensUsed, contextSize } = usage;\n if (tokensUsed == null) return \"📊 Usage data unavailable\";\n if (contextSize == null) return `📊 ${formatTokens(tokensUsed)} tokens`;\n\n const ratio = tokensUsed / contextSize;\n const pct = Math.round(ratio * 100);\n const bar = progressBar(ratio);\n const emoji = pct >= 85 ? \"⚠️\" : \"📊\";\n return `${emoji} ${formatTokens(tokensUsed)} / ${formatTokens(contextSize)} tokens\\n${bar} ${pct}%`;\n}\n\nexport function formatSummary(summary: string, sessionName?: string): string {\n const header = sessionName\n ? `📋 <b>Summary — ${escapeHtml(sessionName)}</b>`\n : \"📋 <b>Session Summary</b>\";\n return `${header}\\n\\n${escapeHtml(summary)}`;\n}\n\nexport function splitMessage(text: string, maxLength = 3800): string[] {\n return sharedSplitMessage(text, maxLength);\n}\n\nexport function renderToolCard(snap: ToolCardSnapshot): string {\n const sections: string[] = [];\n\n const { totalVisible, completedVisible, allComplete } = snap;\n const headerCheck = allComplete ? \" ✅\" : \"\";\n if (totalVisible > 0) {\n sections.push(`<b>📋 Tools (${completedVisible}/${totalVisible})</b>${headerCheck}`);\n }\n\n const DONE = new Set([\"completed\", \"done\", \"failed\", \"error\"]);\n const visible = snap.specs.filter((s) => !s.isHidden);\n const completed = visible.filter((s) => DONE.has(s.status));\n const running = visible.filter((s) => !DONE.has(s.status));\n\n for (const spec of completed) {\n sections.push(renderSpecSection(spec));\n }\n\n if (snap.planEntries && snap.planEntries.length > 0) {\n const planDone = snap.planEntries.filter((e) => e.status === \"completed\").length;\n const planTotal = snap.planEntries.length;\n sections.push(`── Plan: ${planDone}/${planTotal} ──`);\n const statusIcon: Record<string, string> = { completed: \"✅\", in_progress: \"🔄\", pending: \"⬜\" };\n for (let i = 0; i < snap.planEntries.length; i++) {\n const e = snap.planEntries[i];\n sections.push(`${statusIcon[e.status] ?? \"⬜\"} ${i + 1}. ${escapeHtml(e.content)}`);\n }\n sections.push(\"────\");\n }\n\n for (const spec of running) {\n sections.push(renderSpecSection(spec));\n }\n\n return sections.join(\"\\n\\n\");\n}\n\nconst FILE_KINDS = new Set([\"read\", \"edit\", \"write\", \"delete\"]);\n\n/** Shorten absolute file paths to just filename (+ line range if present) */\nfunction shortenTitle(title: string, kind: string): string {\n if (!FILE_KINDS.has(kind) || !title.includes(\"/\")) return title;\n // Separate optional parenthesized suffix (e.g. \" (lines 10–50)\" or \" (from line 10)\")\n const parenIdx = title.indexOf(\" (\");\n const pathPart = parenIdx > 0 ? title.slice(0, parenIdx) : title;\n const rangePart = parenIdx > 0 ? title.slice(parenIdx) : \"\";\n const fileName = pathPart.split(\"/\").pop() || pathPart;\n return fileName + rangePart;\n}\n\nfunction renderSpecSection(spec: ToolDisplaySpec): string {\n const lines: string[] = [];\n\n const DONE = new Set([\"completed\", \"done\", \"failed\", \"error\"]);\n // Status prefix at the start so text doesn't shift when status changes\n const statusPrefix =\n spec.status === \"error\" || spec.status === \"failed\"\n ? \"❌ \"\n : DONE.has(spec.status)\n ? \"✅ \"\n : \"🔄 \";\n\n // Build title line: \"✅ 📖 Read · filename.ts\"\n const kindLabel = KIND_LABELS[spec.kind];\n const displayTitle = shortenTitle(spec.title, spec.kind);\n // Suppress title when it duplicates the kind label (e.g. \"Edit · Edit\")\n const hasUniqueTitle = displayTitle && displayTitle.toLowerCase() !== kindLabel?.toLowerCase()\n && displayTitle.toLowerCase() !== spec.kind;\n let titleLine: string;\n if (kindLabel) {\n titleLine = hasUniqueTitle\n ? `${statusPrefix}${spec.icon} <b>${kindLabel}</b> · ${escapeHtml(displayTitle)}`\n : `${statusPrefix}${spec.icon} <b>${kindLabel}</b>`;\n } else {\n titleLine = `${statusPrefix}${spec.icon} ${escapeHtml(displayTitle)}`;\n }\n if (spec.diffStats) {\n const { added, removed } = spec.diffStats;\n if (added > 0 && removed > 0) titleLine += ` · <i>+${added}/-${removed} lines</i>`;\n else if (added > 0) titleLine += ` · <i>+${added} lines</i>`;\n else if (removed > 0) titleLine += ` · <i>-${removed} lines</i>`;\n }\n lines.push(titleLine);\n\n if (spec.description) lines.push(` <i>${escapeHtml(spec.description)}</i>`);\n if (spec.command) lines.push(` <code>${escapeHtml(spec.command)}</code>`);\n if (spec.inputContent) {\n const truncated = spec.inputContent.length > 800 ? spec.inputContent.slice(0, 797) + \"…\" : spec.inputContent;\n lines.push(` <pre><code>${escapeHtml(truncated)}</code></pre>`);\n }\n if (spec.outputSummary) lines.push(` · ${escapeHtml(spec.outputSummary)}`);\n if (spec.outputContent || spec.outputFallbackContent) {\n const raw = spec.outputContent ?? spec.outputFallbackContent!;\n const truncated =\n raw.length > 800\n ? raw.slice(0, 797) + \"…\"\n : raw;\n lines.push(` <pre><code>${escapeHtml(truncated)}</code></pre>`);\n }\n\n if (spec.viewerLinks?.file || spec.viewerLinks?.diff || spec.outputViewerLink) {\n const linkParts: string[] = [];\n const shortName = displayTitle || kindLabel || spec.kind;\n if (spec.viewerLinks?.file)\n linkParts.push(`<a href=\"${escapeHtml(spec.viewerLinks.file)}\">View ${escapeHtml(shortName)}</a>`);\n if (spec.viewerLinks?.diff)\n linkParts.push(`<a href=\"${escapeHtml(spec.viewerLinks.diff)}\">View diff</a>`);\n if (spec.outputViewerLink)\n linkParts.push(`<a href=\"${escapeHtml(spec.outputViewerLink)}\">View output</a>`);\n lines.push(` ${linkParts.join(\" · \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nconst TELEGRAM_MAX_LENGTH = 4096;\n\n/**\n * Split a tool card into multiple chunks at entry boundaries.\n * Each chunk stays under the Telegram message length limit.\n */\nexport function splitToolCardText(text: string): string[] {\n if (text.length <= TELEGRAM_MAX_LENGTH) return [text];\n\n const sections = text.split(\"\\n\\n\");\n const chunks: string[] = [];\n let current = \"\";\n\n for (const section of sections) {\n // Handle single section > limit (truncate with ellipsis)\n const safeSection =\n section.length > TELEGRAM_MAX_LENGTH\n ? section.slice(0, TELEGRAM_MAX_LENGTH - 3) + \"...\"\n : section;\n\n const candidate = current ? `${current}\\n\\n${safeSection}` : safeSection;\n if (candidate.length > TELEGRAM_MAX_LENGTH && current) {\n chunks.push(current);\n current = safeSection;\n } else {\n current = candidate;\n }\n }\n if (current) chunks.push(current);\n return chunks;\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\nconst log = createChildLogger({ module: \"telegram-cmd-admin\" });\n\nexport function buildDangerousModeKeyboard(\n sessionId: string,\n enabled: boolean,\n): InlineKeyboard {\n return new InlineKeyboard().text(\n enabled ? \"🔐 Disable Dangerous Mode\" : \"☠️ Enable Dangerous Mode\",\n `d:${sessionId}`,\n );\n}\n\nexport function setupDangerousModeCallbacks(bot: Bot, core: OpenACPCore): void {\n bot.callbackQuery(/^d:/, async (ctx) => {\n const sessionId = ctx.callbackQuery.data.slice(2);\n const session = core.sessionManager.getSession(sessionId);\n\n // Session live in memory — toggle directly\n if (session) {\n session.dangerousMode = !session.dangerousMode;\n log.info(\n { sessionId, dangerousMode: session.dangerousMode },\n \"Dangerous mode toggled via button\",\n );\n core.sessionManager\n .patchRecord(sessionId, { dangerousMode: session.dangerousMode })\n .catch(() => {});\n\n const toastText = session.dangerousMode\n ? \"☠️ Dangerous mode enabled — permissions auto-approved\"\n : \"🔐 Dangerous mode disabled — permissions shown normally\";\n try {\n await ctx.answerCallbackQuery({ text: toastText });\n } catch {\n /* expired */\n }\n\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: buildSessionControlKeyboard(\n sessionId,\n session.dangerousMode,\n session.voiceMode === \"on\",\n ),\n });\n } catch {\n /* ignore */\n }\n return;\n }\n\n // Session not in memory (e.g. after restart) — toggle directly in store\n const record = core.sessionManager.getSessionRecord(sessionId);\n if (!record || record.status === \"cancelled\" || record.status === \"error\") {\n try {\n await ctx.answerCallbackQuery({\n text: \"⚠️ Session not found or already ended.\",\n });\n } catch {\n /* expired */\n }\n return;\n }\n\n const newDangerousMode = !(record.dangerousMode ?? false);\n core.sessionManager\n .patchRecord(sessionId, { dangerousMode: newDangerousMode })\n .catch(() => {});\n log.info(\n { sessionId, dangerousMode: newDangerousMode },\n \"Dangerous mode toggled via button (store-only, session not in memory)\",\n );\n\n const toastText = newDangerousMode\n ? \"☠️ Dangerous mode enabled — permissions auto-approved\"\n : \"🔐 Dangerous mode disabled — permissions shown normally\";\n try {\n await ctx.answerCallbackQuery({ text: toastText });\n } catch {\n /* expired */\n }\n\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: buildSessionControlKeyboard(\n sessionId,\n newDangerousMode,\n false,\n ),\n });\n } catch {\n /* ignore */\n }\n });\n}\n\nexport async function handleEnableDangerous(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) {\n await ctx.reply(\"⚠️ This command only works inside a session topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n const session = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n if (session) {\n if (session.dangerousMode) {\n await ctx.reply(\"☠️ Dangerous mode is already enabled.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n session.dangerousMode = true;\n core.sessionManager\n .patchRecord(session.id, { dangerousMode: true })\n .catch(() => {});\n } else {\n // Session not in memory (e.g. after restart) — update store directly\n const record = core.sessionManager.getRecordByThread(\n \"telegram\",\n String(threadId),\n );\n if (!record || record.status === \"cancelled\" || record.status === \"error\") {\n await ctx.reply(\"⚠️ No active session in this topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n if (record.dangerousMode) {\n await ctx.reply(\"☠️ Dangerous mode is already enabled.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n core.sessionManager\n .patchRecord(record.sessionId, { dangerousMode: true })\n .catch(() => {});\n }\n await ctx.reply(\n `⚠️ <b>Dangerous mode enabled</b>\\n\\nAll permission requests will be auto-approved. Claude can run arbitrary commands without asking.\\n\\nUse /disable_dangerous to restore normal behaviour.`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function handleDisableDangerous(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) {\n await ctx.reply(\"⚠️ This command only works inside a session topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n const session = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n if (session) {\n if (!session.dangerousMode) {\n await ctx.reply(\"🔐 Dangerous mode is already disabled.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n session.dangerousMode = false;\n core.sessionManager\n .patchRecord(session.id, { dangerousMode: false })\n .catch(() => {});\n } else {\n // Session not in memory (e.g. after restart) — update store directly\n const record = core.sessionManager.getRecordByThread(\n \"telegram\",\n String(threadId),\n );\n if (!record || record.status === \"cancelled\" || record.status === \"error\") {\n await ctx.reply(\"⚠️ No active session in this topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n if (!record.dangerousMode) {\n await ctx.reply(\"🔐 Dangerous mode is already disabled.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n core.sessionManager\n .patchRecord(record.sessionId, { dangerousMode: false })\n .catch(() => {});\n }\n await ctx.reply(\n \"🔐 <b>Dangerous mode disabled</b>\\n\\nPermission requests will be shown normally.\",\n { parse_mode: \"HTML\" },\n );\n}\n\nexport function buildTTSKeyboard(\n sessionId: string,\n enabled: boolean,\n): InlineKeyboard {\n return new InlineKeyboard().text(\n enabled ? \"🔊 Text to Speech\" : \"🔇 Text to Speech\",\n `v:${sessionId}`,\n );\n}\n\nexport function buildSessionControlKeyboard(\n sessionId: string,\n dangerousMode: boolean,\n voiceMode: boolean,\n): InlineKeyboard {\n return new InlineKeyboard()\n .text(\n dangerousMode ? \"🔐 Disable Dangerous Mode\" : \"☠️ Enable Dangerous Mode\",\n `d:${sessionId}`,\n )\n .row()\n .text(\n voiceMode ? \"🔊 Text to Speech\" : \"🔇 Text to Speech\",\n `v:${sessionId}`,\n );\n}\n\nexport function setupTTSCallbacks(bot: Bot, core: OpenACPCore): void {\n bot.callbackQuery(/^v:/, async (ctx) => {\n const sessionId = ctx.callbackQuery.data.slice(2);\n const session = core.sessionManager.getSession(sessionId);\n\n if (!session) {\n try {\n await ctx.answerCallbackQuery({\n text: \"⚠️ Session not found or not active.\",\n });\n } catch {}\n return;\n }\n\n // Check if TTS provider is available\n if (session.voiceMode !== \"on\" && !core.speechService?.isTTSAvailable()) {\n try {\n await ctx.answerCallbackQuery({\n text: \"⚠️ TTS provider not installed. Use /tts install to set up.\",\n });\n } catch {}\n return;\n }\n\n const newMode = session.voiceMode === \"on\" ? \"off\" : \"on\";\n session.setVoiceMode(newMode);\n\n const toastText =\n newMode === \"on\"\n ? \"🔊 Text to Speech enabled\"\n : \"🔇 Text to Speech disabled\";\n try {\n await ctx.answerCallbackQuery({ text: toastText });\n } catch {}\n\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: buildSessionControlKeyboard(\n sessionId,\n session.dangerousMode,\n newMode === \"on\",\n ),\n });\n } catch {\n /* ignore */\n }\n });\n}\n\nexport async function handleTTS(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) {\n await ctx.reply(\"⚠️ This command only works inside a session topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n const session = await core.getOrResumeSession(\"telegram\", String(threadId));\n if (!session) {\n await ctx.reply(\"⚠️ No active session in this topic.\", {\n parse_mode: \"HTML\",\n });\n return;\n }\n\n const args = ctx.message?.text?.split(/\\s+/).slice(1) ?? [];\n const arg = args[0]?.toLowerCase();\n\n // Check if TTS provider is available before enabling\n if (arg === \"on\" || (!arg)) {\n if (!core.speechService?.isTTSAvailable()) {\n await ctx.reply(\n \"⚠️ TTS provider not installed.\\n\\nUse <code>/tts install</code> to install Edge TTS plugin.\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n }\n\n if (arg === \"on\") {\n session.setVoiceMode(\"on\");\n await ctx.reply(\"🔊 Text to Speech enabled for this session.\", {\n parse_mode: \"HTML\",\n });\n } else if (arg === \"off\") {\n session.setVoiceMode(\"off\");\n await ctx.reply(\"🔇 Text to Speech disabled.\", { parse_mode: \"HTML\" });\n } else {\n session.setVoiceMode(\"next\");\n await ctx.reply(\"🔊 Text to Speech enabled for the next message.\", {\n parse_mode: \"HTML\",\n });\n }\n}\n\n// ─── Verbosity (deprecated alias) ──────────────────────────────────────────\n\nexport async function handleVerbosity(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n // Deprecated — alias for /outputmode\n await ctx.reply(\"⚠️ <code>/verbosity</code> is deprecated. Use <code>/outputmode</code> instead.\", { parse_mode: \"HTML\" });\n await handleOutputMode(ctx, core);\n}\n\n// ─── Output Mode ────────────────────────────────────────────────────────────\n\nconst OUTPUT_MODE_LABELS: Record<string, string> = {\n low: \"🔇 Low\",\n medium: \"📊 Medium\",\n high: \"🔍 High\",\n};\n\nexport async function handleOutputMode(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const args = ctx.message?.text?.split(/\\s+/).slice(1) ?? [];\n const arg0 = args[0]?.toLowerCase();\n const arg1 = args[1]?.toLowerCase();\n\n // /outputmode session [low|medium|high|reset]\n if (arg0 === \"session\") {\n const chatId = ctx.chat?.id;\n const threadId = ctx.message?.message_thread_id;\n if (!chatId || threadId === undefined) {\n await ctx.reply(\"⚠️ This command must be used in a session topic.\", { parse_mode: \"HTML\" });\n return;\n }\n\n const session = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n\n if (!session) {\n await ctx.reply(\"⚠️ No active session found for this topic.\", { parse_mode: \"HTML\" });\n return;\n }\n\n if (arg1 === \"reset\") {\n await core.sessionManager.patchRecord(session.id, { outputMode: undefined });\n await ctx.reply(\"🔄 Session output mode reset to adapter default.\", { parse_mode: \"HTML\" });\n } else if (arg1 === \"low\" || arg1 === \"medium\" || arg1 === \"high\") {\n await core.sessionManager.patchRecord(session.id, { outputMode: arg1 });\n await ctx.reply(\n `${OUTPUT_MODE_LABELS[arg1]} Session output mode set to <b>${arg1}</b>.`,\n { parse_mode: \"HTML\" },\n );\n } else {\n const record = core.sessionManager.getSessionRecord(session.id);\n const current = record?.outputMode ?? \"(adapter default)\";\n await ctx.reply(\n `📊 Session output mode: <b>${current}</b>\\n\\nUsage: <code>/outputmode session low|medium|high|reset</code>`,\n { parse_mode: \"HTML\" },\n );\n }\n return;\n }\n\n // /outputmode [low|medium|high] — adapter-level\n if (arg0 === \"low\" || arg0 === \"medium\" || arg0 === \"high\") {\n await core.configManager.save(\n { channels: { telegram: { outputMode: arg0 } } },\n \"channels.telegram.outputMode\",\n );\n await ctx.reply(\n `${OUTPUT_MODE_LABELS[arg0]} Output mode set to <b>${arg0}</b>.`,\n { parse_mode: \"HTML\" },\n );\n } else {\n const current =\n (core.configManager.get().channels?.telegram as Record<string, unknown> | undefined)\n ?.outputMode ?? \"medium\";\n await ctx.reply(\n `📊 Current output mode: <b>${current}</b>\\n\\n` +\n `Usage: <code>/outputmode low|medium|high</code>\\n` +\n `Session override: <code>/outputmode session low|medium|high|reset</code>\\n\\n` +\n `• <b>low</b> — minimal: title only\\n` +\n `• <b>medium</b> — balanced: description + output summary (default)\\n` +\n `• <b>high</b> — full detail: inline output, IN/OUT blocks`,\n { parse_mode: \"HTML\" },\n );\n }\n}\n\nexport function setupVerbosityCallbacks(bot: Bot, core: OpenACPCore): void {\n bot.callbackQuery(/^vb:/, async (ctx) => {\n const level = ctx.callbackQuery.data.slice(3);\n if (level !== \"low\" && level !== \"medium\" && level !== \"high\") return;\n\n await core.configManager.save(\n { channels: { telegram: { outputMode: level } } },\n \"channels.telegram.outputMode\",\n );\n\n try {\n await ctx.answerCallbackQuery({\n text: `${OUTPUT_MODE_LABELS[level]} Output mode: ${level}`,\n });\n } catch {}\n });\n}\n\nexport async function handleUpdate(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n if (!core.requestRestart) {\n await ctx.reply(\n \"⚠️ Update is not available (no restart handler registered).\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n const { getCurrentVersion, getLatestVersion, compareVersions, runUpdate } =\n await import(\"../../../cli/version.js\");\n const current = getCurrentVersion();\n const statusMsg = await ctx.reply(\n `🔍 Checking for updates... (current: v${escapeHtml(current)})`,\n { parse_mode: \"HTML\" },\n );\n\n const latest = await getLatestVersion();\n if (!latest) {\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n \"❌ Could not check for updates.\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n if (compareVersions(current, latest) >= 0) {\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n `✅ Already up to date (v${escapeHtml(current)}).`,\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n `⬇️ Updating v${escapeHtml(current)} → v${escapeHtml(latest)}...`,\n { parse_mode: \"HTML\" },\n );\n\n const ok = await runUpdate();\n if (!ok) {\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n \"❌ Update failed. Try manually: <code>npm install -g @openacp/cli@latest</code>\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n `✅ Updated to v${escapeHtml(latest)}. Restarting...`,\n { parse_mode: \"HTML\" },\n );\n\n await new Promise((r) => setTimeout(r, 500));\n await core.requestRestart();\n}\n\nexport async function handleRestart(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n if (!core.requestRestart) {\n await ctx.reply(\n \"⚠️ Restart is not available (no restart handler registered).\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n await ctx.reply(\n \"🔄 <b>Restarting OpenACP...</b>\\nRebuilding and restarting. Be back shortly.\",\n { parse_mode: \"HTML\" },\n );\n // Give Telegram a moment to deliver the message before shutting down\n await new Promise((r) => setTimeout(r, 500));\n await core.requestRestart();\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport type { Session } from \"../../../core/sessions/session.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\nconst log = createChildLogger({ module: \"telegram-cmd-session\" });\n\nexport async function handleCancel(\n ctx: Context,\n core: OpenACPCore,\n assistant?: CommandsAssistantContext,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) return;\n\n // In assistant topic: forward to assistant for confirmation\n if (assistant && threadId === assistant.topicId) {\n const assistantSession = assistant.getSession();\n if (assistantSession) {\n await assistantSession.enqueuePrompt(\n \"User wants to cancel a session. Confirm which session to cancel.\",\n );\n return;\n }\n }\n\n const session = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n if (session) {\n log.info({ sessionId: session.id }, \"Abort prompt command\");\n await session.abortPrompt();\n await ctx.reply(\"⛔ Prompt aborted. Session is still active — send a new message to continue.\", { parse_mode: \"HTML\" });\n return;\n }\n\n // Fallback: session not in memory — nothing to abort, but session can\n // still be resumed when the user sends a new message.\n const record = core.sessionManager.getRecordByThread(\"telegram\", String(threadId));\n if (record && record.status !== \"error\") {\n log.info({ sessionId: record.sessionId, status: record.status }, \"Cancel command — no active prompt to abort\");\n await ctx.reply(\"ℹ️ No active prompt to cancel. Send a new message to resume the session.\", { parse_mode: \"HTML\" });\n }\n}\n\nexport async function handleStatus(ctx: Context, core: OpenACPCore): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (threadId) {\n const session = core.sessionManager.getSessionByThread(\n \"telegram\",\n String(threadId),\n );\n if (session) {\n await ctx.reply(\n `<b>Session:</b> ${escapeHtml(session.name || session.id)}\\n` +\n `<b>Agent:</b> ${escapeHtml(session.agentName)}\\n` +\n `<b>Status:</b> ${escapeHtml(session.status)}\\n` +\n `<b>Workspace:</b> <code>${escapeHtml(session.workingDirectory)}</code>\\n` +\n `<b>Queue:</b> ${session.queueDepth} pending`,\n { parse_mode: \"HTML\" },\n );\n } else {\n // Fallback: show stored session info when not loaded in memory (e.g. after restart)\n const record = core.sessionManager.getRecordByThread(\"telegram\", String(threadId));\n if (record) {\n await ctx.reply(\n `<b>Session:</b> ${escapeHtml(record.name || record.sessionId)}\\n` +\n `<b>Agent:</b> ${escapeHtml(record.agentName)}\\n` +\n `<b>Status:</b> ${escapeHtml(record.status)} (not loaded)\\n` +\n `<b>Workspace:</b> <code>${escapeHtml(record.workingDir)}</code>`,\n { parse_mode: \"HTML\" },\n );\n } else {\n await ctx.reply(\"No active session in this topic.\", {\n parse_mode: \"HTML\",\n });\n }\n }\n } else {\n const sessions = core.sessionManager.listSessions(\"telegram\");\n const active = sessions.filter(\n (s) => s.status === \"active\" || s.status === \"initializing\",\n );\n await ctx.reply(\n `<b>OpenACP Status</b>\\n` +\n `Active sessions: ${active.length}\\n` +\n `Total sessions: ${sessions.length}`,\n { parse_mode: \"HTML\" },\n );\n }\n}\n\nexport async function handleTopics(ctx: Context, core: OpenACPCore): Promise<void> {\n try {\n const allRecords = core.sessionManager.listRecords();\n\n // Only show sessions that have a Telegram topic (skip headless/CLI-only)\n const records = allRecords.filter((r) => {\n const platform = r.platform as { topicId?: number };\n return !!platform?.topicId;\n });\n\n const headlessCount = allRecords.length - records.length;\n\n if (records.length === 0) {\n const extra = headlessCount > 0 ? ` (${headlessCount} headless hidden)` : \"\";\n await ctx.reply(`No sessions with topics found.${extra}`, { parse_mode: \"HTML\" });\n return;\n }\n\n const statusEmoji: Record<string, string> = {\n active: \"🟢\",\n initializing: \"🟡\",\n finished: \"✅\",\n error: \"❌\",\n cancelled: \"⛔\",\n };\n\n // Sort: active/initializing first, then by lastActiveAt desc\n const statusOrder: Record<string, number> = { active: 0, initializing: 1, error: 2, finished: 3, cancelled: 4 };\n records.sort((a, b) => (statusOrder[a.status] ?? 5) - (statusOrder[b.status] ?? 5));\n\n const MAX_DISPLAY = 30;\n const displayed = records.slice(0, MAX_DISPLAY);\n\n const lines = displayed.map((r) => {\n const emoji = statusEmoji[r.status] || \"⚪\";\n const name = r.name?.trim();\n const label = name ? escapeHtml(name) : `<i>${escapeHtml(r.agentName)} session</i>`;\n return `${emoji} ${label} <code>[${r.status}]</code>`;\n });\n\n const header = `<b>Sessions: ${records.length}</b>` +\n (headlessCount > 0 ? ` (${headlessCount} headless hidden)` : \"\");\n const truncated = records.length > MAX_DISPLAY ? `\\n\\n<i>...and ${records.length - MAX_DISPLAY} more</i>` : \"\";\n\n // Count by status for cleanup buttons (include headless sessions)\n const finishedCount = allRecords.filter((r) => r.status === \"finished\").length;\n const errorCount = allRecords.filter((r) => r.status === \"error\" || r.status === \"cancelled\").length;\n\n const keyboard = new InlineKeyboard();\n if (finishedCount > 0) {\n keyboard.text(`Cleanup finished (${finishedCount})`, \"m:cleanup:finished\").row();\n }\n if (errorCount > 0) {\n keyboard.text(`Cleanup errors (${errorCount})`, \"m:cleanup:errors\").row();\n }\n if (finishedCount + errorCount > 0) {\n keyboard.text(`Cleanup all non-active (${finishedCount + errorCount})`, \"m:cleanup:all\").row();\n }\n keyboard.text(`⚠️ Cleanup ALL (${allRecords.length})`, \"m:cleanup:everything\").row();\n keyboard.text(\"Refresh\", \"m:topics\");\n\n await ctx.reply(\n `${header}\\n\\n${lines.join(\"\\n\")}${truncated}`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n } catch (err) {\n log.error({ err }, \"handleTopics error\");\n await ctx.reply(\"❌ Failed to list sessions.\", { parse_mode: \"HTML\" }).catch(() => {});\n }\n}\n\nexport async function handleCleanup(ctx: Context, core: OpenACPCore, chatId: number, statuses: string[]): Promise<void> {\n const allRecords = core.sessionManager.listRecords();\n const cleanable = allRecords.filter((r) => statuses.includes(r.status));\n\n if (cleanable.length === 0) {\n await ctx.reply(\"Nothing to clean up.\", { parse_mode: \"HTML\" });\n return;\n }\n\n let deleted = 0;\n let failed = 0;\n\n for (const record of cleanable) {\n try {\n const topicId = (record.platform as { topicId?: number })?.topicId;\n if (topicId) {\n try {\n await ctx.api.deleteForumTopic(chatId, topicId);\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId, topicId }, \"Failed to delete forum topic during cleanup\");\n }\n }\n await core.sessionManager.removeRecord(record.sessionId);\n deleted++;\n } catch (err) {\n log.error({ err, sessionId: record.sessionId }, \"Failed to cleanup session\");\n failed++;\n }\n }\n\n await ctx.reply(\n `🗑 Cleaned up <b>${deleted}</b> sessions${failed > 0 ? ` (${failed} failed)` : \"\"}.`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function handleCleanupEverything(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n systemTopicIds?: { notificationTopicId: number; assistantTopicId: number },\n): Promise<void> {\n const allRecords = core.sessionManager.listRecords();\n const cleanable = allRecords.filter((r) => {\n const platform = r.platform as { topicId?: number };\n if (systemTopicIds && platform?.topicId && (platform.topicId === systemTopicIds.notificationTopicId || platform.topicId === systemTopicIds.assistantTopicId)) return false;\n return true;\n });\n\n if (cleanable.length === 0) {\n await ctx.reply(\"Nothing to clean up.\", { parse_mode: \"HTML\" });\n return;\n }\n\n // Group by status for breakdown\n const statusCounts = new Map<string, number>();\n for (const r of cleanable) {\n statusCounts.set(r.status, (statusCounts.get(r.status) ?? 0) + 1);\n }\n\n const statusEmoji: Record<string, string> = {\n active: \"🟢\", initializing: \"🟡\", finished: \"✅\", error: \"❌\", cancelled: \"⛔\",\n };\n\n const breakdown = Array.from(statusCounts.entries())\n .map(([status, count]) => `${statusEmoji[status] ?? \"⚪\"} ${status}: ${count}`)\n .join(\"\\n\");\n\n const activeCount = (statusCounts.get(\"active\") ?? 0) + (statusCounts.get(\"initializing\") ?? 0);\n const activeWarning = activeCount > 0\n ? `\\n\\n⚠️ <b>${activeCount} active session(s) will be cancelled and their agents stopped!</b>`\n : \"\";\n\n const keyboard = new InlineKeyboard()\n .text(\"Yes, delete all\", \"m:cleanup:everything:confirm\")\n .text(\"Cancel\", \"m:topics\");\n\n await ctx.reply(\n `<b>Delete ${cleanable.length} topics?</b>\\n\\n` +\n `This will:\\n` +\n `• Delete all session topics from this group\\n` +\n `• Cancel any running agent sessions\\n` +\n `• Remove all session records\\n\\n` +\n `<b>Breakdown:</b>\\n${breakdown}${activeWarning}\\n\\n` +\n `<i>Notifications and Assistant topics will NOT be deleted.</i>`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n}\n\nexport async function handleCleanupEverythingConfirmed(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n systemTopicIds?: { notificationTopicId: number; assistantTopicId: number },\n): Promise<void> {\n const allRecords = core.sessionManager.listRecords();\n const cleanable = allRecords.filter((r) => {\n const platform = r.platform as { topicId?: number };\n if (systemTopicIds && platform?.topicId && (platform.topicId === systemTopicIds.notificationTopicId || platform.topicId === systemTopicIds.assistantTopicId)) return false;\n return true;\n });\n\n if (cleanable.length === 0) {\n await ctx.reply(\"Nothing to clean up.\", { parse_mode: \"HTML\" });\n return;\n }\n\n let deleted = 0;\n let failed = 0;\n\n for (const record of cleanable) {\n try {\n // Cancel active sessions first\n if (record.status === \"active\" || record.status === \"initializing\") {\n try {\n await core.sessionManager.cancelSession(record.sessionId);\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId }, \"Failed to cancel session during cleanup\");\n }\n }\n\n const topicId = (record.platform as { topicId?: number })?.topicId;\n if (topicId) {\n try {\n await ctx.api.deleteForumTopic(chatId, topicId);\n } catch (err) {\n log.warn({ err, sessionId: record.sessionId, topicId }, \"Failed to delete forum topic during cleanup\");\n }\n }\n await core.sessionManager.removeRecord(record.sessionId);\n deleted++;\n } catch (err) {\n log.error({ err, sessionId: record.sessionId }, \"Failed to cleanup session\");\n failed++;\n }\n }\n\n await ctx.reply(\n `🗑 Cleaned up <b>${deleted}</b> sessions${failed > 0 ? ` (${failed} failed)` : \"\"}.`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function executeCancelSession(\n core: OpenACPCore,\n excludeSessionId?: string,\n): Promise<Session | null> {\n const sessions = core.sessionManager\n .listSessions(\"telegram\")\n .filter((s) => s.status === \"active\" && s.id !== excludeSessionId)\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n\n const session = sessions[0];\n if (!session) return null;\n\n await session.abortPrompt();\n return session;\n}\n\nexport function setupSessionCallbacks(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n systemTopicIds?: { notificationTopicId: number; assistantTopicId: number },\n): void {\n bot.callbackQuery(/^m:cleanup/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n try {\n await ctx.answerCallbackQuery();\n } catch { /* expired */ }\n\n switch (data) {\n case \"m:cleanup:finished\":\n await handleCleanup(ctx, core, chatId, [\"finished\"]);\n break;\n case \"m:cleanup:errors\":\n await handleCleanup(ctx, core, chatId, [\"error\", \"cancelled\"]);\n break;\n case \"m:cleanup:all\":\n await handleCleanup(ctx, core, chatId, [\"finished\", \"error\", \"cancelled\"]);\n break;\n case \"m:cleanup:everything\":\n await handleCleanupEverything(ctx, core, chatId, systemTopicIds);\n break;\n case \"m:cleanup:everything:confirm\":\n await handleCleanupEverythingConfirmed(ctx, core, chatId, systemTopicIds);\n break;\n }\n });\n}\n\nexport async function handleArchive(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) return;\n\n // Check in-memory session first, then fall back to stored record\n const session = core.sessionManager.getSessionByThread(\"telegram\", String(threadId));\n const record = !session ? core.sessionManager.getRecordByThread(\"telegram\", String(threadId)) : undefined;\n\n // Must be used in a session topic (not orphan or non-session)\n if (!session && !record) {\n await ctx.reply(\"This topic is not linked to a session.\", { parse_mode: \"HTML\" });\n return;\n }\n\n const identifier = session?.id ?? record?.sessionId;\n if (!identifier) {\n await ctx.reply(\"Could not determine session for this topic.\", { parse_mode: \"HTML\" });\n return;\n }\n\n // Session must be active (not initializing)\n const status = session?.status ?? record?.status;\n if (status === \"initializing\") {\n await ctx.reply(\"Cannot archive a session that is still initializing. Wait for it to become active.\", { parse_mode: \"HTML\" });\n return;\n }\n\n await ctx.reply(\n \"⚠️ <b>Archive this session?</b>\\n\\n\" +\n \"This will:\\n\" +\n \"• Stop the agent session\\n\" +\n \"• Delete this topic permanently\\n\\n\" +\n \"<i>This cannot be undone.</i>\",\n {\n parse_mode: \"HTML\",\n reply_markup: new InlineKeyboard()\n .text(\"🗑 Yes, archive\", `ar:yes:${identifier}`)\n .text(\"❌ Cancel\", `ar:no:${identifier}`),\n },\n );\n}\n\nexport async function handleArchiveConfirm(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n): Promise<void> {\n const data = ctx.callbackQuery?.data;\n if (!data) return;\n\n try {\n await ctx.answerCallbackQuery();\n } catch { /* expired */ }\n\n // Format: ar:<action>:<identifier> where identifier is sessionId\n const [, action, ...rest] = data.split(\":\");\n const identifier = rest.join(\":\");\n\n if (action === \"no\") {\n await ctx.editMessageText(\"Archive cancelled.\", { parse_mode: \"HTML\" });\n return;\n }\n\n // action === \"yes\"\n // Note: we don't editMessageText here because the topic is about to be deleted\n\n const result = await core.archiveSession(identifier);\n if (!result.ok) {\n try {\n await ctx.editMessageText(`Failed to archive: <code>${escapeHtml(result.error)}</code>`, { parse_mode: \"HTML\" });\n } catch {\n core.notificationManager.notifyAll({\n sessionId: identifier,\n type: \"error\",\n summary: `Failed to archive session \"${identifier}\": ${result.error}`,\n });\n }\n }\n}\n\n","import type { Bot, Context } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\n\n// Domain modules\nimport { handleNew, handleNewChat, setupNewSessionCallbacks, createSessionDirect } from './new-session.js'\nimport { handleCancel, handleStatus, handleTopics, handleArchive, handleArchiveConfirm, setupSessionCallbacks } from './session.js'\nimport { handleEnableDangerous, handleDisableDangerous, handleUpdate, handleRestart, handleTTS, handleVerbosity, handleOutputMode } from './admin.js'\nimport { handleMenu, handleHelp, handleClear, buildMenuKeyboard } from './menu.js'\nimport { handleAgents, handleInstall, handleAgentCallback } from \"./agents.js\";\nimport { handleIntegrate } from \"./integrate.js\";\nimport {\n handleResume,\n setupResumeCallbacks,\n handlePendingResumeInput,\n} from \"./resume.js\";\nimport { handleSettings, setupSettingsCallbacks } from \"./settings.js\";\nimport { handleDoctor, setupDoctorCallbacks } from \"./doctor.js\";\nimport { handleTunnel, handleTunnels, setupTunnelCallbacks } from \"./tunnel.js\";\nimport { handleSwitch, setupSwitchCallbacks } from \"./switch.js\";\n\nexport function setupCommands(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n assistant?: CommandsAssistantContext,\n): void {\n bot.command(\"new\", (ctx) => handleNew(ctx, core, chatId, assistant));\n bot.command(\"newchat\", (ctx) => handleNewChat(ctx, core, chatId));\n bot.command(\"cancel\", (ctx) => handleCancel(ctx, core, assistant));\n bot.command(\"status\", (ctx) => handleStatus(ctx, core));\n bot.command(\"sessions\", (ctx) => handleTopics(ctx, core));\n bot.command(\"agents\", (ctx) => handleAgents(ctx, core));\n bot.command(\"install\", (ctx) => handleInstall(ctx, core));\n bot.command(\"help\", (ctx) => handleHelp(ctx));\n bot.command(\"menu\", (ctx) => handleMenu(ctx));\n bot.command(\"enable_dangerous\", (ctx) => handleEnableDangerous(ctx, core));\n bot.command(\"disable_dangerous\", (ctx) => handleDisableDangerous(ctx, core));\n bot.command(\"restart\", (ctx) => handleRestart(ctx, core));\n bot.command(\"update\", (ctx) => handleUpdate(ctx, core));\n bot.command(\"integrate\", (ctx) => handleIntegrate(ctx, core));\n bot.command(\"clear\", (ctx) => handleClear(ctx, assistant));\n bot.command(\"doctor\", (ctx) => handleDoctor(ctx));\n bot.command(\"tunnel\", (ctx) => handleTunnel(ctx, core));\n bot.command(\"tunnels\", (ctx) => handleTunnels(ctx, core));\n bot.command(\"archive\", (ctx) => handleArchive(ctx, core));\n bot.command(\"text_to_speech\", (ctx) => handleTTS(ctx, core));\n bot.command(\"verbosity\", (ctx) => handleVerbosity(ctx, core));\n bot.command(\"outputmode\", (ctx) => handleOutputMode(ctx, core));\n bot.command(\"resume\", (ctx) => handleResume(ctx, core, chatId, assistant));\n bot.command(\"switch\", (ctx) => handleSwitch(ctx, core));\n}\n\nexport function setupAllCallbacks(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n systemTopicIds?: { notificationTopicId: number; assistantTopicId: number },\n getAssistantSession?: () =>\n | { topicId: number; enqueuePrompt: (p: string) => Promise<void> }\n | undefined,\n): void {\n // Register specific prefix handlers FIRST (grammY middleware order matters)\n setupNewSessionCallbacks(bot, core, chatId);\n setupResumeCallbacks(bot, core, chatId);\n setupSessionCallbacks(bot, core, chatId, systemTopicIds);\n\n // Settings handlers — must be before broad m: handler\n setupSettingsCallbacks(bot, core, getAssistantSession ?? (() => undefined));\n\n // Doctor handlers — must be before broad m: handler\n setupDoctorCallbacks(bot);\n\n // Tunnel callbacks — must be before broad m: handler\n setupTunnelCallbacks(bot, core);\n\n // Switch agent callbacks — must be before broad m: handler\n setupSwitchCallbacks(bot, core);\n\n // Agent callbacks (install + pagination) — must be before broad m: handler\n bot.callbackQuery(/^ag:/, (ctx) => handleAgentCallback(ctx, core));\n\n // New session with specific agent callback — must be before broad m: handler\n bot.callbackQuery(/^na:/, async (ctx) => {\n const agentKey = ctx.callbackQuery.data!.replace(\"na:\", \"\");\n await ctx.answerCallbackQuery();\n await createSessionDirect(\n ctx,\n core,\n chatId,\n agentKey,\n core.configManager.get().workspace.baseDir,\n );\n });\n\n // Archive confirmation callbacks\n bot.callbackQuery(/^ar:/, (ctx) => handleArchiveConfirm(ctx, core, chatId));\n\n // Broad m: handler for remaining menu dispatch — LAST\n bot.callbackQuery(/^m:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n try {\n await ctx.answerCallbackQuery();\n } catch {\n /* expired or network — ignore */\n }\n\n switch (data) {\n case \"m:new\":\n await handleNew(ctx, core, chatId);\n break;\n case \"m:status\":\n await handleStatus(ctx, core);\n break;\n case \"m:agents\":\n await handleAgents(ctx, core);\n break;\n case \"m:help\":\n await handleHelp(ctx);\n break;\n case \"m:restart\":\n await handleRestart(ctx, core);\n break;\n case \"m:update\":\n await handleUpdate(ctx, core);\n break;\n case \"m:integrate\":\n await handleIntegrate(ctx, core);\n break;\n case \"m:topics\":\n await handleTopics(ctx, core);\n break;\n case \"m:settings\":\n await handleSettings(ctx, core);\n break;\n }\n });\n}\n\n// Backward compat alias\nexport { setupAllCallbacks as setupMenuCallbacks };\n\n// Re-exports for external consumers (adapter.ts, action-detect.ts)\nexport { buildMenuKeyboard } from \"./menu.js\";\nexport { buildSkillMessages } from \"./menu.js\";\nexport {\n handlePendingWorkspaceInput,\n executeNewSession,\n startInteractiveNewSession,\n} from \"./new-session.js\";\nexport { executeCancelSession } from \"./session.js\";\nexport {\n setupDangerousModeCallbacks,\n buildDangerousModeKeyboard,\n} from \"./admin.js\";\nexport {\n setupTTSCallbacks,\n setupVerbosityCallbacks,\n buildTTSKeyboard,\n buildSessionControlKeyboard,\n handleTTS,\n handleVerbosity,\n handleOutputMode,\n} from \"./admin.js\";\nexport { setupIntegrateCallbacks } from \"./integrate.js\";\nexport { setupSettingsCallbacks } from \"./settings.js\";\nexport { setupDoctorCallbacks } from \"./doctor.js\";\nexport { handlePendingResumeInput, setupResumeCallbacks } from \"./resume.js\";\n\nexport const STATIC_COMMANDS = [\n { command: \"new\", description: \"Create new session\" },\n { command: \"newchat\", description: \"New chat, same agent & workspace\" },\n { command: \"cancel\", description: \"Cancel current session\" },\n { command: \"status\", description: \"Show status\" },\n { command: \"sessions\", description: \"List all sessions\" },\n { command: \"agents\", description: \"List available agents\" },\n { command: \"install\", description: \"Install a new agent\" },\n { command: \"help\", description: \"Help\" },\n { command: \"menu\", description: \"Show menu\" },\n {\n command: \"enable_dangerous\",\n description: \"Auto-approve all permission requests (session only)\",\n },\n {\n command: \"disable_dangerous\",\n description: \"Restore normal permission prompts (session only)\",\n },\n { command: \"integrate\", description: \"Manage agent integrations\" },\n { command: \"handoff\", description: \"Continue this session in your terminal\" },\n { command: \"clear\", description: \"Clear assistant history\" },\n { command: \"restart\", description: \"Restart OpenACP\" },\n { command: \"update\", description: \"Update to latest version and restart\" },\n { command: \"doctor\", description: \"Run system diagnostics\" },\n { command: \"tunnel\", description: \"Create/stop tunnel for a local port\" },\n { command: \"tunnels\", description: \"List active tunnels\" },\n { command: 'archive', description: 'Archive session topic (recreate with clean history)' },\n { command: 'text_to_speech', description: 'Toggle Text to Speech (/text_to_speech on, /text_to_speech off)' },\n { command: 'verbosity', description: 'Deprecated: use /outputmode instead' },\n { command: \"outputmode\", description: \"Control output display level (low/medium/high)\" },\n { command: 'resume', description: 'Resume with conversation history from Entire checkpoints' },\n { command: 'switch', description: 'Switch agent in current session' },\n];\n","import type { Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/core.js\";\nimport type { InstallProgress } from \"../../../core/types.js\";\nimport { escapeHtml } from \"../formatting.js\";\n\nconst AGENTS_PER_PAGE = 6;\n\nexport async function handleAgents(ctx: Context, core: OpenACPCore, page = 0): Promise<void> {\n const catalog = core.agentCatalog;\n const items = catalog.getAvailable();\n\n const installed = items.filter((i) => i.installed);\n const available = items.filter((i) => !i.installed);\n\n let text = \"<b>🤖 Agents</b>\\n\\n\";\n\n // Installed agents section\n if (installed.length > 0) {\n text += \"<b>Installed:</b>\\n\";\n for (const item of installed) {\n text += `✅ <b>${escapeHtml(item.name)}</b>`;\n if (item.description) {\n text += ` — <i>${escapeHtml(truncate(item.description, 50))}</i>`;\n }\n text += \"\\n\";\n }\n text += \"\\n\";\n }\n\n // Available agents section (paginated)\n if (available.length > 0) {\n const totalPages = Math.ceil(available.length / AGENTS_PER_PAGE);\n const safePage = Math.max(0, Math.min(page, totalPages - 1));\n const pageItems = available.slice(safePage * AGENTS_PER_PAGE, (safePage + 1) * AGENTS_PER_PAGE);\n\n text += `<b>Available to install:</b>`;\n if (totalPages > 1) {\n text += ` (${safePage + 1}/${totalPages})`;\n }\n text += \"\\n\";\n\n for (const item of pageItems) {\n if (item.available) {\n text += `⬇️ <b>${escapeHtml(item.name)}</b>`;\n } else {\n const deps = item.missingDeps?.join(\", \") ?? \"requirements not met\";\n text += `⚠️ <b>${escapeHtml(item.name)}</b> <i>(needs: ${escapeHtml(deps)})</i>`;\n }\n if (item.description) {\n text += `\\n <i>${escapeHtml(truncate(item.description, 60))}</i>`;\n }\n text += \"\\n\";\n }\n\n // Install buttons for current page\n const keyboard = new InlineKeyboard();\n const installable = pageItems.filter((i) => i.available);\n for (let i = 0; i < installable.length; i += 2) {\n const row = installable.slice(i, i + 2);\n for (const item of row) {\n keyboard.text(`⬇️ ${item.name}`, `ag:install:${item.key}`);\n }\n keyboard.row();\n }\n\n // Pagination buttons\n if (totalPages > 1) {\n if (safePage > 0) {\n keyboard.text(\"◀️ Prev\", `ag:page:${safePage - 1}`);\n }\n if (safePage < totalPages - 1) {\n keyboard.text(\"Next ▶️\", `ag:page:${safePage + 1}`);\n }\n keyboard.row();\n }\n\n // Tip for CLI install\n if (available.some((i) => !i.available)) {\n text += \"\\n💡 <i>Agents marked ⚠️ need additional setup. Use</i> <code>openacp agents info <name></code> <i>for details.</i>\\n\";\n }\n\n await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n } else {\n text += \"<i>All agents are already installed!</i>\";\n await ctx.reply(text, { parse_mode: \"HTML\" });\n }\n}\n\nexport async function handleInstall(ctx: Context, core: OpenACPCore): Promise<void> {\n const text = (ctx.message?.text ?? \"\").trim();\n const parts = text.split(/\\s+/);\n const nameOrId = parts[1];\n\n if (!nameOrId) {\n await ctx.reply(\n \"📦 <b>Install an agent</b>\\n\\n\" +\n \"Usage: <code>/install <agent-name></code>\\n\" +\n \"Example: <code>/install gemini</code>\\n\\n\" +\n \"Use /agents to browse available agents.\",\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n await installAgentWithProgress(ctx, core, nameOrId);\n}\n\nexport async function handleAgentCallback(ctx: Context, core: OpenACPCore): Promise<void> {\n const data = ctx.callbackQuery?.data ?? \"\";\n await ctx.answerCallbackQuery();\n\n if (data.startsWith(\"ag:install:\")) {\n const nameOrId = data.replace(\"ag:install:\", \"\");\n await installAgentWithProgress(ctx, core, nameOrId);\n return;\n }\n\n if (data.startsWith(\"ag:page:\")) {\n const page = parseInt(data.replace(\"ag:page:\", \"\"), 10);\n // Edit the existing message with the new page\n try {\n const catalog = core.agentCatalog;\n const items = catalog.getAvailable();\n const installed = items.filter((i) => i.installed);\n const available = items.filter((i) => !i.installed);\n\n let text = \"<b>🤖 Agents</b>\\n\\n\";\n\n if (installed.length > 0) {\n text += \"<b>Installed:</b>\\n\";\n for (const item of installed) {\n text += `✅ <b>${escapeHtml(item.name)}</b>`;\n if (item.description) {\n text += ` — <i>${escapeHtml(truncate(item.description, 50))}</i>`;\n }\n text += \"\\n\";\n }\n text += \"\\n\";\n }\n\n const totalPages = Math.ceil(available.length / AGENTS_PER_PAGE);\n const safePage = Math.max(0, Math.min(page, totalPages - 1));\n const pageItems = available.slice(safePage * AGENTS_PER_PAGE, (safePage + 1) * AGENTS_PER_PAGE);\n\n text += `<b>Available to install:</b>`;\n if (totalPages > 1) {\n text += ` (${safePage + 1}/${totalPages})`;\n }\n text += \"\\n\";\n\n for (const item of pageItems) {\n if (item.available) {\n text += `⬇️ <b>${escapeHtml(item.name)}</b>`;\n } else {\n const deps = item.missingDeps?.join(\", \") ?? \"requirements not met\";\n text += `⚠️ <b>${escapeHtml(item.name)}</b> <i>(needs: ${escapeHtml(deps)})</i>`;\n }\n if (item.description) {\n text += `\\n <i>${escapeHtml(truncate(item.description, 60))}</i>`;\n }\n text += \"\\n\";\n }\n\n const keyboard = new InlineKeyboard();\n const installable = pageItems.filter((i) => i.available);\n for (let i = 0; i < installable.length; i += 2) {\n const row = installable.slice(i, i + 2);\n for (const item of row) {\n keyboard.text(`⬇️ ${item.name}`, `ag:install:${item.key}`);\n }\n keyboard.row();\n }\n\n if (totalPages > 1) {\n if (safePage > 0) {\n keyboard.text(\"◀️ Prev\", `ag:page:${safePage - 1}`);\n }\n if (safePage < totalPages - 1) {\n keyboard.text(\"Next ▶️\", `ag:page:${safePage + 1}`);\n }\n keyboard.row();\n }\n\n await ctx.editMessageText(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n } catch { /* ignore edit failures */ }\n }\n}\n\nasync function installAgentWithProgress(ctx: Context, core: OpenACPCore, nameOrId: string): Promise<void> {\n const catalog = core.agentCatalog;\n const msg = await ctx.reply(`⏳ Installing <b>${escapeHtml(nameOrId)}</b>...`, { parse_mode: \"HTML\" });\n\n let lastEdit = 0;\n const EDIT_THROTTLE_MS = 1500;\n\n const progress: InstallProgress = {\n onStart(_id, _name) { /* initial message already sent */ },\n async onStep(step) {\n const now = Date.now();\n if (now - lastEdit > EDIT_THROTTLE_MS) {\n lastEdit = now;\n try {\n await ctx.api.editMessageText(msg.chat.id, msg.message_id, `⏳ <b>${escapeHtml(nameOrId)}</b>: ${escapeHtml(step)}`, { parse_mode: \"HTML\" });\n } catch { /* rate limit or unchanged */ }\n }\n },\n async onDownloadProgress(percent) {\n const now = Date.now();\n if (now - lastEdit > EDIT_THROTTLE_MS) {\n lastEdit = now;\n try {\n const bar = buildProgressBar(percent);\n await ctx.api.editMessageText(msg.chat.id, msg.message_id, `⏳ <b>${escapeHtml(nameOrId)}</b>\\nDownloading... ${bar} ${percent}%`, { parse_mode: \"HTML\" });\n } catch { /* rate limit */ }\n }\n },\n async onSuccess(name) {\n try {\n const keyboard = new InlineKeyboard().text(`🚀 Start session with ${name}`, `na:${nameOrId}`);\n await ctx.api.editMessageText(msg.chat.id, msg.message_id, `✅ <b>${escapeHtml(name)}</b> installed!`, { parse_mode: \"HTML\", reply_markup: keyboard });\n } catch { /* ignore */ }\n },\n async onError(error) {\n try {\n await ctx.api.editMessageText(msg.chat.id, msg.message_id, `❌ ${escapeHtml(error)}`, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n },\n };\n\n const result = await catalog.install(nameOrId, progress);\n\n // Auto-integrate handoff if agent supports it\n if (result.ok) {\n const { getAgentCapabilities } = await import(\"../../../core/agents/agent-dependencies.js\");\n const caps = getAgentCapabilities(result.agentKey);\n if (caps.integration) {\n const { installIntegration } = await import(\"../../../cli/integrate.js\");\n const intResult = await installIntegration(result.agentKey, caps.integration);\n if (intResult.success) {\n try {\n await ctx.reply(`🔗 Handoff integration installed for <b>${escapeHtml(result.agentKey)}</b>`, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n }\n }\n }\n\n // Show setup steps as a follow-up message with copyable commands\n if (result.ok && result.setupSteps?.length) {\n let setupText = `📋 <b>Setup for ${escapeHtml(result.agentKey)}:</b>\\n\\n`;\n for (const step of result.setupSteps) {\n setupText += `→ ${formatSetupStep(step)}\\n`;\n }\n setupText += `\\n💡 <i>Tap any command to copy it</i>`;\n try {\n await ctx.reply(setupText, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n }\n}\n\n/**\n * Format a setup step for Telegram, wrapping commands in <code> for tap-to-copy.\n * Patterns handled:\n * \"Install Claude CLI: npm install -g @anthropic-ai/claude-code\"\n * \"Login: claude login (opens browser)\"\n * \"Or set API key: export OPENAI_API_KEY=<your-key>\"\n * \"Free tier: 60 requests/min\" (no command — plain text)\n */\nfunction formatSetupStep(step: string): string {\n const colonIdx = step.indexOf(\": \");\n if (colonIdx === -1) return escapeHtml(step);\n\n const label = step.slice(0, colonIdx);\n const rest = step.slice(colonIdx + 2);\n\n // Check if the part after \":\" looks like a command (starts with known command prefixes)\n const cmdPrefixes = [\n \"npm \", \"npx \", \"pip \", \"uvx \", \"export \", \"claude \", \"codex \",\n \"openacp \", \"goose \", \"gemini \", \"cursor \", \"gh \",\n ];\n const looksLikeCommand = cmdPrefixes.some((p) => rest.startsWith(p));\n\n if (looksLikeCommand) {\n // Split command from parenthetical explanation: \"claude login (opens browser)\"\n const parenIdx = rest.indexOf(\" (\");\n if (parenIdx !== -1) {\n const cmd = rest.slice(0, parenIdx);\n const explanation = rest.slice(parenIdx);\n return `${escapeHtml(label)}: <code>${escapeHtml(cmd)}</code> ${escapeHtml(explanation)}`;\n }\n return `${escapeHtml(label)}: <code>${escapeHtml(rest)}</code>`;\n }\n\n return escapeHtml(step);\n}\n\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen - 1) + \"…\";\n}\n\nfunction buildProgressBar(percent: number): string {\n const filled = Math.round(percent / 10);\n const empty = 10 - filled;\n return \"█\".repeat(filled) + \"░\".repeat(empty);\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport { escapeHtml } from \"../formatting.js\";\n\nexport async function handleIntegrate(ctx: Context, _core: OpenACPCore): Promise<void> {\n const { listIntegrations } = await import(\"../../../cli/integrate.js\");\n const agents = listIntegrations();\n\n const keyboard = new InlineKeyboard();\n for (const agent of agents) {\n keyboard.text(`🤖 ${agent}`, `i:agent:${agent}`).row();\n }\n\n await ctx.reply(\n `<b>🔗 Integrations</b>\\n\\nSelect an agent to manage its integrations.`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n}\n\nfunction buildAgentItemsKeyboard(agentName: string, items: import(\"../../../cli/integrate.js\").IntegrationItem[]): InlineKeyboard {\n const keyboard = new InlineKeyboard();\n for (const item of items) {\n const installed = item.isInstalled();\n keyboard.text(\n installed ? `✅ ${item.name} — Uninstall` : `📦 ${item.name} — Install`,\n installed ? `i:uninstall:${agentName}:${item.id}` : `i:install:${agentName}:${item.id}`,\n ).row();\n }\n keyboard.text(\"← Back\", \"i:back\").row();\n return keyboard;\n}\n\nexport function setupIntegrateCallbacks(\n bot: Bot,\n core: OpenACPCore,\n): void {\n bot.callbackQuery(/^i:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n try {\n await ctx.answerCallbackQuery();\n } catch {\n /* expired */\n }\n\n // Back to agent list\n if (data === \"i:back\") {\n const { listIntegrations } = await import(\"../../../cli/integrate.js\");\n const agents = listIntegrations();\n const keyboard = new InlineKeyboard();\n for (const agent of agents) {\n keyboard.text(`🤖 ${agent}`, `i:agent:${agent}`).row();\n }\n try {\n await ctx.editMessageText(\n `<b>🔗 Integrations</b>\\n\\nSelect an agent to manage its integrations.`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n } catch { /* message unchanged */ }\n return;\n }\n\n // Show agent items\n const agentMatch = data.match(/^i:agent:(.+)$/);\n if (agentMatch) {\n const agentName = agentMatch[1];\n const { getIntegration } = await import(\"../../../cli/integrate.js\");\n const integration = getIntegration(agentName);\n if (!integration) {\n await ctx.reply(`❌ No integration available for '${escapeHtml(agentName)}'.`, { parse_mode: \"HTML\" });\n return;\n }\n const keyboard = buildAgentItemsKeyboard(agentName, integration.items);\n try {\n await ctx.editMessageText(\n `<b>🔗 ${escapeHtml(agentName)} Integrations</b>\\n\\n${integration.items.map((i) => `• <b>${escapeHtml(i.name)}</b> — ${escapeHtml(i.description)}`).join(\"\\n\")}`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n } catch {\n await ctx.reply(\n `<b>🔗 ${escapeHtml(agentName)} Integrations</b>`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n }\n return;\n }\n\n // Install / uninstall item\n const actionMatch = data.match(/^i:(install|uninstall):([^:]+):(.+)$/);\n if (!actionMatch) return;\n\n const action = actionMatch[1] as \"install\" | \"uninstall\";\n const agentName = actionMatch[2];\n const itemId = actionMatch[3];\n\n const { getIntegration } = await import(\"../../../cli/integrate.js\");\n const integration = getIntegration(agentName);\n if (!integration) return;\n\n const item = integration.items.find((i) => i.id === itemId);\n if (!item) return;\n\n const result = action === \"install\"\n ? await item.install()\n : await item.uninstall();\n\n // Save state to config\n const installed = action === \"install\" && result.success;\n await core.configManager.save({\n integrations: {\n [agentName]: {\n installed,\n installedAt: installed ? new Date().toISOString() : undefined,\n },\n },\n });\n\n const statusEmoji = result.success ? \"✅\" : \"❌\";\n const actionLabel = action === \"install\" ? \"installed\" : \"uninstalled\";\n const logsText = result.logs.map((l) => `<code>${escapeHtml(l)}</code>`).join(\"\\n\");\n const resultText = `${statusEmoji} <b>${escapeHtml(item.name)}</b> ${actionLabel}.\\n\\n${logsText}`;\n\n const keyboard = buildAgentItemsKeyboard(agentName, integration.items);\n try {\n await ctx.editMessageText(\n `<b>🔗 ${escapeHtml(agentName)} Integrations</b>\\n\\n${resultText}`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n } catch {\n await ctx.reply(resultText, { parse_mode: \"HTML\" });\n }\n });\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport type { ContextQuery } from \"../../../plugins/context/context-provider.js\";\nimport { DEFAULT_MAX_TOKENS } from \"../../../plugins/context/context-provider.js\";\nimport { CheckpointReader } from \"../../../plugins/context/entire/checkpoint-reader.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createSessionTopic, buildDeepLink } from \"../topics.js\";\nimport { buildSessionControlKeyboard } from \"./admin.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\n\nconst log = createChildLogger({ module: \"telegram-cmd-resume\" });\n\nconst PENDING_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\n\nfunction botFromCtx(ctx: Context): Bot {\n return { api: ctx.api } as unknown as Bot;\n}\n\n// --- Pending state for interactive workspace picker ---\n\ninterface PendingResume {\n query: Omit<ContextQuery, \"repoPath\">;\n step: \"workspace\" | \"workspace_input\";\n messageId: number;\n threadId?: number;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst pendingResumes = new Map<number, PendingResume>();\n\nfunction cleanupPending(userId: number): void {\n const pending = pendingResumes.get(userId);\n if (pending) {\n clearTimeout(pending.timer);\n pendingResumes.delete(userId);\n }\n}\n\n// --- Arg parsing ---\n\nexport function parseResumeArgs(matchStr: string): { query: Omit<ContextQuery, \"repoPath\"> } | null {\n const args = matchStr.split(\" \").filter(Boolean);\n if (args.length === 0) return { query: { type: \"latest\", value: \"5\" } };\n\n const first = args[0];\n\n // Subcommands\n if (first === \"pr\") return args[1] ? { query: { type: \"pr\", value: args[1] } } : null;\n if (first === \"branch\") return args[1] ? { query: { type: \"branch\", value: args[1] } } : null;\n if (first === \"commit\") return args[1] ? { query: { type: \"commit\", value: args[1] } } : null;\n\n // Auto-detect ID format\n if (CheckpointReader.isCheckpointId(first)) return { query: { type: \"checkpoint\", value: first } };\n if (CheckpointReader.isSessionId(first)) return { query: { type: \"session\", value: first } };\n\n // GitHub PR URL: github.com/org/repo/pull/19\n if (first.includes(\"/pull/\")) {\n const prMatch = first.match(/\\/pull\\/(\\d+)/);\n return prMatch ? { query: { type: \"pr\", value: prMatch[1] } } : null;\n }\n\n // GitHub commit URL: github.com/org/repo/commit/e0dd2fa4...\n const ghCommitMatch = first.match(/github\\.com\\/[^/]+\\/[^/]+\\/commit\\/([0-9a-f]+)/);\n if (ghCommitMatch) return { query: { type: \"commit\", value: ghCommitMatch[1] } };\n\n // GitHub branch URL: github.com/org/repo/tree/branch-name\n const ghBranchMatch = first.match(/github\\.com\\/[^/]+\\/[^/]+\\/tree\\/(.+?)(?:\\?|#|$)/);\n if (ghBranchMatch) return { query: { type: \"branch\", value: ghBranchMatch[1] } };\n\n // GitHub compare URL: github.com/org/repo/compare/base...head\n const ghCompareMatch = first.match(/github\\.com\\/[^/]+\\/[^/]+\\/compare\\/(?:[^.]+\\.{2,3})(.+?)(?:\\?|#|$)/);\n if (ghCompareMatch) return { query: { type: \"branch\", value: ghCompareMatch[1] } };\n\n // GitHub bare repo URL: github.com/org/repo (no subpath) → latest\n if (first.match(/github\\.com\\/[^/]+\\/[^/]+\\/?$/) && !first.includes(\"/tree/\") && !first.includes(\"/pull/\") && !first.includes(\"/commit/\") && !first.includes(\"/compare/\")) {\n return { query: { type: \"latest\", value: \"5\" } };\n }\n\n // Entire.io checkpoint URL: entire.io/gh/{owner}/{repo}/checkpoints/{branch}/{checkpoint_id}\n const entireCheckpointMatch = first.match(/entire\\.io\\/gh\\/[^/]+\\/[^/]+\\/checkpoints\\/[^/]+\\/([0-9a-f]{12})/);\n if (entireCheckpointMatch) return { query: { type: \"checkpoint\", value: entireCheckpointMatch[1] } };\n\n // Entire.io commit URL: entire.io/gh/{owner}/{repo}/commit/{commit_hash}\n const entireCommitMatch = first.match(/entire\\.io\\/gh\\/[^/]+\\/[^/]+\\/commit\\/([0-9a-f]+)/);\n if (entireCommitMatch) return { query: { type: \"commit\", value: entireCommitMatch[1] } };\n\n // Unknown — default to latest\n return { query: { type: \"latest\", value: \"5\" } };\n}\n\nfunction looksLikePath(text: string): boolean {\n return text.startsWith(\"/\") || text.startsWith(\"~\") || text.startsWith(\".\");\n}\n\n// --- List subdirectories in workspace baseDir ---\n\nfunction listWorkspaceDirs(baseDir: string, maxItems = 10): string[] {\n const resolved = baseDir.replace(/^~/, os.homedir());\n try {\n if (!fs.existsSync(resolved)) return [];\n return fs.readdirSync(resolved, { withFileTypes: true })\n .filter(d => d.isDirectory() && !d.name.startsWith(\".\"))\n .map(d => d.name)\n .sort()\n .slice(0, maxItems);\n } catch {\n return [];\n }\n}\n\n// --- Workspace picker step ---\n\nasync function showWorkspacePicker(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n userId: number,\n query: Omit<ContextQuery, \"repoPath\">,\n): Promise<void> {\n const config = core.configManager.get();\n const baseDir = config.workspace.baseDir;\n const resolvedBase = baseDir.replace(/^~/, os.homedir());\n const subdirs = listWorkspaceDirs(baseDir);\n\n const keyboard = new InlineKeyboard();\n\n // List subdirectories as buttons\n for (const dir of subdirs) {\n const fullPath = path.join(resolvedBase, dir);\n keyboard.text(`📁 ${dir}`, `m:resume:ws:${dir}`).row();\n }\n\n // Always offer base dir and custom input\n keyboard.text(`📁 Use ${baseDir}`, \"m:resume:ws:default\").row();\n keyboard.text(\"✏️ Enter project path\", \"m:resume:ws:custom\");\n\n const queryLabel = query.type === \"latest\" ? \"latest sessions\" : `${query.type}: ${query.value}`;\n const text =\n `📁 <b>Select project directory for resume</b>\\n\\n` +\n `Query: <code>${escapeHtml(queryLabel)}</code>\\n\\n` +\n `Choose the repo that has Entire checkpoints enabled:`;\n\n const msg = await ctx.reply(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n\n cleanupPending(userId);\n pendingResumes.set(userId, {\n query,\n step: \"workspace\",\n messageId: msg.message_id,\n threadId: ctx.message?.message_thread_id,\n timer: setTimeout(() => pendingResumes.delete(userId), PENDING_TIMEOUT_MS),\n });\n}\n\n// --- Execute resume with resolved workspace ---\n\nasync function executeResume(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n query: Omit<ContextQuery, \"repoPath\">,\n repoPath: string,\n): Promise<void> {\n // Check provider availability\n const provider = await core.contextManager.getProvider(repoPath);\n if (!provider) {\n await ctx.reply(\n `⚠️ <b>Entire not enabled in <code>${escapeHtml(repoPath)}</code></b>\\n\\n` +\n `To enable conversation history tracking:\\n` +\n `<code>cd ${escapeHtml(repoPath)} && npx entire enable</code>\\n\\n` +\n `Learn more: https://docs.entire.io/getting-started`,\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n // Scan sessions\n const fullQuery: ContextQuery = { ...query, repoPath };\n\n await ctx.reply(`🔍 Scanning ${query.type === \"latest\" ? \"latest sessions\" : `${query.type}: ${escapeHtml(query.value)}`}...`, { parse_mode: \"HTML\" });\n\n const listResult = await core.contextManager.listSessions(fullQuery);\n if (!listResult || listResult.sessions.length === 0) {\n await ctx.reply(\n `🔍 <b>No sessions found</b>\\n\\n` +\n `Query: <code>${escapeHtml(query.type)}: ${escapeHtml(query.value)}</code>\\n` +\n `Repo: <code>${escapeHtml(repoPath)}</code>`,\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n const config = core.configManager.get();\n const agentName = config.defaultAgent;\n\n let threadId: number | undefined;\n try {\n // Create topic FIRST (before session events fire — prevent race condition)\n const queryLabel = query.type === \"latest\" ? \"latest\" : `${query.type}: ${query.value.slice(0, 20)}`;\n const topicName = `📜 Resume — ${queryLabel}`;\n threadId = await createSessionTopic(botFromCtx(ctx), chatId, topicName);\n\n await ctx.api.sendMessage(chatId, `⏳ Loading context and starting session...`, {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n });\n\n // TODO: Over-budget interactive selection not yet implemented (F7)\n // Spec says: show options when context > 30K tokens, auto-select after 60s\n\n const { session, contextResult } = await core.createSessionWithContext({\n channelId: \"telegram\",\n agentName,\n workingDirectory: repoPath,\n contextQuery: fullQuery,\n contextOptions: { maxTokens: DEFAULT_MAX_TOKENS },\n });\n\n session.threadId = String(threadId);\n await core.sessionManager.patchRecord(session.id, { platform: { topicId: threadId } });\n\n // Build summary info\n const sessionCount = contextResult?.sessionCount ?? listResult.sessions.length;\n const mode = contextResult?.mode ?? \"full\";\n const tokens = contextResult?.tokenEstimate ?? listResult.estimatedTokens;\n\n const topicLink = buildDeepLink(chatId, threadId);\n const replyTarget = ctx.message?.message_thread_id;\n\n if (replyTarget !== threadId) {\n await ctx.reply(\n `✅ Session resumed → <a href=\"${topicLink}\">Open topic</a>`,\n { parse_mode: \"HTML\" },\n );\n }\n\n await ctx.api.sendMessage(\n chatId,\n `✅ <b>Session resumed with context</b>\\n` +\n `<b>Agent:</b> ${escapeHtml(session.agentName)}\\n` +\n `<b>Workspace:</b> <code>${escapeHtml(session.workingDirectory)}</code>\\n` +\n `<b>Sessions loaded:</b> ${sessionCount}\\n` +\n `<b>Mode:</b> ${escapeHtml(mode)}\\n` +\n `<b>~Tokens:</b> ${tokens.toLocaleString()}\\n\\n` +\n `Context is ready — chat here to continue working with the agent.`,\n {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n reply_markup: buildSessionControlKeyboard(session.id, false, false),\n },\n );\n\n session.warmup().catch((err) => log.error({ err }, \"Warm-up error\"));\n } catch (err) {\n log.error({ err }, \"Resume session creation failed\");\n if (threadId) {\n try {\n await ctx.api.deleteForumTopic(chatId, threadId);\n } catch { /* ignore cleanup failures */ }\n }\n const message = err instanceof Error ? err.message : (typeof err === \"object\" ? JSON.stringify(err) : String(err));\n await ctx.reply(`❌ ${escapeHtml(message)}`, { parse_mode: \"HTML\" });\n }\n}\n\n// --- Main handler ---\n\nexport async function handleResume(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n assistant?: CommandsAssistantContext,\n): Promise<void> {\n const rawMatch = (ctx as Context & { match: unknown }).match;\n const matchStr = typeof rawMatch === \"string\" ? rawMatch : \"\";\n\n const parsed = parseResumeArgs(matchStr);\n if (!parsed) {\n await ctx.reply(\n `❌ <b>Invalid arguments.</b>\\n\\n` +\n `Usage examples:\\n` +\n `• <code>/resume</code> — latest 5 sessions\\n` +\n `• <code>/resume pr 19</code>\\n` +\n `• <code>/resume branch main</code>\\n` +\n `• <code>/resume commit e0dd2fa4</code>\\n` +\n `• <code>/resume f634acf05138</code> — checkpoint ID\\n` +\n `• <code>/resume https://entire.io/gh/.../checkpoints/.../2e884e2c402a</code>\\n` +\n `• <code>/resume https://entire.io/gh/.../commit/e0dd2fa4...</code>`,\n { parse_mode: \"HTML\" },\n );\n return;\n }\n\n const { query } = parsed;\n const userId = ctx.from?.id;\n if (!userId) return;\n\n // Always show workspace picker — user must choose working directory\n await showWorkspacePicker(ctx, core, chatId, userId, query);\n}\n\n// --- Text input handler for custom workspace path ---\n\nexport async function handlePendingResumeInput(\n ctx: Context,\n core: OpenACPCore,\n chatId: number,\n assistantTopicId?: number,\n): Promise<boolean> {\n const userId = ctx.from?.id;\n if (!userId) return false;\n const pending = pendingResumes.get(userId);\n if (!pending || !ctx.message?.text) return false;\n if (pending.step !== \"workspace_input\" && pending.step !== \"workspace\") return false;\n\n // Only intercept in assistant topic or general chat\n const threadId = ctx.message.message_thread_id;\n if (threadId && threadId !== assistantTopicId) return false;\n\n // At \"workspace\" step (picker shown), only intercept if text looks like a path\n if (pending.step === \"workspace\" && !looksLikePath(ctx.message.text.trim())) return false;\n\n let workspace = ctx.message.text.trim();\n if (!workspace) {\n await ctx.reply(\"⚠️ Please enter a valid directory path.\", { parse_mode: \"HTML\" });\n return true;\n }\n\n // Resolve relative paths against baseDir\n if (!workspace.startsWith(\"/\") && !workspace.startsWith(\"~\")) {\n const baseDir = core.configManager.get().workspace.baseDir;\n workspace = `${baseDir.replace(/\\/$/, \"\")}/${workspace}`;\n }\n const resolved = core.configManager.resolveWorkspace(workspace);\n\n cleanupPending(userId);\n await executeResume(ctx, core, chatId, pending.query, resolved);\n return true;\n}\n\n// --- Callback handlers for workspace picker buttons ---\n\nexport function setupResumeCallbacks(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n): void {\n bot.callbackQuery(/^m:resume:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n const userId = ctx.from?.id;\n if (!userId) return;\n\n try {\n await ctx.answerCallbackQuery();\n } catch { /* expired or network — ignore */ }\n\n const pending = pendingResumes.get(userId);\n if (!pending) return;\n\n if (data === \"m:resume:ws:default\") {\n // Use baseDir directly\n const baseDir = core.configManager.get().workspace.baseDir;\n const resolved = core.configManager.resolveWorkspace(baseDir);\n cleanupPending(userId);\n try {\n await ctx.api.editMessageText(chatId, pending.messageId, `⏳ Using <code>${escapeHtml(resolved)}</code>...`, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n await executeResume(ctx, core, chatId, pending.query, resolved);\n return;\n }\n\n if (data === \"m:resume:ws:custom\") {\n // Switch to text input mode\n try {\n await ctx.api.editMessageText(\n chatId,\n pending.messageId,\n `✏️ <b>Enter project path:</b>\\n\\n` +\n `Full path like <code>~/code/my-project</code>\\n` +\n `Or just the folder name (will use workspace baseDir)`,\n { parse_mode: \"HTML\" },\n );\n } catch {\n await ctx.reply(`✏️ <b>Enter project path:</b>`, { parse_mode: \"HTML\" });\n }\n clearTimeout(pending.timer);\n pending.step = \"workspace_input\";\n pending.timer = setTimeout(() => pendingResumes.delete(userId), PENDING_TIMEOUT_MS);\n return;\n }\n\n if (data.startsWith(\"m:resume:ws:\")) {\n // Subdirectory selected\n const dirName = data.replace(\"m:resume:ws:\", \"\");\n const baseDir = core.configManager.get().workspace.baseDir;\n const resolved = core.configManager.resolveWorkspace(path.join(baseDir.replace(/^~/, os.homedir()), dirName));\n cleanupPending(userId);\n try {\n await ctx.api.editMessageText(chatId, pending.messageId, `⏳ Using <code>${escapeHtml(resolved)}</code>...`, { parse_mode: \"HTML\" });\n } catch { /* ignore */ }\n await executeResume(ctx, core, chatId, pending.query, resolved);\n return;\n }\n });\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport { getSafeFields, resolveOptions, getConfigValue, isHotReloadable, type ConfigFieldDef } from \"../../../core/config/config-registry.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"telegram-settings\" });\n\nfunction buildSettingsKeyboard(core: OpenACPCore): InlineKeyboard {\n const config = core.configManager.get();\n const fields = getSafeFields();\n const kb = new InlineKeyboard();\n\n for (const field of fields) {\n const value = getConfigValue(config, field.path);\n const label = formatFieldLabel(field, value);\n\n if (field.type === 'toggle') {\n kb.text(`${label}`, `s:toggle:${field.path}`).row();\n } else if (field.type === 'select') {\n kb.text(`${label}`, `s:select:${field.path}`).row();\n } else {\n kb.text(`${label}`, `s:input:${field.path}`).row();\n }\n }\n\n kb.text(\"◀️ Back to Menu\", \"s:back\");\n return kb;\n}\n\nfunction formatFieldLabel(field: ConfigFieldDef, value: unknown): string {\n const icons: Record<string, string> = {\n agent: '🤖', logging: '📝', tunnel: '🔗',\n security: '🔒', workspace: '📁', storage: '💾', speech: '🎤',\n };\n const icon = icons[field.group] ?? '⚙️';\n\n if (field.type === 'toggle') {\n return `${icon} ${field.displayName}: ${value ? 'ON' : 'OFF'}`;\n }\n const displayValue = value === null || value === undefined ? 'Not set' : String(value);\n return `${icon} ${field.displayName}: ${displayValue}`;\n}\n\nexport async function handleSettings(ctx: Context, core: OpenACPCore): Promise<void> {\n const kb = buildSettingsKeyboard(core);\n await ctx.reply(`<b>⚙️ Settings</b>\\nTap to change:`, {\n parse_mode: \"HTML\",\n reply_markup: kb,\n });\n}\n\nexport function setupSettingsCallbacks(\n bot: Bot,\n core: OpenACPCore,\n getAssistantSession: () => { topicId: number; enqueuePrompt: (p: string) => Promise<void> } | undefined,\n): void {\n bot.callbackQuery(/^s:toggle:/, async (ctx) => {\n const fieldPath = ctx.callbackQuery.data.replace('s:toggle:', '');\n const config = core.configManager.get();\n const currentValue = getConfigValue(config, fieldPath);\n const newValue = !currentValue;\n\n try {\n const updates = buildNestedUpdate(fieldPath, newValue);\n await core.configManager.save(updates, fieldPath);\n\n const toast = isHotReloadable(fieldPath)\n ? `✅ ${fieldPath} = ${newValue}`\n : `✅ ${fieldPath} = ${newValue} (restart needed)`;\n try { await ctx.answerCallbackQuery({ text: toast }); } catch { /* expired */ }\n\n try {\n await ctx.editMessageReplyMarkup({ reply_markup: buildSettingsKeyboard(core) });\n } catch { /* ignore */ }\n } catch (err) {\n log.error({ err, fieldPath }, 'Failed to toggle config');\n try { await ctx.answerCallbackQuery({ text: '❌ Failed to update' }); } catch { /* expired */ }\n }\n });\n\n bot.callbackQuery(/^s:select:/, async (ctx) => {\n const fieldPath = ctx.callbackQuery.data.replace('s:select:', '');\n const config = core.configManager.get();\n const fieldDef = getSafeFields().find(f => f.path === fieldPath);\n if (!fieldDef) return;\n\n const options = resolveOptions(fieldDef, config) ?? [];\n const currentValue = getConfigValue(config, fieldPath);\n const kb = new InlineKeyboard();\n\n for (const opt of options) {\n const marker = opt === String(currentValue) ? ' ✓' : '';\n kb.text(`${opt}${marker}`, `s:pick:${fieldPath}:${opt}`).row();\n }\n kb.text(\"◀️ Back\", \"s:back:refresh\");\n\n try { await ctx.answerCallbackQuery(); } catch { /* expired */ }\n\n try {\n await ctx.editMessageText(`<b>⚙️ ${fieldDef.displayName}</b>\\nSelect a value:`, {\n parse_mode: \"HTML\",\n reply_markup: kb,\n });\n } catch { /* ignore */ }\n });\n\n bot.callbackQuery(/^s:pick:/, async (ctx) => {\n const parts = ctx.callbackQuery.data.replace('s:pick:', '').split(':');\n const fieldPath = parts.slice(0, -1).join(':');\n const newValue = parts[parts.length - 1];\n\n try {\n // For speech.stt.provider: check if the selected provider has an API key configured\n if (fieldPath === 'speech.stt.provider') {\n const config = core.configManager.get();\n const providerConfig = config.speech?.stt?.providers?.[newValue];\n if (!providerConfig?.apiKey) {\n // No API key — delegate to assistant to collect it\n const assistant = getAssistantSession();\n if (assistant) {\n try { await ctx.answerCallbackQuery({ text: `🔑 API key needed — check Assistant topic` }); } catch { /* expired */ }\n const prompt = `User wants to enable ${newValue} as Speech-to-Text provider, but no API key is configured yet. Guide them to get a ${newValue} API key and set it up. After they provide the key, run both commands: \\`openacp config set speech.stt.providers.${newValue}.apiKey <key>\\` and \\`openacp config set speech.stt.provider ${newValue}\\``;\n await assistant.enqueuePrompt(prompt);\n return;\n }\n // No assistant — just warn\n try { await ctx.answerCallbackQuery({ text: `⚠️ Set API key first: openacp config set speech.stt.providers.${newValue}.apiKey <key>` }); } catch { /* expired */ }\n return;\n }\n }\n\n const updates = buildNestedUpdate(fieldPath, newValue);\n await core.configManager.save(updates, fieldPath);\n\n try { await ctx.answerCallbackQuery({ text: `✅ ${fieldPath} = ${newValue}` }); } catch { /* expired */ }\n try {\n await ctx.editMessageText(`<b>⚙️ Settings</b>\\nTap to change:`, {\n parse_mode: \"HTML\",\n reply_markup: buildSettingsKeyboard(core),\n });\n } catch { /* ignore */ }\n } catch (err) {\n log.error({ err, fieldPath }, 'Failed to set config');\n try { await ctx.answerCallbackQuery({ text: '❌ Failed to update' }); } catch { /* expired */ }\n }\n });\n\n bot.callbackQuery(/^s:input:/, async (ctx) => {\n const fieldPath = ctx.callbackQuery.data.replace('s:input:', '');\n const config = core.configManager.get();\n const fieldDef = getSafeFields().find(f => f.path === fieldPath);\n if (!fieldDef) return;\n\n const currentValue = getConfigValue(config, fieldPath);\n const assistant = getAssistantSession();\n\n if (!assistant) {\n try { await ctx.answerCallbackQuery({ text: '⚠️ Start the assistant first (/assistant)' }); } catch { /* expired */ }\n return;\n }\n\n try { await ctx.answerCallbackQuery({ text: `Delegating to assistant...` }); } catch { /* expired */ }\n\n const prompt = `User wants to change ${fieldDef.displayName} (config path: ${fieldPath}). Current value: ${JSON.stringify(currentValue)}. Ask them for the new value and apply it using: openacp config set ${fieldPath} <value>`;\n await assistant.enqueuePrompt(prompt);\n });\n\n bot.callbackQuery(\"s:back\", async (ctx) => {\n try { await ctx.answerCallbackQuery(); } catch { /* expired */ }\n const { buildMenuKeyboard } = await import('./menu.js');\n try {\n await ctx.editMessageText(`<b>OpenACP Menu</b>\\nChoose an action:`, {\n parse_mode: \"HTML\",\n reply_markup: buildMenuKeyboard(),\n });\n } catch { /* ignore */ }\n });\n\n bot.callbackQuery(\"s:back:refresh\", async (ctx) => {\n try { await ctx.answerCallbackQuery(); } catch { /* expired */ }\n try {\n await ctx.editMessageText(`<b>⚙️ Settings</b>\\nTap to change:`, {\n parse_mode: \"HTML\",\n reply_markup: buildSettingsKeyboard(core),\n });\n } catch { /* ignore */ }\n });\n}\n\nfunction buildNestedUpdate(dotPath: string, value: unknown): Record<string, unknown> {\n const parts = dotPath.split('.');\n const result: Record<string, unknown> = {};\n let target = result;\n for (let i = 0; i < parts.length - 1; i++) {\n target[parts[i]] = {};\n target = target[parts[i]] as Record<string, unknown>;\n }\n target[parts[parts.length - 1]] = value;\n return result;\n}\n","import type { Bot, Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport { DoctorEngine } from \"../../../core/doctor/index.js\";\nimport type { DoctorReport, PendingFix } from \"../../../core/doctor/types.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"telegram-cmd-doctor\" });\n\nconst pendingFixesStore = new Map<string, PendingFix[]>();\n\nfunction renderReport(report: DoctorReport): { text: string; keyboard: InlineKeyboard | undefined } {\n const icons = { pass: \"✅\", warn: \"⚠️\", fail: \"❌\" };\n const lines: string[] = [\"🩺 <b>OpenACP Doctor</b>\\n\"];\n\n for (const category of report.categories) {\n lines.push(`<b>${category.name}</b>`);\n for (const result of category.results) {\n lines.push(` ${icons[result.status]} ${escapeHtml(result.message)}`);\n }\n lines.push(\"\");\n }\n\n const { passed, warnings, failed, fixed } = report.summary;\n const fixedStr = fixed > 0 ? `, ${fixed} fixed` : \"\";\n lines.push(`<b>Result:</b> ${passed} passed, ${warnings} warnings, ${failed} failed${fixedStr}`);\n\n let keyboard: InlineKeyboard | undefined;\n if (report.pendingFixes.length > 0) {\n keyboard = new InlineKeyboard();\n for (let i = 0; i < report.pendingFixes.length; i++) {\n const label = `🔧 Fix: ${report.pendingFixes[i].message.slice(0, 30)}`;\n keyboard.text(label, `m:doctor:fix:${i}`).row();\n }\n }\n\n return { text: lines.join(\"\\n\"), keyboard };\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\n}\n\nexport async function handleDoctor(ctx: Context): Promise<void> {\n const statusMsg = await ctx.reply(\"🩺 Running diagnostics...\", { parse_mode: \"HTML\" });\n\n try {\n const engine = new DoctorEngine();\n const report = await engine.runAll();\n const { text, keyboard } = renderReport(report);\n\n const storeKey = `${ctx.chat!.id}:${statusMsg.message_id}`;\n if (report.pendingFixes.length > 0) {\n pendingFixesStore.set(storeKey, report.pendingFixes);\n }\n\n await ctx.api.editMessageText(ctx.chat!.id, statusMsg.message_id, text, {\n parse_mode: \"HTML\",\n reply_markup: keyboard,\n });\n } catch (err) {\n log.error({ err }, \"Doctor command failed\");\n await ctx.api.editMessageText(\n ctx.chat!.id,\n statusMsg.message_id,\n `❌ Doctor failed: ${err instanceof Error ? err.message : String(err)}`,\n { parse_mode: \"HTML\" },\n );\n }\n}\n\nexport function setupDoctorCallbacks(bot: Bot): void {\n bot.callbackQuery(/^m:doctor:fix:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n const index = parseInt(data.replace(\"m:doctor:fix:\", \"\"), 10);\n const chatId = ctx.callbackQuery.message?.chat.id;\n const messageId = ctx.callbackQuery.message?.message_id;\n\n try {\n await ctx.answerCallbackQuery({ text: \"Applying fix...\" });\n } catch { /* expired */ }\n\n if (chatId === undefined || messageId === undefined) return;\n\n const storeKey = `${chatId}:${messageId}`;\n const fixes = pendingFixesStore.get(storeKey);\n if (!fixes || index < 0 || index >= fixes.length) {\n try { await ctx.answerCallbackQuery({ text: \"Fix no longer available\" }); } catch { /* */ }\n return;\n }\n\n const pending = fixes[index];\n try {\n const result = await pending.fix();\n if (result.success) {\n const engine = new DoctorEngine();\n const report = await engine.runAll();\n const { text, keyboard } = renderReport(report);\n\n if (report.pendingFixes.length > 0) {\n pendingFixesStore.set(storeKey, report.pendingFixes);\n } else {\n pendingFixesStore.delete(storeKey);\n }\n\n await ctx.editMessageText(text, { parse_mode: \"HTML\", reply_markup: keyboard });\n } else {\n try { await ctx.answerCallbackQuery({ text: `Fix failed: ${result.message}` }); } catch { /* */ }\n }\n } catch (err) {\n log.error({ err, index }, \"Doctor fix callback failed\");\n }\n });\n\n bot.callbackQuery(\"m:doctor\", async (ctx) => {\n try { await ctx.answerCallbackQuery(); } catch { /* */ }\n await handleDoctor(ctx);\n });\n}\n","import type { Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"telegram-cmd-tunnel\" });\n\nexport async function handleTunnel(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n if (!core.tunnelService) {\n await ctx.reply(\"❌ Tunnel service is not enabled.\", { parse_mode: \"HTML\" });\n return;\n }\n\n const match = (ctx as Context & { match?: string }).match?.trim() ?? \"\";\n\n // /tunnel stop <port>\n if (match.startsWith(\"stop \")) {\n const portStr = match.slice(5).trim();\n const port = parseInt(portStr, 10);\n if (isNaN(port)) {\n await ctx.reply(\"❌ Invalid port number.\", { parse_mode: \"HTML\" });\n return;\n }\n\n try {\n await core.tunnelService.stopTunnel(port);\n await ctx.reply(`🔌 Tunnel stopped: port ${port}`, { parse_mode: \"HTML\" });\n } catch (err) {\n await ctx.reply(`❌ ${escapeHtml((err as Error).message)}`, { parse_mode: \"HTML\" });\n }\n return;\n }\n\n // /tunnel <port> [label]\n if (match) {\n const parts = match.split(/\\s+/);\n const port = parseInt(parts[0], 10);\n if (isNaN(port)) {\n await ctx.reply(\"❌ Invalid port number. Usage: <code>/tunnel 3000 [label]</code>\", { parse_mode: \"HTML\" });\n return;\n }\n const label = parts.slice(1).join(\" \") || undefined;\n\n // Find session for this thread\n const threadId = ctx.message?.message_thread_id;\n let sessionId: string | undefined;\n if (threadId) {\n const session = core.sessionManager.getSessionByThread(\"telegram\", String(threadId));\n if (session) sessionId = session.id;\n }\n\n try {\n await ctx.reply(`⏳ Starting tunnel for port ${port}...`, { parse_mode: \"HTML\" });\n const entry = await core.tunnelService.addTunnel(port, { label, sessionId });\n await ctx.reply(\n `🔗 <b>Tunnel active</b>\\n\\nPort ${port}${label ? ` (${escapeHtml(label)})` : \"\"}\\n→ <a href=\"${escapeHtml(entry.publicUrl || \"\")}\">${escapeHtml(entry.publicUrl || \"\")}</a>`,\n { parse_mode: \"HTML\" },\n );\n } catch (err) {\n await ctx.reply(`❌ ${escapeHtml((err as Error).message)}`, { parse_mode: \"HTML\" });\n }\n return;\n }\n\n // No args — show help\n await ctx.reply(\n `<b>Tunnel commands:</b>\\n\\n` +\n `<code>/tunnel <port> [label]</code> — Create tunnel\\n` +\n `<code>/tunnel stop <port></code> — Stop tunnel\\n` +\n `<code>/tunnels</code> — List active tunnels`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function handleTunnels(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n if (!core.tunnelService) {\n await ctx.reply(\"❌ Tunnel service is not enabled.\", { parse_mode: \"HTML\" });\n return;\n }\n\n // In session topic: show only that session's tunnels. In assistant/other: show all.\n const threadId = ctx.message?.message_thread_id;\n let entries = core.tunnelService.listTunnels();\n let sessionScoped = false;\n\n if (threadId) {\n const session = core.sessionManager.getSessionByThread(\"telegram\", String(threadId));\n if (session) {\n entries = entries.filter(e => e.sessionId === session.id);\n sessionScoped = true;\n }\n }\n\n if (entries.length === 0) {\n const hint = sessionScoped\n ? \"No tunnels for this session.\\n\\nUse <code>/tunnel <port></code> to create one.\"\n : \"No active tunnels.\\n\\nUse <code>/tunnel <port></code> to create one.\";\n await ctx.reply(hint, { parse_mode: \"HTML\" });\n return;\n }\n\n const lines = entries.map((e) => {\n const status = e.status === \"active\" ? \"✅\" : e.status === \"starting\" ? \"⏳\" : \"❌\";\n const label = e.label ? ` (${escapeHtml(e.label)})` : \"\";\n const url = e.publicUrl ? `\\n → <a href=\"${escapeHtml(e.publicUrl)}\">${escapeHtml(e.publicUrl)}</a>` : \"\";\n return `${status} Port <b>${e.port}</b>${label}${url}`;\n });\n\n const keyboard = new InlineKeyboard();\n for (const e of entries) {\n keyboard.text(`🔌 Stop ${e.port}${e.label ? ` (${e.label})` : \"\"}`, `tn:stop:${e.port}`).row();\n }\n if (entries.length > 1) {\n keyboard.text(\"🔌 Stop all\", \"tn:stop-all\").row();\n }\n\n await ctx.reply(\n `<b>Active tunnels:</b>\\n\\n${lines.join(\"\\n\\n\")}`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n}\n\nexport function setupTunnelCallbacks(\n bot: import(\"grammy\").Bot,\n core: OpenACPCore,\n): void {\n bot.callbackQuery(/^tn:/, async (ctx) => {\n const data = ctx.callbackQuery.data;\n if (!core.tunnelService) {\n await ctx.answerCallbackQuery({ text: \"Tunnel not enabled\" });\n return;\n }\n\n try {\n if (data === \"tn:stop-all\") {\n const entries = core.tunnelService.listTunnels();\n for (const e of entries) {\n try { await core.tunnelService.stopTunnel(e.port); } catch { /* ignore system */ }\n }\n await ctx.answerCallbackQuery({ text: \"All tunnels stopped\" });\n await ctx.editMessageText(\"🔌 All tunnels stopped.\", { parse_mode: \"HTML\" });\n } else if (data.startsWith(\"tn:stop:\")) {\n const port = parseInt(data.replace(\"tn:stop:\", \"\"), 10);\n await core.tunnelService.stopTunnel(port);\n await ctx.answerCallbackQuery({ text: `Port ${port} stopped` });\n // Refresh list with keyboard\n const remaining = core.tunnelService.listTunnels();\n if (remaining.length === 0) {\n await ctx.editMessageText(\"🔌 All tunnels stopped.\", { parse_mode: \"HTML\" });\n } else {\n const kb = new InlineKeyboard();\n for (const e of remaining) {\n kb.text(`🔌 Stop ${e.port}${e.label ? ` (${e.label})` : \"\"}`, `tn:stop:${e.port}`).row();\n }\n if (remaining.length > 1) {\n kb.text(\"🔌 Stop all\", \"tn:stop-all\").row();\n }\n await ctx.editMessageText(\n `<b>Active tunnels:</b>\\n\\n` +\n remaining.map(e => {\n const status = e.status === \"active\" ? \"✅\" : \"⏳\";\n const label = e.label ? ` (${escapeHtml(e.label)})` : \"\";\n const url = e.publicUrl ? `\\n → <a href=\"${escapeHtml(e.publicUrl)}\">${escapeHtml(e.publicUrl)}</a>` : \"\";\n return `${status} Port <b>${e.port}</b>${label}${url}`;\n }).join(\"\\n\\n\"),\n { parse_mode: \"HTML\", reply_markup: kb },\n );\n }\n }\n } catch (err) {\n await ctx.answerCallbackQuery({ text: (err as Error).message });\n }\n });\n}\n","import type { Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { OpenACPCore } from \"../../../core/index.js\";\nimport { escapeHtml } from \"../formatting.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"telegram-cmd-switch\" });\n\nexport async function handleSwitch(\n ctx: Context,\n core: OpenACPCore,\n): Promise<void> {\n const threadId = ctx.message?.message_thread_id;\n if (!threadId) return;\n\n const session = await core.getOrResumeSession(\"telegram\", String(threadId));\n if (!session) {\n await ctx.reply(\"No active session in this topic.\");\n return;\n }\n\n const rawMatch = (ctx as Context & { match: unknown }).match;\n const raw = (typeof rawMatch === \"string\" ? rawMatch : \"\").trim();\n\n // /switch label on|off\n if (raw.startsWith(\"label \")) {\n const value = raw.slice(6).trim().toLowerCase();\n if (value === \"on\" || value === \"off\") {\n await core.configManager.save(\n { agentSwitch: { labelHistory: value === \"on\" } },\n \"agentSwitch.labelHistory\",\n );\n await ctx.reply(`Agent label in history: ${value}`);\n } else {\n await ctx.reply(\"Usage: /switch label on|off\");\n }\n return;\n }\n\n // /switch (no args) → show menu\n if (!raw) {\n const agents = core.agentManager.getAvailableAgents();\n const currentAgent = session.agentName;\n const options = agents.filter((a) => a.name !== currentAgent);\n\n if (options.length === 0) {\n await ctx.reply(\"No other agents available.\");\n return;\n }\n\n const keyboard = new InlineKeyboard();\n for (const agent of options) {\n keyboard.text(agent.name, `sw:${agent.name}`).row();\n }\n\n await ctx.reply(\n `<b>Switch Agent</b>\\nCurrent: <code>${escapeHtml(currentAgent)}</code>\\n\\nSelect an agent:`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n return;\n }\n\n // /switch <agentName> → direct switch\n // Check if a prompt is currently being processed\n if (session.promptRunning) {\n const keyboard = new InlineKeyboard();\n keyboard.text(\"Yes, switch now\", `swc:${raw}`).text(\"Cancel\", \"swc:cancel\");\n await ctx.reply(\n `A prompt is currently running. Switching will interrupt it.\\n\\nSwitch to <b>${escapeHtml(raw)}</b> anyway?`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n return;\n }\n\n await executeSwitchAgent(ctx, core, session.id, raw);\n}\n\nexport async function executeSwitchAgent(\n ctx: Context,\n core: OpenACPCore,\n sessionId: string,\n agentName: string,\n): Promise<void> {\n try {\n const { resumed } = await core.switchSessionAgent(sessionId, agentName);\n const status = resumed ? \"resumed\" : \"new session\";\n await ctx.reply(\n `Switched to <b>${escapeHtml(agentName)}</b> (${status})`,\n { parse_mode: \"HTML\" },\n );\n log.info({ sessionId, agentName, resumed }, \"Agent switched via /switch\");\n } catch (err: any) {\n await ctx.reply(`Failed to switch agent: ${escapeHtml(String(err.message || err))}`);\n log.warn({ sessionId, agentName, err: err.message }, \"Agent switch failed\");\n }\n}\n\nexport function setupSwitchCallbacks(\n bot: import(\"grammy\").Bot,\n core: OpenACPCore,\n): void {\n bot.callbackQuery(/^sw:/, async (ctx) => {\n const agentName = ctx.callbackQuery.data!.replace(\"sw:\", \"\");\n await ctx.answerCallbackQuery();\n\n const threadId = ctx.callbackQuery.message?.message_thread_id;\n if (!threadId) return;\n\n const session = await core.getOrResumeSession(\"telegram\", String(threadId));\n if (!session) {\n await ctx.reply(\"No active session in this topic.\");\n return;\n }\n\n // Check if a prompt is currently being processed\n if (session.promptRunning) {\n const keyboard = new InlineKeyboard();\n keyboard.text(\"Yes, switch now\", `swc:${agentName}`).text(\"Cancel\", \"swc:cancel\");\n await ctx.reply(\n `A prompt is currently running. Switching will interrupt it.\\n\\nSwitch to <b>${escapeHtml(agentName)}</b> anyway?`,\n { parse_mode: \"HTML\", reply_markup: keyboard },\n );\n return;\n }\n\n await executeSwitchAgent(ctx, core, session.id, agentName);\n });\n\n // Handle switch confirmation callbacks (when prompt was in-flight)\n bot.callbackQuery(/^swc:/, async (ctx) => {\n const data = ctx.callbackQuery.data!.replace(\"swc:\", \"\");\n await ctx.answerCallbackQuery();\n\n if (data === \"cancel\") {\n await ctx.editMessageText(\"Switch cancelled.\");\n return;\n }\n\n const threadId = ctx.callbackQuery.message?.message_thread_id;\n if (!threadId) return;\n\n const session = await core.getOrResumeSession(\"telegram\", String(threadId));\n if (!session) {\n await ctx.reply(\"No active session in this topic.\");\n return;\n }\n\n // Cancel in-flight prompt before switching\n await session.abortPrompt();\n await executeSwitchAgent(ctx, core, session.id, data);\n });\n}\n","import type { Bot } from 'grammy'\nimport { InlineKeyboard } from 'grammy'\nimport { nanoid } from 'nanoid'\nimport type { PermissionRequest, NotificationMessage, Session } from '../../core/index.js'\nimport { escapeHtml } from './formatting.js'\nimport { buildDeepLink } from './topics.js'\nimport { createChildLogger } from '../../core/utils/log.js'\nconst log = createChildLogger({ module: 'telegram-permissions' })\n\n// Stored pending permission callbacks: callbackKey → { sessionId, requestId, options }\ninterface PendingPermission {\n sessionId: string\n requestId: string\n options: { id: string; isAllow: boolean }[]\n}\n\nexport class PermissionHandler {\n private pending: Map<string, PendingPermission> = new Map()\n\n constructor(\n private bot: Bot,\n private chatId: number,\n private getSession: (sessionId: string) => Session | undefined,\n private sendNotification: (notification: NotificationMessage) => Promise<void>,\n ) {}\n\n async sendPermissionRequest(session: Session, request: PermissionRequest): Promise<void> {\n const threadId = Number(session.threadId)\n\n // Short callback key (Telegram 64-byte limit on callback_data)\n const callbackKey = nanoid(8)\n this.pending.set(callbackKey, {\n sessionId: session.id,\n requestId: request.id,\n options: request.options.map(o => ({ id: o.id, isAllow: o.isAllow })),\n })\n\n // Build inline keyboard\n const keyboard = new InlineKeyboard()\n for (const option of request.options) {\n const emoji = option.isAllow ? '✅' : '❌'\n keyboard.text(`${emoji} ${option.label}`, `p:${callbackKey}:${option.id}`)\n }\n\n // Send in session topic WITH notification\n const msg = await this.bot.api.sendMessage(this.chatId,\n `🔐 <b>Permission request:</b>\\n\\n${escapeHtml(request.description)}`,\n {\n message_thread_id: threadId,\n parse_mode: 'HTML',\n reply_markup: keyboard,\n disable_notification: false,\n }\n )\n\n // Deep link for notification — include threadId so link navigates into the topic\n const deepLink = buildDeepLink(this.chatId, threadId, msg.message_id)\n\n // Notify in notification topic (fire-and-forget to avoid sendQueue deadlock:\n // this method runs INSIDE a sendQueue item, so awaiting another enqueue() deadlocks)\n void this.sendNotification({\n sessionId: session.id,\n sessionName: session.name,\n type: 'permission',\n summary: request.description,\n deepLink,\n })\n }\n\n setupCallbackHandler(): void {\n this.bot.on('callback_query:data', async (ctx) => {\n const data = ctx.callbackQuery.data\n if (!data.startsWith('p:')) return\n\n const parts = data.split(':')\n if (parts.length < 3) return\n const [, callbackKey, optionId] = parts\n\n const pending = this.pending.get(callbackKey)\n if (!pending) {\n try { await ctx.answerCallbackQuery({ text: '❌ Expired' }) } catch { /* old query */ }\n return\n }\n\n const session = this.getSession(pending.sessionId)\n const isAllow = pending.options.find(o => o.id === optionId)?.isAllow ?? false\n log.info({ requestId: pending.requestId, optionId, isAllow }, 'Permission responded')\n if (session?.permissionGate.requestId === pending.requestId) {\n session.permissionGate.resolve(optionId)\n }\n this.pending.delete(callbackKey)\n\n try { await ctx.answerCallbackQuery({ text: '✅ Responded' }) } catch { /* old query */ }\n\n // Remove buttons\n try {\n await ctx.editMessageReplyMarkup({ reply_markup: undefined })\n } catch { /* ignore */ }\n })\n }\n}\n","import type { OpenACPCore, IChannelAdapter, Config, Session } from \"../../core/index.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nimport { PRODUCT_GUIDE } from \"../../data/product-guide.js\";\nconst log = createChildLogger({ module: \"telegram-assistant\" });\n\nexport type SpawnAssistantResult = {\n session: Session;\n /** Resolves when the background system prompt completes (or fails). */\n ready: Promise<void>;\n};\n\nexport async function spawnAssistant(\n core: OpenACPCore,\n adapter: IChannelAdapter,\n assistantTopicId: number,\n): Promise<SpawnAssistantResult> {\n const config = core.configManager.get();\n\n // Create session with default agent via unified pipeline\n log.info({ agent: config.defaultAgent }, \"Creating assistant session...\");\n const session = await core.createSession({\n channelId: \"telegram\",\n agentName: config.defaultAgent,\n workingDirectory: core.configManager.resolveWorkspace(),\n initialName: \"Assistant\", // Prevent auto-naming from triggering after system prompt\n });\n session.threadId = String(assistantTopicId);\n log.info({ sessionId: session.id }, \"Assistant agent spawned\");\n\n // Build dynamic context for system prompt\n const allRecords = core.sessionManager.listRecords();\n const activeCount = allRecords.filter(r => r.status === 'active' || r.status === 'initializing').length;\n const statusCounts = new Map<string, number>();\n for (const r of allRecords) {\n statusCounts.set(r.status, (statusCounts.get(r.status) ?? 0) + 1);\n }\n const topicSummary = Array.from(statusCounts.entries()).map(([status, count]) => ({ status, count }));\n\n // Get agent info from catalog\n const installedAgents = Object.keys(core.agentCatalog.getInstalledEntries());\n const availableItems = core.agentCatalog.getAvailable();\n const availableAgentCount = availableItems.filter(i => !i.installed).length;\n\n const ctx: AssistantContext = {\n config,\n activeSessionCount: activeCount,\n totalSessionCount: allRecords.length,\n topicSummary,\n installedAgents,\n availableAgentCount,\n };\n\n // Fire system prompt in background — don't block startup.\n const systemPrompt = buildAssistantSystemPrompt(ctx);\n const ready = session.enqueuePrompt(systemPrompt)\n .then(() => { log.info({ sessionId: session.id }, \"Assistant system prompt completed\"); })\n .catch((err) => { log.warn({ err }, \"Assistant system prompt failed\"); });\n\n return { session, ready };\n}\n\nexport interface AssistantContext {\n config: Config\n activeSessionCount: number\n totalSessionCount: number\n topicSummary: { status: string; count: number }[]\n installedAgents?: string[]\n availableAgentCount?: number\n}\n\nexport interface WelcomeContext {\n activeCount: number;\n errorCount: number;\n totalCount: number;\n agents: string[];\n defaultAgent: string;\n}\n\nexport function buildWelcomeMessage(ctx: WelcomeContext): string {\n const { activeCount, errorCount, totalCount, agents, defaultAgent } = ctx;\n\n const agentList = agents\n .map((a) => `${a}${a === defaultAgent ? \" (default)\" : \"\"}`)\n .join(\", \");\n\n // Variant 1: No sessions\n if (totalCount === 0) {\n return `👋 <b>OpenACP is ready!</b>\\n\\nNo sessions yet. Tap 🆕 New Session to start, or ask me anything!`;\n }\n\n // Variant 2: Has errors\n if (errorCount > 0) {\n return (\n `👋 <b>OpenACP is ready!</b>\\n\\n` +\n `📊 ${activeCount} active, ${errorCount} errors / ${totalCount} total\\n` +\n `⚠️ ${errorCount} session${errorCount > 1 ? \"s have\" : \" has\"} errors — ask me to check if you'd like.\\n\\n` +\n `Agents: ${agentList}`\n );\n }\n\n // Variant 3/4: Has active or fallback\n return (\n `👋 <b>OpenACP is ready!</b>\\n\\n` +\n `📊 ${activeCount} active / ${totalCount} total\\n` +\n `Agents: ${agentList}`\n );\n}\n\nexport function buildAssistantSystemPrompt(ctx: AssistantContext): string {\n const { config, activeSessionCount, totalSessionCount, topicSummary, installedAgents, availableAgentCount } = ctx;\n const agentNames = installedAgents?.length ? installedAgents.join(\", \") : Object.keys(config.agents).join(\", \");\n const topicBreakdown =\n topicSummary.map((s) => `${s.status}: ${s.count}`).join(\", \") || \"none\";\n\n return `You are the OpenACP Assistant — a helpful guide for managing AI coding sessions.\n\n## Current State\n- Active sessions: ${activeSessionCount} / ${totalSessionCount} total\n- Topics by status: ${topicBreakdown}\n- Installed agents: ${agentNames}\n- Available in ACP Registry: ${availableAgentCount ?? \"28+\"} more agents (use /agents to browse)\n- Default agent: ${config.defaultAgent}\n- Workspace base directory: ${config.workspace.baseDir}\n- STT: ${config.speech?.stt?.provider ? `${config.speech.stt.provider} ✅` : \"Not configured\"}\n\n## Action Playbook\n\n### Create Session\n- The workspace is the project directory where the agent will work (read, write, execute code). It is NOT the base directory — it should be a specific project folder like \\`~/code/my-project\\` or \\`${config.workspace.baseDir}/my-app\\`.\n- Ask which agent to use (if multiple are installed). Show installed: ${agentNames}\n- Ask which project directory to use as workspace. Suggest \\`${config.workspace.baseDir}\\` as the base, but explain the user can provide any path.\n- Confirm before creating: show agent name + full workspace path.\n- Create via: \\`openacp api new <agent> <workspace> --channel telegram\\`\n\n### Browse & Install Agents\n- Guide users to /agents command to see all available agents (installed + from ACP Registry)\n- The /agents list is paginated with install buttons — users can tap to install directly\n- For CLI users: \\`openacp agents install <name>\\`\n- Some agents need login/setup after install — guide users to \\`openacp agents info <name>\\` for setup steps\n- To run agent CLI for login: \\`openacp agents run <name> -- <args>\\`\n- Common setup examples:\n - Gemini: \\`openacp agents run gemini -- auth login\\`\n - GitHub Copilot: \\`openacp agents run copilot -- auth login\\`\n - Codex: needs OPENAI_API_KEY environment variable\n\n### Check Status / List Sessions\n- Run \\`openacp api status\\` for active sessions overview\n- Run \\`openacp api topics\\` for full list with statuses\n- Format the output nicely for the user\n\n### Cancel Session\n- Run \\`openacp api status\\` to see what's active\n- If 1 active session → ask user to confirm → \\`openacp api cancel <id>\\`\n- If multiple → list them, ask user which one to cancel\n\n### Troubleshoot (Session Stuck, Errors)\n- Run \\`openacp api health\\` + \\`openacp api status\\` to diagnose\n- Small issue (stuck session) → suggest cancel + create new\n- Big issue (system-level) → suggest restart, ask for confirmation first\n\n### Cleanup Old Sessions\n- Run \\`openacp api topics --status finished,error\\` to see what can be cleaned\n- Report the count, ask user to confirm\n- Execute: \\`openacp api cleanup --status <statuses>\\`\n\n### Configuration\n- View: \\`openacp config\\` (or \\`openacp api config\\` — deprecated)\n- Update: \\`openacp config set <key> <value>\\`\n- When user asks about \"settings\" or \"config\", use \\`openacp config set\\` directly\n- When receiving a delegated request from the Settings menu, ask user for the new value, then apply with \\`openacp config set <path> <value>\\`\n\n### Voice / Speech-to-Text\n- OpenACP can transcribe voice messages to text using STT providers (Groq Whisper, OpenAI Whisper)\n- Current STT provider: ${config.speech?.stt?.provider ?? \"Not configured\"}\n- To enable: user needs an API key from the STT provider\n - Groq (recommended, free tier ~8h/day): Get key at console.groq.com → API Keys\n - Set via: \\`openacp config set speech.stt.provider groq\\` then \\`openacp config set speech.stt.providers.groq.apiKey <key>\\`\n- When STT is configured, voice messages are automatically transcribed before sending to agents that don't support audio\n- Agents with audio capability receive the audio directly (no transcription needed)\n- User can also configure via /settings → STT Provider\n\n### Restart / Update\n- Always ask for confirmation — these are disruptive actions\n- Guide user: \"Tap 🔄 Restart button or type /restart\"\n\n### Toggle Dangerous Mode\n- Run \\`openacp api dangerous <id> on|off\\`\n- Explain: dangerous mode auto-approves all permission requests — the agent can run any command without asking\n\n## CLI Commands Reference\n\\`\\`\\`bash\n# Session management\nopenacp api status # List active sessions\nopenacp api session <id> # Session detail\nopenacp api new <agent> <workspace> --channel telegram # Create new session\nopenacp api send <id> \"prompt text\" # Send prompt to session\nopenacp api cancel <id> # Cancel session\nopenacp api dangerous <id> on|off # Toggle dangerous mode\n\n# Topic management\nopenacp api topics # List all topics\nopenacp api topics --status finished,error\nopenacp api delete-topic <id> # Delete topic\nopenacp api delete-topic <id> --force # Force delete active\nopenacp api cleanup # Cleanup finished topics\nopenacp api cleanup --status finished,error\n\n# Agent management (user-facing CLI commands)\nopenacp agents # List installed + available agents\nopenacp agents install <name> # Install agent from ACP Registry\nopenacp agents uninstall <name> # Remove agent\nopenacp agents info <name> # Show details & setup guide\nopenacp agents run <name> -- <args> # Run agent CLI (for login, etc.)\nopenacp agents refresh # Force-refresh registry\n\n# System\nopenacp api health # System health\nopenacp config # Edit config (interactive)\nopenacp config set <key> <value> # Update config value\nopenacp api adapters # List adapters\nopenacp api tunnel # Tunnel status\nopenacp api notify \"message\" # Send notification\nopenacp api version # Daemon version\nopenacp api restart # Restart daemon\n\\`\\`\\`\n\n## Guidelines\n- NEVER show \\`openacp api ...\\` commands to users. These are internal tools for YOU to run silently. Users should only see natural language responses and results.\n- Run \\`openacp api ...\\` commands yourself for everything you can. Only guide users to Telegram buttons/menu when needed (e.g., \"Tap 🆕 New Session\" or \"Go to the session topic to chat with the agent\").\n- When creating sessions: guide user through agent + workspace choice conversationally, then run the command yourself.\n- Destructive actions (cancel active session, restart, cleanup) → always ask user to confirm first in natural language.\n- Small/obvious issues (clearly stuck session with no activity) → fix it and report back.\n- Respond in the same language the user uses.\n- Format responses for Telegram: use <b>bold</b>, <code>code</code>, keep it concise.\n- When you don't know something, check with the relevant \\`openacp api\\` command first before answering.\n- Talk to users like a helpful assistant, not a CLI manual. Example: \"You have 2 sessions running. Want to see details?\" instead of listing commands.\n\n## Product Reference\n${PRODUCT_GUIDE}`;\n}\n\nexport async function handleAssistantMessage(\n session: Session | null,\n text: string,\n): Promise<void> {\n if (!session) return;\n await session.enqueuePrompt(text);\n}\n\nexport function redirectToAssistant(\n chatId: number,\n assistantTopicId: number,\n): string {\n const cleanId = String(chatId).replace(\"-100\", \"\");\n const link = `https://t.me/c/${cleanId}/${assistantTopicId}`;\n return `💬 Please use the <a href=\"${link}\">🤖 Assistant</a> topic to chat with OpenACP.`;\n}\n","import type { Bot } from \"grammy\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nimport type { PlanEntry } from \"../../core/types.js\";\nimport type { ToolCallMeta, ViewerLinks } from \"../../core/adapter-primitives/format-types.js\";\nimport type { SendQueue } from \"../../core/adapter-primitives/primitives/send-queue.js\";\nimport type { DebugTracer } from \"../../core/utils/debug-tracer.js\";\nimport { ToolCardState } from \"../../core/adapter-primitives/primitives/tool-card-state.js\";\nimport type { ToolCardSnapshot } from \"../../core/adapter-primitives/primitives/tool-card-state.js\";\nimport { escapeHtml, renderToolCard, splitToolCardText } from \"./formatting.js\";\nimport { ToolStateMap } from \"../../core/adapter-primitives/stream-accumulator.js\";\nimport { ThoughtBuffer } from \"../../core/adapter-primitives/stream-accumulator.js\";\nimport { DisplaySpecBuilder } from \"../../core/adapter-primitives/display-spec-builder.js\";\nimport type { ToolDisplaySpec } from \"../../core/adapter-primitives/display-spec-builder.js\";\nimport type { OutputMode } from \"../../core/adapter-primitives/format-types.js\";\nimport type { TunnelServiceInterface } from \"../../core/plugin/types.js\";\n\nconst log = createChildLogger({ module: \"telegram:activity\" });\n\n// ─── ThinkingIndicator ────────────────────────────────────────────────────────\n\nconst THINKING_REFRESH_MS = 15_000;\nconst THINKING_MAX_MS = 3 * 60 * 1000;\n\nexport class ThinkingIndicator {\n private msgId?: number;\n private sending = false;\n private dismissed = false;\n private refreshTimer?: ReturnType<typeof setInterval>;\n private showTime = 0;\n private tracer: DebugTracer | null;\n\n constructor(\n private api: Bot[\"api\"],\n private chatId: number,\n private threadId: number,\n private sendQueue: SendQueue,\n private sessionId: string = \"\",\n tracer: DebugTracer | null = null,\n ) {\n this.tracer = tracer;\n }\n\n async show(): Promise<void> {\n if (this.sending || this.dismissed) return;\n if (this.msgId) return;\n this.sending = true;\n this.showTime = Date.now();\n const text = \"💭 <i>Thinking...</i>\";\n try {\n const result = await this.sendQueue.enqueue(() =>\n this.api.sendMessage(this.chatId, text, {\n message_thread_id: this.threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n if (result) {\n this.tracer?.log(\"telegram\", { action: \"thinking:show\", sessionId: this.sessionId, msgId: result.message_id });\n if (this.dismissed) {\n // dismissed during queue wait — message stays in chat (no delete to save API calls)\n } else {\n this.msgId = result.message_id;\n this.startRefreshTimer();\n }\n }\n } catch (err) {\n log.warn({ err }, \"ThinkingIndicator.show() failed\");\n } finally {\n this.sending = false;\n }\n }\n\n /** Edit the indicator message to append a viewer link, then dismiss. */\n async finalizeWithViewerLink(url: string): Promise<void> {\n this.stopRefreshTimer();\n if (this.msgId && !this.dismissed) {\n const text = `💭 <i>Thinking...</i> <a href=\"${escapeHtml(url)}\">View thinking</a>`;\n await this.sendQueue\n .enqueue(() => {\n if (!this.msgId) return Promise.resolve(undefined);\n return this.api.editMessageText(this.chatId, this.msgId, text, { parse_mode: \"HTML\" });\n })\n .catch(() => {});\n }\n this.dismissed = true;\n this.msgId = undefined;\n }\n\n /** Dismiss indicator: stops refresh timer. Message is left in chat to reduce API calls. */\n async dismiss(): Promise<void> {\n if (this.dismissed) return;\n this.dismissed = true;\n this.tracer?.log(\"telegram\", { action: \"thinking:dismiss\", sessionId: this.sessionId });\n this.stopRefreshTimer();\n this.msgId = undefined;\n }\n\n /** Reset for a new prompt cycle */\n reset(): void {\n this.dismissed = false;\n }\n\n private startRefreshTimer(): void {\n this.stopRefreshTimer();\n this.refreshTimer = setInterval(() => {\n if (\n this.dismissed ||\n !this.msgId ||\n Date.now() - this.showTime >= THINKING_MAX_MS\n ) {\n this.stopRefreshTimer();\n return;\n }\n const elapsed = Math.round((Date.now() - this.showTime) / 1000);\n const refreshText = `💭 <i>Still thinking... (${elapsed}s)</i>`;\n this.sendQueue\n .enqueue(() => {\n // Re-check after waiting in queue — dismiss may have been called\n if (this.dismissed || !this.msgId) return Promise.resolve(undefined);\n return this.api.editMessageText(\n this.chatId,\n this.msgId,\n refreshText,\n { parse_mode: \"HTML\" },\n );\n })\n .then(() => {})\n .catch(() => {});\n }, THINKING_REFRESH_MS);\n }\n\n private stopRefreshTimer(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n}\n\n// ─── ToolCard ─────────────────────────────────────────────────────────────────\n\nexport class ToolCard {\n private state: ToolCardState;\n private msgId?: number;\n private lastSentText?: string;\n private flushPromise: Promise<void> = Promise.resolve();\n private overflowMsgIds: number[] = [];\n private tracer: DebugTracer | null;\n private sessionId: string;\n\n constructor(\n private api: Bot[\"api\"],\n private chatId: number,\n private threadId: number,\n private sendQueue: SendQueue,\n sessionId: string = \"\",\n tracer: DebugTracer | null = null,\n ) {\n this.tracer = tracer;\n this.sessionId = sessionId;\n this.state = new ToolCardState({\n onFlush: (snapshot) => {\n this.flushPromise = this.flushPromise\n .then(() => this._sendOrEdit(snapshot))\n .catch(() => {});\n },\n });\n }\n\n updateFromSpec(spec: ToolDisplaySpec): void {\n this.state.updateFromSpec(spec);\n }\n\n updatePlan(entries: PlanEntry[]): void {\n this.state.updatePlan(entries);\n }\n\n appendUsage(usage: { tokensUsed?: number; contextSize?: number; cost?: number }): void {\n this.state.appendUsage(usage);\n }\n\n async finalize(): Promise<void> {\n this.state.finalize();\n await this.flushPromise;\n }\n\n destroy(): void {\n this.state.destroy();\n }\n\n hasContent(): boolean {\n return this.state.hasContent();\n }\n\n getMsgId(): number | undefined {\n return this.msgId;\n }\n\n private async _sendOrEdit(snapshot: ToolCardSnapshot): Promise<void> {\n // Overflow strip: if full render exceeds Telegram limit, strip inline outputContent\n let snapshotToRender = snapshot;\n let fullText = renderToolCard(snapshotToRender);\n if (fullText.length > 4096) {\n snapshotToRender = {\n ...snapshot,\n specs: snapshot.specs.map((s) =>\n s.outputContent ? { ...s, outputContent: null } : s\n ),\n };\n fullText = renderToolCard(snapshotToRender);\n }\n\n if (!fullText) return;\n if (this.msgId && fullText === this.lastSentText) return;\n this.lastSentText = fullText;\n\n const chunks = splitToolCardText(fullText);\n this.tracer?.log(\"telegram\", { action: \"toolCard:render\", sessionId: this.sessionId, chunks: chunks.length, total: snapshot.totalVisible, completed: snapshot.completedVisible, allComplete: snapshot.allComplete, msgId: this.msgId, entries: snapshot.specs.map(s => ({ id: s.id, kind: s.kind, icon: s.icon, title: s.title })), html: fullText });\n\n try {\n const firstChunk = chunks[0];\n if (this.msgId) {\n await this.sendQueue.enqueue(() =>\n this.api.editMessageText(this.chatId, this.msgId!, firstChunk, { parse_mode: \"HTML\" }),\n );\n this.tracer?.log(\"telegram\", { action: \"telegram:edit\", sessionId: this.sessionId, msgId: this.msgId, html: firstChunk });\n } else {\n const result = await this.sendQueue.enqueue(() =>\n this.api.sendMessage(this.chatId, firstChunk, {\n message_thread_id: this.threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n if (result) this.msgId = result.message_id;\n this.tracer?.log(\"telegram\", { action: \"telegram:send\", sessionId: this.sessionId, msgId: result?.message_id, html: firstChunk });\n }\n\n for (let i = 1; i < chunks.length; i++) {\n const overflowIdx = i - 1;\n if (overflowIdx < this.overflowMsgIds.length) {\n await this.sendQueue.enqueue(() =>\n this.api.editMessageText(this.chatId, this.overflowMsgIds[overflowIdx], chunks[i], { parse_mode: \"HTML\" }),\n );\n this.tracer?.log(\"telegram\", { action: \"telegram:edit:overflow\", sessionId: this.sessionId, msgId: this.overflowMsgIds[overflowIdx] });\n } else {\n const result = await this.sendQueue.enqueue(() =>\n this.api.sendMessage(this.chatId, chunks[i], {\n message_thread_id: this.threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n if (result) this.overflowMsgIds.push(result.message_id);\n this.tracer?.log(\"telegram\", { action: \"telegram:send:overflow\", sessionId: this.sessionId, msgId: result?.message_id });\n }\n }\n\n // Clean up stale overflow messages when chunk count decreases\n const neededOverflow = chunks.length - 1;\n while (this.overflowMsgIds.length > neededOverflow) {\n const staleId = this.overflowMsgIds.pop()!;\n await this.sendQueue.enqueue(() =>\n this.api.deleteMessage(this.chatId, staleId).catch(() => {}),\n );\n this.tracer?.log(\"telegram\", { action: \"telegram:delete:overflow\", sessionId: this.sessionId, msgId: staleId });\n }\n } catch (err) {\n log.warn({ err }, \"[ToolCard] send/edit failed\");\n }\n }\n}\n\n// ─── ActivityTracker ──────────────────────────────────────────────────────────\n\nexport class ActivityTracker {\n private isFirstEvent = true;\n private thinking: ThinkingIndicator;\n private toolCard: ToolCard;\n private previousToolCard?: ToolCard;\n private toolStateMap: ToolStateMap;\n private previousToolStateMap?: ToolStateMap;\n private specBuilder: DisplaySpecBuilder;\n private thoughtBuffer: ThoughtBuffer;\n private _outputMode: OutputMode;\n private tracer: DebugTracer | null;\n private sessionId: string;\n private sessionContext?: { id: string; workingDirectory: string };\n private tunnelService?: TunnelServiceInterface;\n\n constructor(\n private api: Bot[\"api\"],\n private chatId: number,\n private threadId: number,\n private sendQueue: SendQueue,\n outputMode: OutputMode = \"medium\",\n sessionId: string = \"\",\n tracer: DebugTracer | null = null,\n tunnelService?: TunnelServiceInterface,\n sessionContext?: { id: string; workingDirectory: string },\n ) {\n this._outputMode = outputMode;\n this.tracer = tracer;\n this.sessionId = sessionId;\n this.sessionContext = sessionContext;\n this.tunnelService = tunnelService;\n this.specBuilder = new DisplaySpecBuilder(tunnelService);\n this.toolStateMap = new ToolStateMap();\n this.thoughtBuffer = new ThoughtBuffer();\n this.thinking = new ThinkingIndicator(api, chatId, threadId, sendQueue, sessionId, tracer);\n this.toolCard = new ToolCard(api, chatId, threadId, sendQueue, sessionId, tracer);\n }\n\n setOutputMode(mode: OutputMode): void {\n this._outputMode = mode;\n }\n\n async onNewPrompt(): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:newPrompt\", sessionId: this.sessionId });\n this.isFirstEvent = true;\n this.thoughtBuffer.reset();\n await this.thinking.dismiss();\n this.thinking.reset();\n await this.toolCard.finalize();\n // Clear previous card references so tool updates from new prompt don't leak into old messages\n this.previousToolCard = undefined;\n this.previousToolStateMap = undefined;\n this.toolStateMap.clear();\n this.toolCard = new ToolCard(this.api, this.chatId, this.threadId, this.sendQueue, this.sessionId, this.tracer);\n }\n\n async onThought(text: string): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:thought\", sessionId: this.sessionId });\n this.isFirstEvent = false;\n if (!this.thoughtBuffer.isSealed()) this.thoughtBuffer.append(text);\n await this.sealToolCardIfNeeded();\n await this.thinking.show();\n }\n\n async onTextStart(): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:textStart\", sessionId: this.sessionId });\n this.isFirstEvent = false;\n this.thoughtBuffer.seal();\n\n // In high mode with tunnel: store thought content and show a viewer link before dismissing\n if (this._outputMode === \"high\" && this.tunnelService && this.sessionContext) {\n const thoughtText = this.thoughtBuffer.getText();\n if (thoughtText.trim().length > 0) {\n const id = this.tunnelService.getStore().storeOutput(\n this.sessionContext.id,\n \"thinking\",\n thoughtText,\n );\n if (id !== null) {\n await this.thinking.finalizeWithViewerLink(this.tunnelService.outputUrl(id));\n } else {\n await this.thinking.dismiss();\n }\n } else {\n await this.thinking.dismiss();\n }\n } else {\n await this.thinking.dismiss();\n }\n\n await this.sealToolCardIfNeeded();\n }\n\n async onToolCall(\n meta: ToolCallMeta,\n kind: string,\n rawInput: unknown,\n ): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:toolCall\", sessionId: this.sessionId, meta, kind, rawInput });\n this.isFirstEvent = false;\n await this.thinking.dismiss();\n this.thinking.reset();\n\n const entry = this.toolStateMap.upsert(meta, kind, rawInput);\n const spec = this.specBuilder.buildToolSpec(entry, this._outputMode, this.sessionContext);\n this.toolCard.updateFromSpec(spec);\n }\n\n async onToolUpdate(\n id: string,\n status: string,\n viewerLinks?: ViewerLinks,\n viewerFilePath?: string,\n content?: string | null,\n rawInput?: unknown,\n diffStats?: { added: number; removed: number },\n ): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:toolUpdate\", sessionId: this.sessionId, toolId: id, status, viewerLinks, viewerFilePath, hasPrevCard: !!this.previousToolCard });\n\n // Forward to previous card first if the tool originated there (out-of-order update after seal)\n if (this.previousToolStateMap?.get(id)) {\n this.previousToolStateMap.merge(id, status, rawInput, content, viewerLinks, diffStats);\n const prevEntry = this.previousToolStateMap.get(id);\n if (prevEntry) {\n const prevSpec = this.specBuilder.buildToolSpec(prevEntry, this._outputMode, this.sessionContext);\n this.previousToolCard?.updateFromSpec(prevSpec);\n }\n }\n\n const existed = !!this.toolStateMap.get(id);\n const entry = this.toolStateMap.merge(id, status, rawInput, content, viewerLinks, diffStats);\n // Skip spec build for out-of-order updates — buffered in pendingUpdates\n if (!existed || !entry) return;\n\n if (viewerLinks || entry.viewerLinks) {\n log.debug({ toolId: id, status, hasIncomingLinks: !!viewerLinks, hasEntryLinks: !!entry.viewerLinks, entryLinks: entry.viewerLinks }, \"toolUpdate: viewer links trace\");\n }\n const spec = this.specBuilder.buildToolSpec(entry, this._outputMode, this.sessionContext);\n this.toolCard.updateFromSpec(spec);\n }\n\n async onPlan(entries: PlanEntry[]): Promise<void> {\n this.tracer?.log(\"telegram\", { action: \"tracker:plan\", sessionId: this.sessionId, entries });\n this.isFirstEvent = false;\n await this.thinking.dismiss();\n this.toolCard.updatePlan(entries);\n }\n\n /** @deprecated Usage is now sent as a separate message by the adapter */\n async sendUsage(_usage: {\n tokensUsed?: number;\n contextSize?: number;\n cost?: number;\n }): Promise<void> {\n // no-op — adapter sends usage as a standalone message\n }\n\n getToolCardMsgId(): number | undefined {\n return this.toolCard.getMsgId();\n }\n\n async cleanup(): Promise<void> {\n await this.thinking.dismiss();\n await this.toolCard.finalize();\n this.toolCard.destroy();\n }\n\n destroy(): void {\n void this.thinking.dismiss();\n this.toolCard.destroy();\n }\n\n private async sealToolCardIfNeeded(): Promise<void> {\n if (!this.toolCard.hasContent()) return;\n this.tracer?.log(\"telegram\", { action: \"tracker:seal\", sessionId: this.sessionId });\n await this.toolCard.finalize();\n this.previousToolCard = this.toolCard;\n this.previousToolStateMap = this.toolStateMap;\n this.toolStateMap = new ToolStateMap();\n this.toolCard = new ToolCard(this.api, this.chatId, this.threadId, this.sendQueue, this.sessionId, this.tracer);\n }\n}\n","import { nanoid } from \"nanoid\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { Bot } from \"grammy\";\nimport type { OpenACPCore } from \"../../core/core.js\";\nimport { executeNewSession, executeCancelSession, startInteractiveNewSession } from \"./commands/index.js\";\n\nexport interface DetectedAction {\n action: \"new_session\" | \"cancel_session\";\n agent?: string;\n workspace?: string;\n}\n\n// Command patterns: /new [agent] [workspace], /cancel\n// Agent and workspace are ASCII-only tokens (no Unicode letters) to avoid matching non-ASCII words\nconst CMD_NEW_RE =\n /\\/new(?:\\s+([^\\s\\u0080-\\uFFFF]+)(?:\\s+([^\\s\\u0080-\\uFFFF]+))?)?/;\nconst CMD_CANCEL_RE = /\\/cancel\\b/;\n\n// Keyword patterns (compound phrases only to avoid false positives)\nconst KW_NEW_RE = /(?:create|new)\\s+session/i;\nconst KW_CANCEL_RE = /(?:cancel|stop)\\s+session/i;\n\nexport function detectAction(text: string): DetectedAction | null {\n if (!text) return null;\n\n // Priority 1: command pattern\n const cancelCmd = CMD_CANCEL_RE.exec(text);\n if (cancelCmd) return { action: \"cancel_session\" };\n\n const newCmd = CMD_NEW_RE.exec(text);\n if (newCmd) {\n return {\n action: \"new_session\",\n agent: newCmd[1] || undefined,\n workspace: newCmd[2] || undefined,\n };\n }\n\n // Priority 2: keyword matching\n if (KW_CANCEL_RE.test(text)) return { action: \"cancel_session\" };\n if (KW_NEW_RE.test(text))\n return { action: \"new_session\", agent: undefined, workspace: undefined };\n\n return null;\n}\n\n// --- Callback map for action buttons ---\n\nconst ACTION_TTL_MS = 5 * 60 * 1000; // 5 minutes\nconst actionMap: Map<string, { action: DetectedAction; createdAt: number }> =\n new Map();\n\nexport function storeAction(action: DetectedAction): string {\n const id = nanoid(10);\n actionMap.set(id, { action, createdAt: Date.now() });\n // Cleanup expired entries\n for (const [key, entry] of actionMap) {\n if (Date.now() - entry.createdAt > ACTION_TTL_MS) {\n actionMap.delete(key);\n }\n }\n return id;\n}\n\nexport function getAction(id: string): DetectedAction | undefined {\n const entry = actionMap.get(id);\n if (!entry) return undefined;\n if (Date.now() - entry.createdAt > ACTION_TTL_MS) {\n actionMap.delete(id);\n return undefined;\n }\n return entry.action;\n}\n\nexport function removeAction(id: string): void {\n actionMap.delete(id);\n}\n\nexport function buildActionKeyboard(\n actionId: string,\n action: DetectedAction,\n): InlineKeyboard {\n const keyboard = new InlineKeyboard();\n if (action.action === \"new_session\") {\n keyboard.text(\"✅ Create session\", `a:${actionId}`);\n keyboard.text(\"❌ Cancel\", `a:dismiss:${actionId}`);\n } else {\n keyboard.text(\"⛔ Cancel session\", `a:${actionId}`);\n keyboard.text(\"❌ No\", `a:dismiss:${actionId}`);\n }\n return keyboard;\n}\n\nexport function setupActionCallbacks(\n bot: Bot,\n core: OpenACPCore,\n chatId: number,\n getAssistantSessionId: () => string | undefined,\n): void {\n // IMPORTANT: dismiss handler MUST be registered BEFORE generic a: handler\n // because grammY routes to the first matching handler and /^a:/ also matches a:dismiss:\n bot.callbackQuery(/^a:dismiss:/, async (ctx) => {\n const actionId = ctx.callbackQuery.data.replace(\"a:dismiss:\", \"\");\n removeAction(actionId);\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n } catch {\n /* message may be old */\n }\n await ctx.answerCallbackQuery({ text: \"Dismissed\" });\n });\n\n bot.callbackQuery(/^a:(?!dismiss)/, async (ctx) => {\n const actionId = ctx.callbackQuery.data.replace(\"a:\", \"\");\n const action = getAction(actionId);\n if (!action) {\n await ctx.answerCallbackQuery({ text: \"Action expired\" });\n return;\n }\n removeAction(actionId);\n\n try {\n if (action.action === \"new_session\") {\n // If both agent and workspace provided → create directly\n if (action.agent && action.workspace) {\n await ctx.answerCallbackQuery({ text: \"⏳ Creating session...\" });\n const { threadId, firstMsgId } = await executeNewSession(\n bot,\n core,\n chatId,\n action.agent,\n action.workspace,\n );\n const cleanId = String(chatId).replace(\"-100\", \"\");\n const topicLink = firstMsgId\n ? `https://t.me/c/${cleanId}/${threadId}/${firstMsgId}`\n : `https://t.me/c/${cleanId}/${threadId}`;\n const originalText = ctx.callbackQuery.message?.text ?? \"\";\n try {\n await ctx.editMessageText(\n originalText +\n `\\n\\n✅ Session created → <a href=\"${topicLink}\">Go to topic</a>`,\n { parse_mode: \"HTML\" },\n );\n } catch {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n }\n } else {\n // Missing workspace → start interactive flow\n await ctx.answerCallbackQuery();\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n } catch { /* best effort */ }\n await startInteractiveNewSession(ctx, core, chatId, action.agent);\n }\n } else if (action.action === \"cancel_session\") {\n const assistantId = getAssistantSessionId();\n const cancelled = await executeCancelSession(core, assistantId);\n if (cancelled) {\n await ctx.answerCallbackQuery({ text: \"⛔ Session cancelled\" });\n const originalText = ctx.callbackQuery.message?.text ?? \"\";\n try {\n await ctx.editMessageText(\n originalText +\n `\\n\\n⛔ Session \"${cancelled.name ?? cancelled.id}\" cancelled`,\n { parse_mode: \"HTML\" },\n );\n } catch {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n }\n } else {\n await ctx.answerCallbackQuery({\n text: \"No active session\",\n });\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n } catch {\n /* best effort */\n }\n }\n }\n } catch {\n await ctx.answerCallbackQuery({ text: \"❌ Error, try again later\" });\n try {\n await ctx.editMessageReplyMarkup({\n reply_markup: { inline_keyboard: [] },\n });\n } catch {\n /* best effort */\n }\n }\n });\n}\n","import type { Bot } from 'grammy'\nimport { markdownToTelegramHtml, splitMessage } from './formatting.js'\nimport type { SendQueue } from '../../core/adapter-primitives/primitives/send-queue.js'\nimport type { DebugTracer } from '../../core/utils/debug-tracer.js'\n\nconst FLUSH_INTERVAL = 5000\n\nexport class MessageDraft {\n private buffer: string = ''\n private messageId?: number\n private firstFlushPending = false\n private flushTimer?: ReturnType<typeof setTimeout>\n private flushPromise: Promise<void> = Promise.resolve()\n private lastSentBuffer: string = ''\n private displayTruncated = false\n private tracer: DebugTracer | null\n\n constructor(\n private bot: Bot,\n private chatId: number,\n private threadId: number,\n private sendQueue: SendQueue,\n private sessionId: string,\n tracer: DebugTracer | null = null,\n ) {\n this.tracer = tracer\n }\n\n append(text: string): void {\n if (!text) return\n this.buffer += text\n this.scheduleFlush()\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined\n this.flushPromise = this.flushPromise\n .then(() => this.flush())\n .catch(() => {})\n }, FLUSH_INTERVAL)\n }\n\n private async flush(): Promise<void> {\n if (!this.buffer) return\n if (this.firstFlushPending) return\n\n // CRITICAL: Snapshot the buffer BEFORE any await.\n // append() can be called synchronously while we're awaiting sendQueue,\n // so this.buffer may change. We must track what was ACTUALLY sent.\n const snapshot = this.buffer\n\n let html = markdownToTelegramHtml(snapshot)\n if (!html) return\n let truncated = false\n if (html.length > 4096) {\n // Estimate markdown cut point proportionally, then find a line boundary\n const ratio = 4000 / html.length\n const targetLen = Math.floor(snapshot.length * ratio)\n let cutAt = snapshot.lastIndexOf('\\n', targetLen)\n if (cutAt < targetLen * 0.5) cutAt = targetLen\n html = markdownToTelegramHtml(snapshot.slice(0, cutAt) + '\\n…')\n truncated = true\n if (html.length > 4096) {\n html = html.slice(0, 4090) + '\\n…'\n }\n }\n\n if (!this.messageId) {\n this.firstFlushPending = true\n try {\n const result = await this.sendQueue.enqueue(\n () => this.bot.api.sendMessage(this.chatId, html, {\n message_thread_id: this.threadId,\n parse_mode: 'HTML',\n disable_notification: true,\n }),\n { type: 'other' },\n )\n if (result) {\n this.messageId = result.message_id\n this.tracer?.log(\"telegram\", { action: \"draft:send\", sessionId: this.sessionId, msgId: result.message_id, textLen: snapshot.length, truncated, text: snapshot })\n if (!truncated) {\n this.lastSentBuffer = snapshot\n this.displayTruncated = false\n } else {\n this.displayTruncated = true\n }\n }\n } catch {\n // sendMessage failed — next flush will retry\n } finally {\n this.firstFlushPending = false\n }\n } else {\n try {\n const result = await this.sendQueue.enqueue(\n () => this.bot.api.editMessageText(this.chatId, this.messageId!, html, {\n parse_mode: 'HTML',\n }),\n { type: 'text', key: this.sessionId },\n )\n // Only mark as sent if the edit was actually executed (not dropped by dedup/rate-limit)\n if (result !== undefined) {\n this.tracer?.log(\"telegram\", { action: \"draft:edit\", sessionId: this.sessionId, msgId: this.messageId, textLen: snapshot.length, truncated, text: snapshot })\n if (!truncated) {\n this.lastSentBuffer = snapshot\n this.displayTruncated = false\n } else {\n this.displayTruncated = true\n }\n }\n } catch {\n // Don't reset messageId — transient errors (rate limit, network) would cause\n // the next flush to sendMessage the full buffer as a NEW message, creating duplicates.\n // If the message was truly deleted, finalize() handles the fallback.\n }\n }\n }\n\n async finalize(): Promise<number | undefined> {\n this.tracer?.log(\"telegram\", { action: \"draft:finalize\", sessionId: this.sessionId, bufferLen: this.buffer.length, msgId: this.messageId })\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = undefined\n }\n\n await this.flushPromise\n\n if (!this.buffer) return this.messageId\n\n // Skip if buffer was already fully sent by flush() and nothing new was appended.\n // Do NOT skip if flush() truncated the display — finalize must send the full content.\n if (this.messageId && this.buffer === this.lastSentBuffer && !this.displayTruncated) {\n return this.messageId\n }\n\n // Try sending full buffer as a single message (most common case).\n // Only split if HTML exceeds Telegram's 4096 char limit.\n const fullHtml = markdownToTelegramHtml(this.buffer)\n if (fullHtml.length <= 4096) {\n // Single enqueue — no ordering issue possible\n try {\n if (this.messageId) {\n await this.sendQueue.enqueue(\n () => this.bot.api.editMessageText(this.chatId, this.messageId!, fullHtml, {\n parse_mode: 'HTML',\n }),\n { type: 'other' },\n )\n this.tracer?.log(\"telegram\", { action: \"draft:finalize:edit\", sessionId: this.sessionId, msgId: this.messageId })\n } else {\n const msg = await this.sendQueue.enqueue(\n () => this.bot.api.sendMessage(this.chatId, fullHtml, {\n message_thread_id: this.threadId,\n parse_mode: 'HTML',\n disable_notification: true,\n }),\n { type: 'other' },\n )\n if (msg) this.messageId = msg.message_id\n this.tracer?.log(\"telegram\", { action: \"draft:finalize:send\", sessionId: this.sessionId, msgId: msg?.message_id })\n }\n return this.messageId\n } catch {\n // HTML send failed — fall through to split/fallback below\n }\n }\n\n // HTML > 4096 or single send failed — split markdown, convert each chunk separately.\n // This prevents breaking HTML tags (e.g. <pre><code>) at split boundaries.\n //\n // CRITICAL: Enqueue ALL chunks in a tight synchronous loop (no await between\n // enqueues). This prevents concurrent event handlers (usage, session_end) from\n // slipping their messages between our chunks in the sendQueue.\n const mdChunks = splitMessage(this.buffer)\n const chunkPromises: Promise<void>[] = []\n\n for (let i = 0; i < mdChunks.length; i++) {\n const html = markdownToTelegramHtml(mdChunks[i])\n const isEdit = i === 0 && !!this.messageId\n const chunkMd = mdChunks[i]\n\n const fn = isEdit\n ? () => this.bot.api.editMessageText(this.chatId, this.messageId!, html, { parse_mode: 'HTML' }) as Promise<unknown>\n : () => this.bot.api.sendMessage(this.chatId, html, {\n message_thread_id: this.threadId,\n parse_mode: 'HTML',\n disable_notification: true,\n })\n const promise = this.sendQueue.enqueue(fn, { type: 'other' })\n .then((result) => {\n if (!isEdit && result && typeof result === 'object' && 'message_id' in (result as Record<string, unknown>)) {\n this.messageId = (result as { message_id: number }).message_id\n }\n })\n .catch(() => {\n // HTML failed — enqueue plain text fallback (goes after all chunks, acceptable)\n const fallbackFn = isEdit\n ? () => this.bot.api.editMessageText(this.chatId, this.messageId!, chunkMd.slice(0, 4096)) as Promise<unknown>\n : () => this.bot.api.sendMessage(this.chatId, chunkMd.slice(0, 4096), {\n message_thread_id: this.threadId,\n disable_notification: true,\n })\n return this.sendQueue.enqueue(fallbackFn, { type: 'other' })\n .then((result) => {\n if (!isEdit && result && typeof result === 'object' && 'message_id' in (result as Record<string, unknown>)) {\n this.messageId = (result as { message_id: number }).message_id\n }\n })\n .catch(() => {})\n })\n\n chunkPromises.push(promise)\n }\n\n // All chunks are now in the queue — any items enqueued by concurrent handlers\n // (usage, session_end) will go AFTER our chunks. Safe to await.\n await Promise.all(chunkPromises)\n this.tracer?.log(\"telegram\", { action: \"draft:finalize:split\", sessionId: this.sessionId, chunks: mdChunks.length })\n\n return this.messageId\n }\n\n getMessageId(): number | undefined {\n return this.messageId\n }\n\n async stripPattern(pattern: RegExp): Promise<void> {\n if (!this.messageId || !this.buffer) return\n\n const stripped = this.buffer.replace(pattern, '').trim()\n if (stripped === this.buffer.trim()) return\n\n this.buffer = stripped\n this.lastSentBuffer = stripped\n\n const html = markdownToTelegramHtml(stripped)\n if (!html) return\n\n try {\n await this.sendQueue.enqueue(\n () => this.bot.api.editMessageText(this.chatId, this.messageId!, html, {\n parse_mode: 'HTML',\n }),\n { type: 'other' },\n )\n } catch {\n // Best effort — non-critical edit\n }\n }\n}\n","import type { Bot } from \"grammy\";\nimport { MessageDraft } from \"./streaming.js\";\nimport type { SendQueue } from \"../../core/adapter-primitives/primitives/send-queue.js\";\nimport type { DebugTracer } from \"../../core/utils/debug-tracer.js\";\nimport {\n detectAction,\n storeAction,\n buildActionKeyboard,\n} from \"./action-detect.js\";\n\ninterface FinalizedDraft {\n messageId: number;\n draft: MessageDraft;\n}\n\nexport class DraftManager {\n private drafts: Map<string, MessageDraft> = new Map();\n private textBuffers: Map<string, string> = new Map();\n private finalizedDrafts: Map<string, FinalizedDraft> = new Map();\n\n constructor(\n private bot: Bot,\n private chatId: number,\n private sendQueue: SendQueue,\n ) {}\n\n getOrCreate(sessionId: string, threadId: number, tracer: DebugTracer | null = null): MessageDraft {\n let draft = this.drafts.get(sessionId);\n if (!draft) {\n draft = new MessageDraft(\n this.bot,\n this.chatId,\n threadId,\n this.sendQueue,\n sessionId,\n tracer,\n );\n this.drafts.set(sessionId, draft);\n }\n return draft;\n }\n\n hasDraft(sessionId: string): boolean {\n return this.drafts.has(sessionId);\n }\n\n getDraft(sessionId: string): MessageDraft | undefined {\n return this.drafts.get(sessionId);\n }\n\n appendText(sessionId: string, text: string): void {\n this.textBuffers.set(\n sessionId,\n (this.textBuffers.get(sessionId) ?? \"\") + text,\n );\n }\n\n /**\n * Finalize the current draft and return the message ID.\n * Optionally detects actions in assistant responses.\n */\n async finalize(\n sessionId: string,\n assistantSessionId?: string,\n ): Promise<void> {\n const draft = this.drafts.get(sessionId);\n if (!draft) return;\n\n // Delete BEFORE awaiting to prevent concurrent finalizeDraft() calls\n // from double-finalizing the same draft\n this.drafts.delete(sessionId);\n const finalMsgId = await draft.finalize();\n\n // Keep finalized draft reference so tts_strip can edit after finalization\n if (finalMsgId) {\n this.finalizedDrafts.set(sessionId, { messageId: finalMsgId, draft });\n }\n\n // Detect actions in assistant responses and attach keyboard\n if (assistantSessionId && sessionId === assistantSessionId) {\n const fullText = this.textBuffers.get(sessionId);\n this.textBuffers.delete(sessionId);\n if (fullText && finalMsgId) {\n const detected = detectAction(fullText);\n if (detected) {\n const actionId = storeAction(detected);\n const keyboard = buildActionKeyboard(actionId, detected);\n try {\n await this.bot.api.editMessageReplyMarkup(\n this.chatId,\n finalMsgId,\n { reply_markup: keyboard },\n );\n } catch {\n // Best effort — keyboard attachment is non-critical\n }\n }\n }\n } else {\n this.textBuffers.delete(sessionId);\n }\n }\n\n /**\n * Strip a regex pattern from the active or finalized draft for a session.\n * Used by tts_strip to remove [TTS]...[/TTS] blocks after TTS audio is sent.\n */\n async stripPattern(sessionId: string, pattern: RegExp): Promise<void> {\n const draft = this.drafts.get(sessionId);\n if (draft) {\n await draft.stripPattern(pattern);\n return;\n }\n const finalized = this.finalizedDrafts.get(sessionId);\n if (finalized) {\n await finalized.draft.stripPattern(pattern);\n }\n // If no draft found (e.g., TTS synthesis slower than next prompt cycle), the\n // [TTS] block will remain visible. This is a rare edge case — log for debugging.\n }\n\n cleanup(sessionId: string): void {\n this.drafts.delete(sessionId);\n this.textBuffers.delete(sessionId);\n this.finalizedDrafts.delete(sessionId);\n }\n}\n","import type { Bot } from \"grammy\";\nimport type { SendQueue } from \"../../core/adapter-primitives/primitives/send-queue.js\";\nimport type { AgentCommand } from \"../../core/types.js\";\nimport type { SessionManager } from \"../../core/sessions/session-manager.js\";\nimport type { TelegramPlatformData } from \"../../core/types.js\";\nimport { buildSkillMessages } from \"./commands/index.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"skill-commands\" });\n\nexport class SkillCommandManager {\n private messages: Map<string, number> = new Map(); // sessionId → pinned msgId\n\n constructor(\n private bot: Bot,\n private chatId: number,\n private sendQueue: SendQueue,\n private sessionManager: SessionManager,\n ) {}\n\n async send(\n sessionId: string,\n threadId: number,\n commands: AgentCommand[],\n ): Promise<void> {\n // Restore skillMsgIds from persisted platform data if not in memory\n if (!this.messages.has(sessionId)) {\n const record = this.sessionManager.getSessionRecord(sessionId);\n const platform = record?.platform as TelegramPlatformData | undefined;\n if (platform?.skillMsgId) {\n this.messages.set(sessionId, platform.skillMsgId);\n }\n }\n\n // Empty commands → remove pinned message\n if (commands.length === 0) {\n await this.cleanup(sessionId);\n return;\n }\n\n const messages = buildSkillMessages(commands);\n const existingMsgId = this.messages.get(sessionId);\n\n if (existingMsgId) {\n try {\n await this.bot.api.editMessageText(\n this.chatId,\n existingMsgId,\n messages[0],\n { parse_mode: \"HTML\" },\n );\n return;\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : \"\";\n if (msg.includes(\"message is not modified\")) return;\n try {\n await this.bot.api.deleteMessage(this.chatId, existingMsgId);\n } catch { /* already gone */ }\n this.messages.delete(sessionId);\n }\n }\n\n // Send new messages and pin the first one\n try {\n let firstMsgId: number | undefined;\n for (const text of messages) {\n const msg = await this.sendQueue.enqueue(() =>\n this.bot.api.sendMessage(this.chatId, text, {\n message_thread_id: threadId,\n parse_mode: \"HTML\",\n disable_notification: true,\n }),\n );\n if (!firstMsgId) firstMsgId = msg!.message_id;\n }\n\n this.messages.set(sessionId, firstMsgId!);\n\n // Persist skillMsgId so it survives restarts\n const record = this.sessionManager.getSessionRecord(sessionId);\n if (record) {\n await this.sessionManager.patchRecord(sessionId, {\n platform: { ...record.platform, skillMsgId: firstMsgId },\n });\n }\n\n await this.bot.api.pinChatMessage(this.chatId, firstMsgId!, {\n disable_notification: true,\n });\n } catch (err) {\n log.error({ err, sessionId }, \"Failed to send skill commands\");\n }\n }\n\n async cleanup(sessionId: string): Promise<void> {\n const msgId = this.messages.get(sessionId);\n if (!msgId) return;\n\n try {\n await this.bot.api.editMessageText(\n this.chatId,\n msgId,\n \"🛠 <i>Session ended</i>\",\n { parse_mode: \"HTML\" },\n );\n await this.bot.api.unpinChatMessage(this.chatId, msgId);\n } catch { /* message may already be deleted */ }\n\n this.messages.delete(sessionId);\n\n // Clear persisted skillMsgId\n const record = this.sessionManager.getSessionRecord(sessionId);\n if (record) {\n const platform = record.platform;\n if (platform && typeof platform === 'object' && 'topicId' in platform) {\n const { skillMsgId: _removed, ...rest } = platform as unknown as TelegramPlatformData;\n await this.sessionManager.patchRecord(sessionId, { platform: rest });\n }\n }\n }\n}\n","import { BaseRenderer } from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport type { RenderedMessage } from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport type { OutgoingMessage, NotificationMessage } from \"../../core/types.js\";\nimport type {\n DisplayVerbosity,\n ToolCallMeta,\n ToolUpdateMeta,\n} from \"../../core/adapter-primitives/format-types.js\";\nimport {\n escapeHtml,\n formatToolCall,\n formatToolUpdate,\n formatPlan,\n formatUsage,\n} from \"./formatting.js\";\n\nexport class TelegramRenderer extends BaseRenderer {\n renderToolCall(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolCallMeta>;\n return {\n body: formatToolCall(meta as ToolCallMeta, verbosity),\n format: \"html\",\n };\n }\n\n renderToolUpdate(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = (content.metadata ?? {}) as Partial<ToolUpdateMeta>;\n return {\n body: formatToolUpdate(meta as ToolUpdateMeta, verbosity),\n format: \"html\",\n };\n }\n\n renderPlan(content: OutgoingMessage): RenderedMessage {\n const meta = content.metadata as\n | { entries?: Array<{ content: string; status: string }> }\n | undefined;\n return {\n body: formatPlan({ entries: meta?.entries ?? [] }),\n format: \"html\",\n };\n }\n\n renderUsage(\n content: OutgoingMessage,\n verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const meta = content.metadata as\n | { tokensUsed?: number; contextSize?: number; cost?: number }\n | undefined;\n return { body: formatUsage(meta ?? {}, verbosity), format: \"html\" };\n }\n\n renderError(content: OutgoingMessage): RenderedMessage {\n return {\n body: `❌ <b>Error:</b> ${escapeHtml(content.text)}`,\n format: \"html\",\n };\n }\n\n renderNotification(notification: NotificationMessage): RenderedMessage {\n const emoji: Record<string, string> = {\n completed: \"✅\",\n error: \"❌\",\n permission: \"🔐\",\n input_required: \"💬\",\n budget_warning: \"⚠️\",\n };\n let text = `${emoji[notification.type] || \"ℹ️\"} <b>${escapeHtml(notification.sessionName || \"Session\")}</b>\\n`;\n text += escapeHtml(notification.summary);\n return { body: text, format: \"html\" };\n }\n\n renderSystemMessage(content: OutgoingMessage): RenderedMessage {\n return { body: escapeHtml(content.text), format: \"html\" };\n }\n\n renderModeChange(content: OutgoingMessage): RenderedMessage {\n const modeId = (content.metadata as Record<string, unknown>)?.modeId ?? \"\";\n return {\n body: `🔄 <b>Mode:</b> ${escapeHtml(String(modeId))}`,\n format: \"html\",\n };\n }\n\n renderConfigUpdate(): RenderedMessage {\n return { body: \"⚙️ <b>Config updated</b>\", format: \"html\" };\n }\n\n renderModelUpdate(content: OutgoingMessage): RenderedMessage {\n const modelId =\n (content.metadata as Record<string, unknown>)?.modelId ?? \"\";\n return {\n body: `🤖 <b>Model:</b> ${escapeHtml(String(modelId))}`,\n format: \"html\",\n };\n }\n}\n"],"mappings":"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","names":["resolve","path","fs","os","expandHome","fs","path","log","fs","path","fs","path","os","expandHome","log","getConfigValue","input","resolved","fs","execFileSync","fs","path","fs","path","os","resolve","platform","log","fs","os","path","fs","path","path","fs","path","os","fs","path","fileURLToPath","dirname","join","resolve","existsSync","readFileSync","spawn","clack","ok","InlineKeyboard","header","c","existsSync","mkdirSync","readFileSync","writeFileSync","unlinkSync","join","dirname","homedir","resolve","ok","spawn","fs","path","resolve","fs","path","log","path","fs","spawn","resolve","c","text","text","resolve","resolve","fs","text","c","log","input","id","log","fs","log","path","os","fs","path","log","log","fs","path","os","fs","path","os","z","log","fs","path","os","log","platform","execFileSync","log","readFileSync","path","os","fs","path","path","os","log","resolve","log","path","os","setLogLevel","access","platform","existsSync","fs","path","fs","execFileSync","fs","path","commandExists","fs","fs","expandHome","fs","path","fs","resolve","fs","path","os","execFileSync","ensureCloudflared","expandHome","path","clack","execFileSync","fs","path","os","log","logDir","select","validateBotToken","tgUp","validateChatId","installNpmPlugin","SettingsManager","createInstallContext","getGlobalRoot","logDir","expandHome","path","spawn","fs","path","os","DEFAULT_ROOT","logDir","expandHome","resolve","isProcessAlive","fs","path","readTextFileWithRange","log","text","os","path","fs","path","execFileSync","text","text","c","path","text","text","resolve","text","DEBOUNCE_MS","input","InlineKeyboard","text","splitMessage","text","log","log","toastText","getCurrentVersion","getLatestVersion","compareVersions","runUpdate","ok","log","InlineKeyboard","text","InlineKeyboard","log","platform","header","InlineKeyboard","InlineKeyboard","text","InlineKeyboard","getAgentCapabilities","installIntegration","InlineKeyboard","listIntegrations","InlineKeyboard","keyboard","agentName","getIntegration","integration","fs","path","os","InlineKeyboard","log","PENDING_TIMEOUT_MS","botFromCtx","cleanupPending","text","InlineKeyboard","InlineKeyboard","log","buildMenuKeyboard","InlineKeyboard","log","escapeHtml","InlineKeyboard","text","InlineKeyboard","log","InlineKeyboard","InlineKeyboard","log","InlineKeyboard","InlineKeyboard","nanoid","log","nanoid","InlineKeyboard","log","text","log","text","ActivityTracker","nanoid","InlineKeyboard","text","nanoid","InlineKeyboard","text","splitMessage","DraftManager","text","log","platform","text","text","log","input","ActivityTracker","DraftManager","text","getAgentCapabilities","platform"]}
|