@openacp/cli 2026.327.3 → 2026.328.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/dist/adapter-HGJENQCN.js +13 -0
- package/dist/agent-catalog-SZQQERV7.js +10 -0
- package/dist/{agent-dependencies-WS7Z2DFW.js → agent-dependencies-ED2ZTUHG.js} +1 -2
- package/dist/{agent-registry-5LZT7CUB.js → agent-registry-YOGP656W.js} +1 -2
- package/dist/agent-store-5UHZH2XI.js +8 -0
- package/dist/{api-client-AQPNKXI2.js → api-client-XTLRRFPX.js} +1 -2
- package/dist/api-server-DSUW637I.js +7 -0
- package/dist/api-server-WFB5K6FP.js +10 -0
- package/dist/{autostart-6JS565RY.js → autostart-CUPZMKKC.js} +3 -4
- package/dist/{chunk-WIIZNPCR.js → chunk-2KT6TROD.js} +12 -33
- package/dist/chunk-2KT6TROD.js.map +1 -0
- package/dist/{chunk-PPSMUECX.js → chunk-2R5XM3ES.js} +2 -2
- package/dist/{chunk-SNPYTMPR.js → chunk-3EWTPOF7.js} +2 -2
- package/dist/{chunk-YEULD3SG.js → chunk-3NAFXVQM.js} +7 -2
- package/dist/{chunk-YEULD3SG.js.map → chunk-3NAFXVQM.js.map} +1 -1
- package/dist/{chunk-QAQDGPB4.js → chunk-43JVXFYP.js} +3 -3
- package/dist/{chunk-KMMEFXIE.js → chunk-4B6PCWQP.js} +37 -9
- package/dist/chunk-4B6PCWQP.js.map +1 -0
- package/dist/{chunk-A6Y4GZM3.js → chunk-566W6INH.js} +2 -2
- package/dist/{chunk-ODUM3D6X.js → chunk-5HKQCYOI.js} +1 -39
- package/dist/chunk-5HKQCYOI.js.map +1 -0
- package/dist/{chunk-36YQ44D7.js → chunk-5TCXYDLR.js} +3 -3
- package/dist/{chunk-XIBG7LSL.js → chunk-6VR4GWOO.js} +238 -108
- package/dist/chunk-6VR4GWOO.js.map +1 -0
- package/dist/{chunk-WXVT3AOY.js → chunk-7ZCQF6QM.js} +8 -3
- package/dist/chunk-7ZCQF6QM.js.map +1 -0
- package/dist/{chunk-HUWOFP2H.js → chunk-E2SLHZAC.js} +8 -12
- package/dist/{chunk-HUWOFP2H.js.map → chunk-E2SLHZAC.js.map} +1 -1
- package/dist/{chunk-RBYBSSGO.js → chunk-FCTC7KDT.js} +2 -2
- package/dist/chunk-I53NEV3S.js +45 -0
- package/dist/chunk-I53NEV3S.js.map +1 -0
- package/dist/{chunk-2YCW3QDV.js → chunk-IXMIC4GQ.js} +8 -7
- package/dist/chunk-IXMIC4GQ.js.map +1 -0
- package/dist/{chunk-BLQUXO7S.js → chunk-IZ5UEZF7.js} +27 -2
- package/dist/chunk-IZ5UEZF7.js.map +1 -0
- package/dist/{chunk-QVMEF6FB.js → chunk-JOMDPFQ2.js} +10 -24
- package/dist/chunk-JOMDPFQ2.js.map +1 -0
- package/dist/{chunk-4GMLGCF2.js → chunk-JUFN4XMB.js} +2 -2
- package/dist/{chunk-AD3X6DGK.js → chunk-NT6FYV27.js} +75 -13
- package/dist/chunk-NT6FYV27.js.map +1 -0
- package/dist/{chunk-UMT7RU77.js → chunk-QBEQJFGL.js} +9 -9
- package/dist/{chunk-XMMAGAT4.js → chunk-R6KZYF7D.js} +8 -1
- package/dist/{chunk-XMMAGAT4.js.map → chunk-R6KZYF7D.js.map} +1 -1
- package/dist/{chunk-LP45RCA4.js → chunk-RXMWJHWH.js} +1007 -495
- package/dist/chunk-RXMWJHWH.js.map +1 -0
- package/dist/{chunk-SHTGQGAU.js → chunk-V2YZWYXT.js} +3 -3
- package/dist/{chunk-BQ6FR32N.js → chunk-VD3QSMVY.js} +2 -2
- package/dist/cli.js +141 -115
- package/dist/cli.js.map +1 -1
- package/dist/{config-I4FMCJGZ.js → config-UCAFCS5W.js} +3 -4
- package/dist/config-editor-OU6PUY66.js +10 -0
- package/dist/{config-registry-CUMNXFGK.js → config-registry-ZXAIJNYB.js} +2 -3
- package/dist/{context-XM6E22LM.js → context-7MPU7RL5.js} +1 -2
- package/dist/core-plugins-R2EVZAJV.js +22 -0
- package/dist/{daemon-PXO5QPCR.js → daemon-DTA6KYYY.js} +4 -5
- package/dist/{dev-loader-DRU3R7ZM.js → dev-loader-7P3HZCIA.js} +1 -3
- package/dist/{dev-loader-DRU3R7ZM.js.map → dev-loader-7P3HZCIA.js.map} +1 -1
- package/dist/doctor-D723IB2I.js +9 -0
- package/dist/file-service-HHB3JQIO.js +8 -0
- package/dist/index.d.ts +41 -150
- package/dist/index.js +63 -29
- package/dist/index.js.map +1 -1
- package/dist/{install-cloudflared-AN24L4DP.js → install-cloudflared-JRJ4BSOM.js} +3 -4
- package/dist/{install-cloudflared-AN24L4DP.js.map → install-cloudflared-JRJ4BSOM.js.map} +1 -1
- package/dist/{install-context-XPWTFT3J.js → install-context-EHYV5WRY.js} +2 -3
- package/dist/{install-context-XPWTFT3J.js.map → install-context-EHYV5WRY.js.map} +1 -1
- package/dist/{install-jq-CRVDJGF3.js → install-jq-ISTGT263.js} +3 -4
- package/dist/{install-jq-CRVDJGF3.js.map → install-jq-ISTGT263.js.map} +1 -1
- package/dist/{integrate-G6CVXTGT.js → integrate-JIEZYDOR.js} +1 -2
- package/dist/{integrate-G6CVXTGT.js.map → integrate-JIEZYDOR.js.map} +1 -1
- package/dist/{log-LZ7FTRKG.js → log-YZ243M5G.js} +4 -3
- package/dist/{main-UVTZ46WP.js → main-RRSX5SRL.js} +117 -40
- package/dist/main-RRSX5SRL.js.map +1 -0
- package/dist/{menu-YDQ2LWAR.js → menu-ALFN37IR.js} +1 -2
- package/dist/notifications-MO23S7S3.js +8 -0
- package/dist/{plugin-create-5HQRF2ID.js → plugin-create-EHL76ZZG.js} +1 -2
- package/dist/{plugin-create-5HQRF2ID.js.map → plugin-create-EHL76ZZG.js.map} +1 -1
- package/dist/plugin-installer-5XHORMLS.js +9 -0
- package/dist/{plugin-registry-WB3DR67H.js → plugin-registry-6J3YSFHF.js} +1 -2
- package/dist/{plugin-search-HQ4WQKOF.js → plugin-search-MGKAL5JM.js} +1 -2
- package/dist/{plugin-search-HQ4WQKOF.js.map → plugin-search-MGKAL5JM.js.map} +1 -1
- package/dist/{post-upgrade-3ADZRMYJ.js → post-upgrade-Y26S2ZQ7.js} +6 -7
- package/dist/{post-upgrade-3ADZRMYJ.js.map → post-upgrade-Y26S2ZQ7.js.map} +1 -1
- package/dist/{read-text-file-IRZM3QLM.js → read-text-file-DJBTITIB.js} +1 -2
- package/dist/{registry-client-AVGRE4CF.js → registry-client-GTBWLXYU.js} +1 -2
- package/dist/{security-YNRBW6S7.js → security-2BA265LN.js} +1 -2
- package/dist/{settings-manager-MD2U4ZV2.js → settings-manager-B4UN2LAC.js} +1 -2
- package/dist/{setup-EYAFK2WI.js → setup-OI6A3OXW.js} +109 -80
- package/dist/setup-OI6A3OXW.js.map +1 -0
- package/dist/speech-GB7PHVQZ.js +9 -0
- package/dist/{suggest-7D6B542M.js → suggest-RST5VOHB.js} +1 -3
- package/dist/{suggest-7D6B542M.js.map → suggest-RST5VOHB.js.map} +1 -1
- package/dist/telegram-UVIAXADE.js +7 -0
- package/dist/tunnel-4WNFC7GO.js +7 -0
- package/dist/{tunnel-service-QJPUYEKU.js → tunnel-service-I2NFUX3V.js} +3 -4
- package/dist/{tunnel-service-QJPUYEKU.js.map → tunnel-service-I2NFUX3V.js.map} +1 -1
- package/dist/{validators-WSTBNKRW.js → validators-GITLOFXC.js} +1 -2
- package/dist/{version-NQZBM5M7.js → version-AXXV6IV2.js} +1 -2
- package/package.json +1 -3
- package/dist/adapter-LC2QSDAS.js +0 -15
- package/dist/adapter-Y55NXX6I.js +0 -1006
- package/dist/adapter-Y55NXX6I.js.map +0 -1
- package/dist/agent-catalog-YHBFERYO.js +0 -11
- package/dist/agent-store-VSHNY5GT.js +0 -9
- package/dist/api-server-7G3ZUZRM.js +0 -8
- package/dist/api-server-CAYNPUF2.js +0 -11
- package/dist/chunk-2YCW3QDV.js.map +0 -1
- package/dist/chunk-3ASUU6WW.js +0 -124
- package/dist/chunk-3ASUU6WW.js.map +0 -1
- package/dist/chunk-AD3X6DGK.js.map +0 -1
- package/dist/chunk-BLQUXO7S.js.map +0 -1
- package/dist/chunk-KMMEFXIE.js.map +0 -1
- package/dist/chunk-LP45RCA4.js.map +0 -1
- package/dist/chunk-ODUM3D6X.js.map +0 -1
- package/dist/chunk-QVMEF6FB.js.map +0 -1
- package/dist/chunk-TRXBJEZ5.js +0 -447
- package/dist/chunk-TRXBJEZ5.js.map +0 -1
- package/dist/chunk-VUNV25KB.js +0 -16
- package/dist/chunk-WIIZNPCR.js.map +0 -1
- package/dist/chunk-WXVT3AOY.js.map +0 -1
- package/dist/chunk-XIBG7LSL.js.map +0 -1
- package/dist/config-editor-3IKBPZA7.js +0 -11
- package/dist/core-plugins-ROU4GPLT.js +0 -23
- package/dist/dist-UHQK5CXN.js +0 -21151
- package/dist/dist-UHQK5CXN.js.map +0 -1
- package/dist/doctor-QZQAP46W.js +0 -10
- package/dist/file-service-EUODJAIT.js +0 -9
- package/dist/main-UVTZ46WP.js.map +0 -1
- package/dist/notifications-D5BRDNSU.js +0 -9
- package/dist/plugin-installer-GQ2P3Q3E.js +0 -23
- package/dist/plugin-installer-GQ2P3Q3E.js.map +0 -1
- package/dist/setup-EYAFK2WI.js.map +0 -1
- package/dist/slack-37ZWBDUI.js +0 -8
- package/dist/speech-2GHQNRIO.js +0 -9
- package/dist/telegram-2ZCCCZIY.js +0 -8
- package/dist/tunnel-45HA72MB.js +0 -8
- package/dist/version-NQZBM5M7.js.map +0 -1
- /package/dist/{adapter-LC2QSDAS.js.map → adapter-HGJENQCN.js.map} +0 -0
- /package/dist/{agent-catalog-YHBFERYO.js.map → agent-catalog-SZQQERV7.js.map} +0 -0
- /package/dist/{agent-dependencies-WS7Z2DFW.js.map → agent-dependencies-ED2ZTUHG.js.map} +0 -0
- /package/dist/{agent-registry-5LZT7CUB.js.map → agent-registry-YOGP656W.js.map} +0 -0
- /package/dist/{agent-store-VSHNY5GT.js.map → agent-store-5UHZH2XI.js.map} +0 -0
- /package/dist/{api-client-AQPNKXI2.js.map → api-client-XTLRRFPX.js.map} +0 -0
- /package/dist/{api-server-7G3ZUZRM.js.map → api-server-DSUW637I.js.map} +0 -0
- /package/dist/{api-server-CAYNPUF2.js.map → api-server-WFB5K6FP.js.map} +0 -0
- /package/dist/{autostart-6JS565RY.js.map → autostart-CUPZMKKC.js.map} +0 -0
- /package/dist/{chunk-PPSMUECX.js.map → chunk-2R5XM3ES.js.map} +0 -0
- /package/dist/{chunk-SNPYTMPR.js.map → chunk-3EWTPOF7.js.map} +0 -0
- /package/dist/{chunk-QAQDGPB4.js.map → chunk-43JVXFYP.js.map} +0 -0
- /package/dist/{chunk-A6Y4GZM3.js.map → chunk-566W6INH.js.map} +0 -0
- /package/dist/{chunk-36YQ44D7.js.map → chunk-5TCXYDLR.js.map} +0 -0
- /package/dist/{chunk-RBYBSSGO.js.map → chunk-FCTC7KDT.js.map} +0 -0
- /package/dist/{chunk-4GMLGCF2.js.map → chunk-JUFN4XMB.js.map} +0 -0
- /package/dist/{chunk-UMT7RU77.js.map → chunk-QBEQJFGL.js.map} +0 -0
- /package/dist/{chunk-SHTGQGAU.js.map → chunk-V2YZWYXT.js.map} +0 -0
- /package/dist/{chunk-BQ6FR32N.js.map → chunk-VD3QSMVY.js.map} +0 -0
- /package/dist/{chunk-VUNV25KB.js.map → config-UCAFCS5W.js.map} +0 -0
- /package/dist/{config-I4FMCJGZ.js.map → config-editor-OU6PUY66.js.map} +0 -0
- /package/dist/{config-editor-3IKBPZA7.js.map → config-registry-ZXAIJNYB.js.map} +0 -0
- /package/dist/{config-registry-CUMNXFGK.js.map → context-7MPU7RL5.js.map} +0 -0
- /package/dist/{context-XM6E22LM.js.map → core-plugins-R2EVZAJV.js.map} +0 -0
- /package/dist/{core-plugins-ROU4GPLT.js.map → daemon-DTA6KYYY.js.map} +0 -0
- /package/dist/{daemon-PXO5QPCR.js.map → doctor-D723IB2I.js.map} +0 -0
- /package/dist/{doctor-QZQAP46W.js.map → file-service-HHB3JQIO.js.map} +0 -0
- /package/dist/{file-service-EUODJAIT.js.map → log-YZ243M5G.js.map} +0 -0
- /package/dist/{log-LZ7FTRKG.js.map → menu-ALFN37IR.js.map} +0 -0
- /package/dist/{menu-YDQ2LWAR.js.map → notifications-MO23S7S3.js.map} +0 -0
- /package/dist/{notifications-D5BRDNSU.js.map → plugin-installer-5XHORMLS.js.map} +0 -0
- /package/dist/{plugin-registry-WB3DR67H.js.map → plugin-registry-6J3YSFHF.js.map} +0 -0
- /package/dist/{read-text-file-IRZM3QLM.js.map → read-text-file-DJBTITIB.js.map} +0 -0
- /package/dist/{registry-client-AVGRE4CF.js.map → registry-client-GTBWLXYU.js.map} +0 -0
- /package/dist/{security-YNRBW6S7.js.map → security-2BA265LN.js.map} +0 -0
- /package/dist/{settings-manager-MD2U4ZV2.js.map → settings-manager-B4UN2LAC.js.map} +0 -0
- /package/dist/{slack-37ZWBDUI.js.map → speech-GB7PHVQZ.js.map} +0 -0
- /package/dist/{speech-2GHQNRIO.js.map → telegram-UVIAXADE.js.map} +0 -0
- /package/dist/{telegram-2ZCCCZIY.js.map → tunnel-4WNFC7GO.js.map} +0 -0
- /package/dist/{tunnel-45HA72MB.js.map → validators-GITLOFXC.js.map} +0 -0
- /package/dist/{validators-WSTBNKRW.js.map → version-AXXV6IV2.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/utils/streams.ts","../../src/core/utils/stderr-capture.ts","../../src/core/utils/typed-emitter.ts","../../src/core/agents/agent-instance.ts","../../src/core/sessions/terminal-manager.ts","../../src/core/agents/mcp-manager.ts","../../src/core/agents/agent-manager.ts","../../src/core/sessions/prompt-queue.ts","../../src/core/sessions/permission-gate.ts","../../src/core/sessions/session.ts","../../src/core/sessions/session-manager.ts","../../src/core/sessions/session-bridge.ts","../../src/core/utils/extract-file-info.ts","../../src/core/message-transformer.ts","../../src/core/sessions/session-factory.ts","../../src/core/event-bus.ts","../../src/core/core.ts","../../src/core/sessions/session-store.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-storage.ts","../../src/core/plugin/plugin-context.ts","../../src/core/plugin/lifecycle-manager.ts","../../src/core/command-registry.ts"],"sourcesContent":["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","/**\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, 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 { 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 middlewareChain?: MiddlewareChain;\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 log.debug(\n { direction: \"send\", raw: chunk.toString().trimEnd() },\n \"ACP raw\",\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 log.debug(\n { direction: \"recv\", raw: chunk.toString().trimEnd() },\n \"ACP raw\",\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 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.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 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 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","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 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 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","import { nanoid } from \"nanoid\";\nimport type { AgentInstance } from \"../agents/agent-instance.js\";\nimport type { AgentCapabilities, AgentEvent, 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}\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 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.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\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 /** 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 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 { 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 { 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\n constructor(\n private session: Session,\n private adapter: IChannelAdapter,\n private deps: BridgeDeps,\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 if (!result) return;\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.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\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 // 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 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.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 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 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 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 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\n this.namedHandler = (name: string) => {\n this.deps.sessionManager.patchRecord(this.session.id, { name });\n this.deps.eventBus?.emit(\"session:updated\", {\n sessionId: this.session.id,\n name,\n });\n this.adapter.renameSessionThread(this.session.id, name);\n };\n this.session.on(\"named\", this.namedHandler);\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 _meta.claudeCode.toolResponse (Claude Code puts raw file data here)\n if (meta) {\n const m = meta as Record<string, unknown>\n const claudeCode = m?.claudeCode as Record<string, unknown> | undefined\n const tr = claudeCode?.toolResponse as Record<string, unknown> | undefined\n // Read tool: toolResponse.file.filePath + toolResponse.file.content\n const file = tr?.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 // Write/Edit tool: toolResponse.filePath + toolResponse.content (direct)\n if (!info && typeof tr?.filePath === 'string' && typeof tr?.content === 'string') {\n info = { filePath: tr.filePath, content: tr.content }\n }\n }\n\n // 2. Try rawInput for file path + content from regular 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 // Try to get content from the content field (including oldContent for diffs)\n const parsed = content ? parseContent(content) : null\n const riContent = typeof ri?.content === 'string' ? ri.content : undefined\n info = { filePath, content: parsed?.content || riContent, oldContent: parsed?.oldContent }\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\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\nexport class MessageTransformer {\n constructor(private tunnelService?: TunnelServiceInterface) {}\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 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 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: 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_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 private enrichWithViewerLinks(\n event: AgentEvent & { type: \"tool_call\" | \"tool_update\" },\n metadata: Record<string, unknown>,\n sessionContext?: { id: string; workingDirectory: string },\n ): void {\n if (!this.tunnelService || !sessionContext) return;\n\n const name = \"name\" in event ? event.name || \"\" : \"\";\n const kind = \"kind\" in event ? event.kind : undefined;\n\n log.debug(\n { name, kind, status: event.status, hasContent: !!event.content },\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) return;\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\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 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 { 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\n constructor(\n private agentManager: AgentManager,\n private sessionManager: SessionManager,\n private speechServiceAccessor: SpeechService | (() => SpeechService),\n private eventBus: EventBus,\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 const 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\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. 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 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 { 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\nexport class EventBus extends TypedEmitter<EventBusEvents> {}\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 { AgentCatalog } from \"./agents/agent-catalog.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 { ContextQuery, ContextOptions, ContextResult } from \"../plugins/context/context-provider.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 /** 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 private resumeLocks: Map<string, Promise<Session | null>> = new Map();\n eventBus: EventBus;\n sessionFactory: SessionFactory;\n readonly lifecycleManager: LifecycleManager;\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) {\n this.configManager = configManager;\n const config = configManager.get();\n this.agentCatalog = new AgentCatalog();\n this.agentCatalog.load();\n this.agentManager = new AgentManager(this.agentCatalog);\n const storePath = 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 );\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: path.join(os.homedir(), \".openacp\", \"plugins\", \"data\"),\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 // 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 = new MessageTransformer(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 for (const adapter of this.adapters.values()) {\n await adapter.start();\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; newThreadId: string } | { 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 old topic → create new topic\n const newThreadId = await adapter.archiveSessionTopic(session.id);\n\n // Rewire session to new topic\n session.threadId = newThreadId;\n\n // Update session store with new topic ID (best-effort — topic is already recreated)\n try {\n const platform: Record<string, unknown> = {};\n if (session.channelId === \"telegram\") {\n platform.topicId = Number(newThreadId);\n } else {\n platform.threadId = newThreadId;\n }\n await this.sessionManager.patchRecord(sessionId, { platform });\n } catch (patchErr) {\n log.warn({ err: patchErr, sessionId }, \"Failed to update session record after archive — session will work but may not survive restart\");\n }\n\n return { ok: true, newThreadId };\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\n let session = this.sessionManager.getSessionByThread(\n message.channelId,\n message.threadId,\n );\n\n // Lazy resume: try to restore session from store\n if (!session) {\n session = (await this.lazyResume(message)) ?? undefined;\n }\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. Connect SessionBridge\n if (adapter) {\n const bridge = this.createBridge(session, adapter);\n bridge.connect();\n }\n\n // 5b-5c. 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 // 6. Persist initial record\n // Preserve existing platform data (e.g. topicId) when resuming an existing session\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 });\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 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.createSession({\n channelId,\n agentName: resolvedAgent,\n workingDirectory: resolvedWorkspace,\n createThread: options?.createThread,\n });\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(\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 (e.g. after restart before lazy resume)\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 let contextResult: ContextResult | null = null;\n try {\n contextResult = await this.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 const session = await this.createSession({\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 // --- Lazy Resume ---\n\n /**\n * Get active session by thread, or attempt lazy resume from store.\n * Used by adapter command handlers that need a session but don't go through handleMessage().\n */\n async getOrResumeSession(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, userId: \"\", text: \"\" });\n }\n\n private async lazyResume(message: IncomingMessage): Promise<Session | null> {\n const store = this.sessionStore;\n if (!store) return null;\n\n const lockKey = `${message.channelId}:${message.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 message.channelId,\n (p) => String(p.topicId) === message.threadId,\n );\n if (!record) {\n log.debug(\n { threadId: message.threadId, channelId: message.channelId },\n \"No session record found for thread\",\n );\n return null;\n }\n\n // Don't resume errored or cancelled sessions\n if (record.status === \"error\" || record.status === \"cancelled\") {\n log.debug(\n {\n threadId: message.threadId,\n sessionId: record.sessionId,\n status: record.status,\n },\n \"Skipping resume of error session\",\n );\n return null;\n }\n\n log.info(\n {\n threadId: message.threadId,\n sessionId: record.sessionId,\n status: record.status,\n },\n \"Lazy resume: found record, attempting resume\",\n );\n\n const resumePromise = (async (): Promise<Session | null> => {\n try {\n const session = await this.createSession({\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: message.threadId,\n });\n session.activate();\n session.dangerousMode = record.dangerousMode ?? false;\n\n log.info(\n { sessionId: session.id, threadId: message.threadId },\n \"Lazy resume successful\",\n );\n return session;\n } catch (err) {\n log.error({ err, record }, \"Lazy resume failed\");\n // Send error feedback to user instead of silent drop\n const adapter = this.adapters.get(message.channelId);\n if (adapter) {\n try {\n await adapter.sendMessage(message.threadId, {\n type: \"error\",\n text: `⚠️ Failed to resume session: ${err instanceof Error ? err.message : String(err)}`,\n });\n } catch {\n /* best effort */\n }\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 // --- Event Wiring ---\n\n /** Create a SessionBridge for the given session and adapter */\n createBridge(session: Session, adapter: IChannelAdapter): SessionBridge {\n return 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 }\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 return [...this.records.values()].find(\n (r) =>\n r.agentSessionId === agentSessionId ||\n r.originalAgentSessionId === agentSessionId,\n );\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 { 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 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 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}\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\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 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 { 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}\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 private settingsManager: SettingsManager | undefined\n private pluginRegistry: PluginRegistry | 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 }\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 })\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"],"mappings":"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","names":["spawn","spawn","fs","log","fs","log","id","log","path","fs","path","log","path","fs","fs","path","log","log","path"]}
|