@openacp/cli 2026.327.5 → 2026.330.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-4U6MC5ZS.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-5VNYFWJE.js +7 -0
- package/dist/api-server-JLBDKCU4.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-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/{plugin-installer-QVJP6VKV.js → chunk-5WGVYX3C.js} +18 -5
- package/dist/chunk-5WGVYX3C.js.map +1 -0
- package/dist/{chunk-XWDW3XBE.js → chunk-5ZNBNIK3.js} +1331 -237
- package/dist/chunk-5ZNBNIK3.js.map +1 -0
- package/dist/{chunk-XIBG7LSL.js → chunk-7RKPIM3E.js} +482 -175
- package/dist/chunk-7RKPIM3E.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-2YCW3QDV.js → chunk-BTJHGSLM.js} +8 -7
- package/dist/chunk-BTJHGSLM.js.map +1 -0
- package/dist/{chunk-P2G275VD.js → chunk-CFUJGWOP.js} +3 -3
- package/dist/{chunk-RBYBSSGO.js → chunk-FCTC7KDT.js} +2 -2
- package/dist/{chunk-QAQDGPB4.js → chunk-GEOXPGCO.js} +3 -3
- package/dist/{chunk-BLQUXO7S.js → chunk-IZ5UEZF7.js} +27 -2
- package/dist/chunk-IZ5UEZF7.js.map +1 -0
- package/dist/{chunk-4GMLGCF2.js → chunk-KDU3ZEWT.js} +2 -2
- package/dist/{chunk-QWP76EBW.js → chunk-MITTQMGZ.js} +16 -9
- package/dist/chunk-MITTQMGZ.js.map +1 -0
- package/dist/{chunk-HRKAXFWR.js → chunk-MPGEHTGE.js} +9 -9
- package/dist/{chunk-KMMEFXIE.js → chunk-PA6MNBG4.js} +41 -9
- package/dist/chunk-PA6MNBG4.js.map +1 -0
- package/dist/{chunk-BQ6FR32N.js → chunk-QWVHCTCA.js} +2 -2
- 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-AD3X6DGK.js → chunk-TMVTSWVH.js} +75 -13
- package/dist/chunk-TMVTSWVH.js.map +1 -0
- package/dist/chunk-UWH7KIAA.js +701 -0
- package/dist/chunk-UWH7KIAA.js.map +1 -0
- package/dist/{chunk-SHTGQGAU.js → chunk-V2YZWYXT.js} +3 -3
- package/dist/{chunk-QVMEF6FB.js → chunk-W4LK6WJP.js} +38 -27
- package/dist/chunk-W4LK6WJP.js.map +1 -0
- package/dist/{chunk-S3ZGPPXY.js → chunk-YIGBJFJL.js} +9 -13
- package/dist/{chunk-S3ZGPPXY.js.map → chunk-YIGBJFJL.js.map} +1 -1
- package/dist/cli.js +133 -132
- package/dist/cli.js.map +1 -1
- package/dist/config-KN6NKKPF.js +20 -0
- package/dist/config-editor-76RVZS4B.js +10 -0
- package/dist/{config-registry-CUMNXFGK.js → config-registry-ZXAIJNYB.js} +2 -3
- package/dist/context-NXXW62NJ.js +9 -0
- package/dist/core-plugins-OCHKGCIZ.js +22 -0
- package/dist/{daemon-PXO5QPCR.js → daemon-XFEMMJSZ.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-AV6AUO22.js +9 -0
- package/dist/file-service-HHB3JQIO.js +8 -0
- package/dist/index.d.ts +141 -187
- package/dist/index.js +33 -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-3GF3EQTE.js → main-L2M4NTJY.js} +135 -50
- package/dist/main-L2M4NTJY.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-VSTYZSXC.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-A7VPW46C.js → setup-E6BNEYCS.js} +109 -83
- package/dist/setup-E6BNEYCS.js.map +1 -0
- package/dist/speech-SG62JYIF.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-EAVRDNFU.js +7 -0
- package/dist/tunnel-HWJ27WDH.js +7 -0
- package/dist/{tunnel-service-QJPUYEKU.js → tunnel-service-ZMO4THKE.js} +90 -11
- package/dist/tunnel-service-ZMO4THKE.js.map +1 -0
- 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-JQFQ3JAO.js +0 -15
- package/dist/adapter-UORRGHNH.js +0 -1030
- package/dist/adapter-UORRGHNH.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-32LVIEPW.js +0 -477
- package/dist/chunk-32LVIEPW.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-ODUM3D6X.js.map +0 -1
- package/dist/chunk-QVMEF6FB.js.map +0 -1
- package/dist/chunk-QWP76EBW.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/chunk-XWDW3XBE.js.map +0 -1
- package/dist/chunk-ZHGPZBS4.js +0 -49
- package/dist/chunk-ZHGPZBS4.js.map +0 -1
- package/dist/chunk-ZNSO2QVC.js +0 -124
- package/dist/chunk-ZNSO2QVC.js.map +0 -1
- package/dist/config-I4FMCJGZ.js +0 -15
- package/dist/config-editor-7PKW42GZ.js +0 -11
- package/dist/context-XM6E22LM.js +0 -10
- package/dist/core-plugins-Y5US6RED.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-3GF3EQTE.js.map +0 -1
- package/dist/notifications-D5BRDNSU.js +0 -9
- package/dist/plugin-installer-QVJP6VKV.js.map +0 -1
- package/dist/setup-A7VPW46C.js.map +0 -1
- package/dist/slack-2XNWBOWH.js +0 -8
- package/dist/speech-2GHQNRIO.js +0 -9
- package/dist/telegram-E65IWFBW.js +0 -8
- package/dist/tunnel-45HA72MB.js +0 -8
- package/dist/tunnel-service-QJPUYEKU.js.map +0 -1
- package/dist/version-NQZBM5M7.js.map +0 -1
- /package/dist/{adapter-JQFQ3JAO.js.map → adapter-4U6MC5ZS.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-5VNYFWJE.js.map} +0 -0
- /package/dist/{api-server-CAYNPUF2.js.map → api-server-JLBDKCU4.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-A6Y4GZM3.js.map → chunk-566W6INH.js.map} +0 -0
- /package/dist/{chunk-P2G275VD.js.map → chunk-CFUJGWOP.js.map} +0 -0
- /package/dist/{chunk-RBYBSSGO.js.map → chunk-FCTC7KDT.js.map} +0 -0
- /package/dist/{chunk-QAQDGPB4.js.map → chunk-GEOXPGCO.js.map} +0 -0
- /package/dist/{chunk-4GMLGCF2.js.map → chunk-KDU3ZEWT.js.map} +0 -0
- /package/dist/{chunk-HRKAXFWR.js.map → chunk-MPGEHTGE.js.map} +0 -0
- /package/dist/{chunk-BQ6FR32N.js.map → chunk-QWVHCTCA.js.map} +0 -0
- /package/dist/{chunk-SHTGQGAU.js.map → chunk-V2YZWYXT.js.map} +0 -0
- /package/dist/{chunk-VUNV25KB.js.map → config-KN6NKKPF.js.map} +0 -0
- /package/dist/{config-I4FMCJGZ.js.map → config-editor-76RVZS4B.js.map} +0 -0
- /package/dist/{config-editor-7PKW42GZ.js.map → config-registry-ZXAIJNYB.js.map} +0 -0
- /package/dist/{config-registry-CUMNXFGK.js.map → context-NXXW62NJ.js.map} +0 -0
- /package/dist/{context-XM6E22LM.js.map → core-plugins-OCHKGCIZ.js.map} +0 -0
- /package/dist/{core-plugins-Y5US6RED.js.map → daemon-XFEMMJSZ.js.map} +0 -0
- /package/dist/{daemon-PXO5QPCR.js.map → doctor-AV6AUO22.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-VSTYZSXC.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-2XNWBOWH.js.map → speech-SG62JYIF.js.map} +0 -0
- /package/dist/{speech-2GHQNRIO.js.map → telegram-EAVRDNFU.js.map} +0 -0
- /package/dist/{telegram-E65IWFBW.js.map → tunnel-HWJ27WDH.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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/slack/adapter.ts","../../src/plugins/slack/utils.ts","../../src/plugins/slack/formatter.ts","../../src/plugins/slack/renderer.ts","../../src/plugins/slack/send-queue.ts","../../src/plugins/slack/slug.ts","../../src/plugins/slack/channel-manager.ts","../../src/plugins/slack/permission-handler.ts","../../src/plugins/slack/event-router.ts","../../src/plugins/slack/text-buffer.ts"],"sourcesContent":["// src/adapters/slack/adapter.ts\nimport fs from \"node:fs\";\nimport { App } from \"@slack/bolt\";\nimport { WebClient } from \"@slack/web-api\";\nimport type { OpenACPCore } from \"../../core/core.js\";\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n Attachment,\n} from \"../../core/types.js\";\nimport type { AdapterCapabilities } from \"../../core/channel.js\";\nimport type { FileServiceInterface } from \"../../core/plugin/types.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nimport { MessagingAdapter, type MessagingAdapterConfig } from \"../../core/adapter-primitives/messaging-adapter.js\";\nimport type { DisplayVerbosity } from \"../../core/adapter-primitives/format-types.js\";\nimport type { IRenderer } from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport { SlackRenderer } from \"./renderer.js\";\nconst log = createChildLogger({ module: \"slack\" });\n\nimport type { SlackChannelConfig } from \"./types.js\";\nimport type { SlackSessionMeta, SlackFileInfo } from \"./types.js\";\nimport { SlackSendQueue } from \"./send-queue.js\";\nimport { SlackFormatter } from \"./formatter.js\";\nimport { SlackChannelManager } from \"./channel-manager.js\";\nimport { SlackPermissionHandler } from \"./permission-handler.js\";\nimport { SlackEventRouter } from \"./event-router.js\";\nimport { SlackTextBuffer } from \"./text-buffer.js\";\nimport { toSlug } from \"./slug.js\";\nimport { isAudioClip } from \"./utils.js\";\n\nexport class SlackAdapter extends MessagingAdapter {\n readonly name = 'slack';\n readonly renderer!: IRenderer;\n readonly capabilities: AdapterCapabilities = {\n streaming: true, richFormatting: true, threads: true,\n reactions: false, fileUpload: true, voice: true,\n };\n\n private core: OpenACPCore;\n private app!: App;\n private webClient!: WebClient;\n private queue!: SlackSendQueue;\n private formatter: SlackFormatter;\n private channelManager!: SlackChannelManager;\n private permissionHandler!: SlackPermissionHandler;\n private eventRouter!: SlackEventRouter;\n private sessions = new Map<string, SlackSessionMeta>();\n private textBuffers = new Map<string, SlackTextBuffer>();\n private botUserId = \"\";\n private slackConfig: SlackChannelConfig;\n private fileService!: FileServiceInterface;\n\n constructor(core: OpenACPCore, config: SlackChannelConfig) {\n super(\n { configManager: core.configManager },\n { ...config as Record<string, unknown>, maxMessageLength: 3000, enabled: config.enabled ?? true } as MessagingAdapterConfig,\n );\n this.core = core;\n this.slackConfig = config;\n this.formatter = new SlackFormatter();\n (this as { renderer: IRenderer }).renderer = new SlackRenderer(this.formatter);\n }\n\n async start(): Promise<void> {\n const { botToken, appToken, signingSecret } = this.slackConfig;\n\n if (!botToken || !appToken || !signingSecret) {\n throw new Error(\"Slack adapter requires botToken, appToken, and signingSecret\");\n }\n\n this.app = new App({\n token: botToken,\n appToken,\n signingSecret,\n socketMode: true,\n });\n\n this.webClient = new WebClient(botToken);\n this.queue = new SlackSendQueue(this.webClient);\n this.fileService = this.core.fileService;\n\n // Resolve bot user ID — required to filter bot's own messages (prevent infinite loop)\n const authResult = await this.webClient.auth.test();\n if (!authResult.user_id) {\n throw new Error(\"Slack auth.test() did not return user_id — verify botToken is valid\");\n }\n this.botUserId = authResult.user_id as string;\n log.info({ botUserId: this.botUserId }, \"Slack bot authenticated\");\n\n this.channelManager = new SlackChannelManager(this.queue, this.slackConfig);\n\n // Permission handler — resolve permission gate when user clicks a button\n this.permissionHandler = new SlackPermissionHandler(\n this.queue,\n (requestId, optionId) => {\n for (const [sessionId, _meta] of this.sessions) {\n const session = this.core.sessionManager.getSession(sessionId);\n if (session && session.permissionGate.requestId === requestId) {\n session.permissionGate.resolve(optionId);\n log.info({ sessionId, requestId, optionId }, \"Permission resolved\");\n return;\n }\n }\n log.warn({ requestId, optionId }, \"No matching session found for permission response\");\n },\n );\n this.permissionHandler.register(this.app);\n\n // Event router — dispatch incoming messages from session channels to core\n this.eventRouter = new SlackEventRouter(\n (slackChannelId) => {\n for (const meta of this.sessions.values()) {\n if (meta.channelId === slackChannelId) return meta;\n }\n return undefined;\n },\n (sessionChannelSlug, text, userId, files) => {\n const processFiles = async (): Promise<Attachment[] | undefined> => {\n if (!files?.length) return undefined;\n const audioFiles = files.filter((f) => isAudioClip(f));\n if (!audioFiles.length) return undefined;\n\n const attachments: Attachment[] = [];\n for (const file of audioFiles) {\n const buffer = await this.downloadSlackFile(file.url_private);\n if (!buffer) continue;\n const mimeType = file.mimetype === \"video/mp4\" ? \"audio/mp4\" : file.mimetype;\n const sessionId = this.core.sessionManager.getSessionByThread(\"slack\", sessionChannelSlug)?.id;\n if (!sessionId) continue;\n const att = await this.fileService.saveFile(sessionId, file.name, buffer, mimeType);\n attachments.push(att);\n }\n return attachments.length > 0 ? attachments : undefined;\n };\n\n processFiles()\n .then((attachments) => {\n this.core\n .handleMessage({\n channelId: \"slack\",\n threadId: sessionChannelSlug,\n userId,\n text,\n attachments,\n })\n .catch((err) => log.error({ err }, \"handleMessage error\"));\n })\n .catch((err) => log.error({ err }, \"Failed to process audio files\"));\n },\n this.botUserId,\n this.slackConfig.notificationChannelId,\n // onNewSession: reply with guidance when user messages the notification channel\n async (_text, _userId) => {\n if (this.slackConfig.notificationChannelId) {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: this.slackConfig.notificationChannelId,\n text: \"💬 To start a new session, use the `/openacp-new` slash command in any channel.\",\n }).catch((err: unknown) => log.warn({ err }, \"Failed to send onNewSession reply\"));\n }\n },\n this.slackConfig,\n this.core.configManager.get().security.allowedUserIds,\n );\n this.eventRouter.register(this.app);\n\n // Start Bolt (Socket Mode)\n await this.app.start();\n log.info(\"Slack adapter started (Socket Mode)\");\n\n // Create startup session + channel (configurable — set autoCreateSession: false to skip)\n if (this.slackConfig.autoCreateSession !== false) {\n await this._createStartupSession();\n }\n }\n\n private async downloadSlackFile(url: string): Promise<Buffer | null> {\n try {\n const resp = await fetch(url, {\n headers: { Authorization: `Bearer ${this.slackConfig.botToken}` },\n });\n if (!resp.ok) {\n log.warn({ status: resp.status }, \"Failed to download Slack file\");\n return null;\n }\n // Slack returns 200 with HTML login page if bot lacks files:read scope\n const contentType = resp.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"text/html\")) {\n log.warn(\"Slack file download returned HTML instead of binary — bot likely missing files:read scope. Reinstall the Slack app with files:read scope.\");\n return null;\n }\n return Buffer.from(await resp.arrayBuffer());\n } catch (err) {\n log.error({ err }, \"Error downloading Slack file\");\n return null;\n }\n }\n\n private async uploadAudioFile(channelId: string, att: Attachment): Promise<void> {\n const fileBuffer = await fs.promises.readFile(att.filePath);\n await this.webClient.files.uploadV2({\n channel_id: channelId,\n file: fileBuffer,\n filename: att.fileName,\n });\n }\n\n private async _createStartupSession(): Promise<void> {\n try {\n let reuseChannelId = this.slackConfig.startupChannelId;\n\n // Try to reuse existing startup channel (Telegram ensureTopics pattern)\n if (reuseChannelId) {\n try {\n const info = await this.queue.enqueue<Record<string, unknown>>(\n \"conversations.info\", { channel: reuseChannelId },\n );\n const channel = (info as Record<string, unknown>)?.channel as Record<string, unknown> | undefined;\n if (!channel || typeof channel.is_archived !== \"boolean\") {\n log.warn({ reuseChannelId }, \"Unexpected conversations.info response shape, creating new channel\");\n reuseChannelId = undefined;\n } else if (channel.is_archived) {\n await this.queue.enqueue(\"conversations.unarchive\", { channel: reuseChannelId });\n log.info({ channelId: reuseChannelId }, \"Unarchived startup channel for reuse\");\n }\n } catch {\n // Channel deleted or inaccessible — will create new\n reuseChannelId = undefined;\n }\n }\n\n if (reuseChannelId) {\n // Reuse existing channel — create session pointing to it\n let hasSession = false;\n for (const m of this.sessions.values()) {\n if (m.channelId === reuseChannelId) { hasSession = true; break; }\n }\n if (!hasSession) {\n const session = await this.core.handleNewSession(\"slack\", undefined, undefined, { createThread: false });\n const slug = `startup-${session.id.slice(0, 8)}`;\n this.sessions.set(session.id, { channelId: reuseChannelId, channelSlug: slug });\n session.threadId = slug;\n // Persist slug to session store so session resume after restart can find it\n await this.core.sessionManager.patchRecord(session.id, {\n platform: { topicId: slug },\n });\n log.info({ sessionId: session.id, channelId: reuseChannelId }, \"Reused startup channel\");\n }\n } else {\n // Create new channel + session\n const session = await this.core.handleNewSession(\"slack\", undefined, undefined, { createThread: true });\n if (!session.threadId) {\n log.error({ sessionId: session.id }, \"Startup session created without threadId\");\n return;\n }\n\n // Persist channel ID to config for reuse on next restart\n const meta = this.sessions.get(session.id);\n if (meta) {\n await this.core.configManager.save(\n { channels: { slack: { startupChannelId: meta.channelId } } },\n );\n log.info({ sessionId: session.id, channelId: meta.channelId }, \"Saved startup channel to config\");\n }\n }\n\n // Notify\n if (this.slackConfig.notificationChannelId) {\n const startupMeta = [...this.sessions.values()].find(m =>\n m.channelId === (reuseChannelId ?? this.slackConfig.startupChannelId)\n );\n if (startupMeta) {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: this.slackConfig.notificationChannelId,\n text: `✅ OpenACP ready — chat with the agent in <#${startupMeta.channelId}>`,\n });\n }\n }\n } catch (err) {\n log.error({ err }, \"Failed to create/reuse Slack startup session\");\n }\n }\n\n async stop(): Promise<void> {\n // Flush all active text buffers before stopping to prevent data loss\n for (const [sessionId, buf] of this.textBuffers) {\n try {\n await buf.flush();\n } catch (err) {\n log.warn({ err, sessionId }, \"Flush failed during stop\");\n }\n buf.destroy();\n }\n this.textBuffers.clear();\n await this.app.stop();\n log.info(\"Slack adapter stopped\");\n }\n\n // --- MessagingAdapter implementations ---\n\n async createSessionThread(sessionId: string, name: string): Promise<string> {\n const meta = await this.channelManager.createChannel(sessionId, name);\n this.sessions.set(sessionId, meta);\n log.info({ sessionId, channelId: meta.channelId, slug: meta.channelSlug }, \"Session channel created\");\n // Return the slug as the threadId so that lookups via getSessionByThread work\n return meta.channelSlug;\n }\n\n async renameSessionThread(sessionId: string, newName: string): Promise<void> {\n const meta = this.sessions.get(sessionId);\n if (!meta) return;\n\n const newSlug = toSlug(newName, this.slackConfig.channelPrefix ?? \"openacp\");\n\n try {\n await this.queue.enqueue(\"conversations.rename\", {\n channel: meta.channelId,\n name: newSlug,\n });\n meta.channelSlug = newSlug;\n // Update session.threadId so getSessionByThread() keeps working after rename\n const session = this.core.sessionManager.getSession(sessionId);\n if (session) session.threadId = newSlug;\n const existingRecord = this.core.sessionManager.getSessionRecord(sessionId);\n await this.core.sessionManager.patchRecord(sessionId, {\n name: newName,\n platform: { ...(existingRecord?.platform ?? {}), topicId: newSlug },\n });\n log.info({ sessionId, newSlug }, \"Session channel renamed\");\n } catch (err) {\n log.warn({ err, sessionId }, \"Failed to rename Slack channel\");\n }\n }\n\n async deleteSessionThread(sessionId: string): Promise<void> {\n const meta = this.sessions.get(sessionId);\n if (!meta) return;\n\n try {\n await this.permissionHandler.cleanupSession(meta.channelId);\n } catch (err) {\n log.warn({ err, sessionId }, \"Failed to clean up permission buttons\");\n }\n\n try {\n await this.channelManager.archiveChannel(meta.channelId);\n log.info({ sessionId, channelId: meta.channelId }, \"Session channel archived\");\n } catch (err) {\n log.warn({ err, sessionId }, \"Failed to archive Slack channel\");\n }\n this.sessions.delete(sessionId);\n const buf = this.textBuffers.get(sessionId);\n if (buf) { buf.destroy(); this.textBuffers.delete(sessionId); }\n }\n\n private _sessionMetas = new Map<string, SlackSessionMeta>();\n\n private getSessionMeta(sessionId: string): SlackSessionMeta | undefined {\n return this._sessionMetas.get(sessionId);\n }\n\n private getTextBuffer(sessionId: string, channelId: string): SlackTextBuffer {\n let buf = this.textBuffers.get(sessionId);\n if (!buf) {\n buf = new SlackTextBuffer(channelId, sessionId, this.queue);\n this.textBuffers.set(sessionId, buf);\n }\n return buf;\n }\n\n async sendMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.sessions.get(sessionId);\n if (!meta) {\n log.warn({ sessionId }, \"No Slack channel for session, skipping message\");\n return;\n }\n\n // Store meta per-session so concurrent calls for different sessions don't overwrite each other\n this._sessionMetas.set(sessionId, meta);\n try {\n await super.sendMessage(sessionId, content);\n } finally {\n this._sessionMetas.delete(sessionId);\n }\n }\n\n // --- Handler overrides (dispatched by base class) ---\n\n protected async handleText(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.getSessionMeta(sessionId);\n if (!meta) return;\n // Text chunks are buffered and flushed as a single message after idle timeout\n const buf = this.getTextBuffer(sessionId, meta.channelId);\n buf.append(content.text ?? \"\");\n }\n\n protected async handleSessionEnd(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.getSessionMeta(sessionId);\n if (!meta) return;\n // Flush any pending text first\n await this.flushTextBuffer(sessionId);\n\n const blocks = this.formatter.formatOutgoing(content);\n if (blocks.length === 0) return;\n\n try {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: meta.channelId,\n text: content.text ?? content.type,\n blocks,\n });\n } catch (err) {\n log.error({ err, sessionId, type: content.type }, \"Failed to post Slack message\");\n }\n }\n\n protected async handleError(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.getSessionMeta(sessionId);\n if (!meta) return;\n // Flush any pending text first\n await this.flushTextBuffer(sessionId);\n\n const blocks = this.formatter.formatOutgoing(content);\n if (blocks.length === 0) return;\n\n try {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: meta.channelId,\n text: content.text ?? content.type,\n blocks,\n });\n } catch (err) {\n log.error({ err, sessionId, type: content.type }, \"Failed to post Slack message\");\n }\n }\n\n protected async handleAttachment(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.getSessionMeta(sessionId);\n if (!meta || !content.attachment) return;\n if (content.attachment.type === \"audio\") {\n try {\n await this.uploadAudioFile(meta.channelId, content.attachment);\n const buf = this.textBuffers.get(sessionId);\n if (buf) await buf.stripTtsBlock();\n } catch (err) {\n log.error({ err, sessionId }, \"Failed to upload audio to Slack\");\n }\n }\n }\n\n protected async handleThought(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n protected async handleToolCall(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n protected async handleToolUpdate(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n protected async handlePlan(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n protected async handleUsage(sessionId: string, content: OutgoingMessage, _verbosity: DisplayVerbosity): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n protected async handleSystem(sessionId: string, content: OutgoingMessage): Promise<void> {\n await this.postFormattedMessage(sessionId, content);\n }\n\n // --- Private helpers ---\n\n private async flushTextBuffer(sessionId: string): Promise<void> {\n const buf = this.textBuffers.get(sessionId);\n if (buf) {\n try {\n await buf.flush();\n } catch (err) {\n log.warn({ err, sessionId }, \"Flush failed on session_end\");\n }\n buf.destroy();\n this.textBuffers.delete(sessionId);\n }\n }\n\n private async postFormattedMessage(sessionId: string, content: OutgoingMessage): Promise<void> {\n const meta = this.getSessionMeta(sessionId);\n if (!meta) return;\n const blocks = this.formatter.formatOutgoing(content);\n if (blocks.length === 0) return;\n\n try {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: meta.channelId,\n text: content.text ?? content.type,\n blocks,\n });\n } catch (err) {\n log.error({ err, sessionId, type: content.type }, \"Failed to post Slack message\");\n }\n }\n\n // NOTE: Async flow — different from Telegram adapter.\n // Telegram: sendPermissionRequest awaits user response inline.\n // Slack: posts interactive buttons and returns immediately.\n // Resolution happens asynchronously via the Bolt action handler in\n // SlackPermissionHandler, which calls the PermissionResponseCallback\n // passed during construction. The callback iterates sessions to find\n // the matching permissionGate and resolves it.\n async sendPermissionRequest(\n sessionId: string,\n request: PermissionRequest,\n ): Promise<void> {\n const meta = this.sessions.get(sessionId);\n if (!meta) return;\n\n log.info({ sessionId, requestId: request.id }, \"Sending Slack permission request\");\n const blocks = this.formatter.formatPermissionRequest(request);\n\n try {\n const result = await this.queue.enqueue(\"chat.postMessage\", {\n channel: meta.channelId,\n text: `Permission request: ${request.description}`,\n blocks,\n });\n const ts = (result as { ts?: string })?.ts;\n if (ts) {\n this.permissionHandler.trackPendingMessage(request.id, meta.channelId, ts);\n }\n } catch (err) {\n log.error({ err, sessionId }, \"Failed to post Slack permission request\");\n }\n }\n\n async sendNotification(notification: NotificationMessage): Promise<void> {\n if (!this.slackConfig.notificationChannelId) return;\n\n const emoji: Record<string, string> = {\n completed: \"✅\",\n error: \"❌\",\n permission: \"🔐\",\n input_required: \"💬\",\n };\n const icon = emoji[notification.type] ?? \"ℹ️\";\n const text = `${icon} *${notification.sessionName ?? \"Session\"}*\\n${notification.summary}`;\n const blocks = this.formatter.formatNotification(text);\n\n try {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: this.slackConfig.notificationChannelId,\n text,\n blocks,\n });\n } catch (err) {\n log.warn({ err, sessionId: notification.sessionId }, \"Failed to send Slack notification\");\n }\n }\n}\n\nexport type { SlackChannelConfig } from \"./types.js\";\n","// src/adapters/slack/utils.ts\n// Shared utilities for Slack adapter modules.\n\nimport type { SlackFileInfo } from \"./types.js\";\n\n/** Detect Slack audio clips — MIME type or filename pattern */\nexport function isAudioClip(file: SlackFileInfo): boolean {\n return (file.mimetype === \"video/mp4\" && file.name?.startsWith(\"audio_message\")) ||\n file.mimetype?.startsWith(\"audio/\");\n}\n\nconst SECTION_LIMIT = 3000;\n\n/**\n * Split text at nearest newline boundary before `limit`.\n * Does NOT track code fence state — a triple-backtick block straddling\n * the boundary will be split mid-block.\n * Used by SlackFormatter and SlackTextBuffer to avoid exceeding Slack's\n * 3000-char section limit.\n */\nexport function splitSafe(text: string, limit = SECTION_LIMIT): string[] {\n if (text.length <= limit) return [text];\n const chunks: string[] = [];\n let remaining = text;\n while (remaining.length > 0) {\n if (remaining.length <= limit) { chunks.push(remaining); break; }\n let cut = remaining.lastIndexOf(\"\\n\", limit);\n if (cut <= 0) cut = limit;\n chunks.push(remaining.slice(0, cut));\n remaining = remaining.slice(cut).trimStart();\n }\n return chunks;\n}\n","// src/adapters/slack/formatter.ts\nimport type { types } from \"@slack/bolt\";\nimport type { OutgoingMessage, PermissionRequest } from \"../../core/types.js\";\nimport { splitSafe } from \"./utils.js\";\n\ntype KnownBlock = types.KnownBlock;\n\nexport interface ISlackFormatter {\n formatOutgoing(message: OutgoingMessage): KnownBlock[];\n formatPermissionRequest(req: PermissionRequest): KnownBlock[];\n formatNotification(text: string): KnownBlock[];\n formatSessionEnd(reason?: string): KnownBlock[];\n}\n\n/**\n * Convert a markdown string to Slack mrkdwn format.\n * Handles the most common patterns from AI responses.\n */\nexport function markdownToMrkdwn(text: string): string {\n return text\n // Fenced code blocks — preserve as-is (Slack supports ``` natively)\n // Headers: # H1 → placeholder (protected from italic regex)\n .replace(/^#{1,6}\\s+(.+)$/gm, \"\\x00BOLD\\x00$1\\x00BOLD\\x00\")\n // Bold: **text** → placeholder\n .replace(/\\*\\*(.+?)\\*\\*/g, \"\\x00BOLD\\x00$1\\x00BOLD\\x00\")\n // Italic: *text* → _text_ (won't match placeholder tokens)\n .replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, \"_$1_\")\n // Restore bold/header placeholders → *text*\n .replace(/\\x00BOLD\\x00(.+?)\\x00BOLD\\x00/g, \"*$1*\")\n // Inline code: `code` — kept as-is (Slack supports backtick)\n // Strikethrough: ~~text~~ → ~text~\n .replace(/~~(.+?)~~/g, \"~$1~\")\n // Links: [text](url) → <url|text>\n .replace(/\\[([^\\]]+)\\]\\((https?:\\/\\/[^)]+)\\)/g, \"<$2|$1>\")\n // Unordered lists: \"- item\" or \"* item\" → \"• item\"\n .replace(/^[ \\t]*[-*]\\s+/gm, \"• \")\n // Ordered lists: \"1. item\" → \"1. item\" (already fine in mrkdwn)\n .trim();\n}\n\n// Slack mrkdwn text block, max 3000 chars per section\nconst SECTION_LIMIT = 3000;\n\nfunction section(text: string): KnownBlock {\n return { type: \"section\", text: { type: \"mrkdwn\", text: text.slice(0, SECTION_LIMIT) } };\n}\n\nfunction context(text: string): KnownBlock {\n return { type: \"context\", elements: [{ type: \"mrkdwn\", text }] };\n}\n\nexport class SlackFormatter implements ISlackFormatter {\n formatOutgoing(message: OutgoingMessage): KnownBlock[] {\n switch (message.type) {\n case \"text\": {\n const text = message.text ?? \"\";\n if (!text.trim()) return [];\n const converted = markdownToMrkdwn(text);\n return splitSafe(converted).map(chunk => section(chunk));\n }\n\n case \"thought\":\n return [context(`💭 _${(message.text ?? \"\").slice(0, 500)}_`)];\n\n case \"tool_call\": {\n const name = (message as OutgoingMessage & { metadata?: { name?: string; input?: unknown } }).metadata?.name ?? \"tool\";\n const input = (message as OutgoingMessage & { metadata?: { input?: unknown } }).metadata?.input;\n const inputStr = input ? `\\n\\`\\`\\`\\n${JSON.stringify(input, null, 2).slice(0, 500)}\\n\\`\\`\\`` : \"\";\n return [context(`🔧 \\`${name}\\`${inputStr}`)];\n }\n\n case \"tool_update\": {\n const name = (message as OutgoingMessage & { metadata?: { name?: string; status?: string } }).metadata?.name ?? \"tool\";\n const status = (message as OutgoingMessage & { metadata?: { status?: string } }).metadata?.status ?? \"done\";\n const icon = status === \"error\" ? \"❌\" : \"✅\";\n return [context(`${icon} \\`${name}\\` — ${status}`)];\n }\n\n case \"plan\":\n return [\n { type: \"divider\" },\n section(`📋 *Plan*\\n${message.text ?? \"\"}`),\n ];\n\n case \"usage\": {\n const meta = (message as OutgoingMessage & { metadata?: { input_tokens?: number; output_tokens?: number; cost_usd?: number } }).metadata ?? {};\n const parts = [\n meta.input_tokens != null ? `in: ${meta.input_tokens}` : null,\n meta.output_tokens != null ? `out: ${meta.output_tokens}` : null,\n meta.cost_usd != null ? `$${Number(meta.cost_usd).toFixed(4)}` : null,\n ].filter((p): p is string => p !== null);\n return parts.length ? [context(`📊 ${parts.join(\" · \")}`)] : [];\n }\n\n case \"session_end\":\n return this.formatSessionEnd(message.text);\n\n case \"error\":\n return [section(`⚠️ *Error:* ${message.text ?? \"Unknown error\"}`)];\n\n default:\n return [];\n }\n }\n\n formatPermissionRequest(req: PermissionRequest): KnownBlock[] {\n return [\n section(`🔐 *Permission Request*\\n${req.description}`),\n {\n type: \"actions\",\n block_id: `perm_${req.id}`,\n elements: req.options.map(opt => ({\n type: \"button\" as const,\n text: { type: \"plain_text\" as const, text: opt.label, emoji: true },\n value: `${req.id}:${opt.id}`,\n action_id: `perm_action_${opt.id}_${req.id}`,\n style: (opt.isAllow ? \"primary\" : \"danger\") as \"primary\" | \"danger\",\n })),\n } as KnownBlock,\n ];\n }\n\n formatNotification(text: string): KnownBlock[] {\n return [section(text)];\n }\n\n formatSessionEnd(reason?: string): KnownBlock[] {\n return [\n { type: \"divider\" },\n context(`✅ Session ended${reason ? ` — ${reason}` : \"\"}`),\n ];\n }\n}\n","import { BaseRenderer } from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport type {\n RenderedMessage,\n RenderedPermission,\n} from \"../../core/adapter-primitives/rendering/renderer.js\";\nimport type {\n OutgoingMessage,\n PermissionRequest,\n NotificationMessage,\n} from \"../../core/types.js\";\nimport type { DisplayVerbosity } from \"../../core/adapter-primitives/format-types.js\";\nimport { SlackFormatter, markdownToMrkdwn } from \"./formatter.js\";\n\n/**\n * SlackRenderer — renders messages as Slack Block Kit structures.\n * Delegates to the existing SlackFormatter for block generation,\n * wrapping results into RenderedMessage with format: 'structured'.\n */\nexport class SlackRenderer extends BaseRenderer {\n private formatter: SlackFormatter;\n\n constructor(formatter?: SlackFormatter) {\n super();\n this.formatter = formatter ?? new SlackFormatter();\n }\n\n renderText(content: OutgoingMessage): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderThought(\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderToolCall(\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderToolUpdate(\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderPlan(content: OutgoingMessage): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderUsage(\n content: OutgoingMessage,\n _verbosity: DisplayVerbosity,\n ): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderError(content: OutgoingMessage): RenderedMessage {\n const blocks = this.formatter.formatOutgoing(content);\n return {\n body: content.text ?? \"\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderSessionEnd(content: OutgoingMessage): RenderedMessage {\n const blocks = this.formatter.formatSessionEnd(content.text);\n return {\n body: content.text ?? \"Session ended\",\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderPermission(request: PermissionRequest): RenderedPermission {\n const blocks = this.formatter.formatPermissionRequest(request);\n return {\n body: request.description,\n format: \"structured\",\n components: blocks,\n actions: request.options.map((o) => ({\n id: o.id,\n label: o.label,\n isAllow: o.isAllow,\n })),\n };\n }\n\n renderNotification(notification: NotificationMessage): RenderedMessage {\n const emoji: Record<string, string> = {\n completed: \"✅\",\n error: \"❌\",\n permission: \"🔐\",\n input_required: \"💬\",\n budget_warning: \"⚠️\",\n };\n const icon = emoji[notification.type] || \"ℹ️\";\n const text = `${icon} *${notification.sessionName ?? \"Session\"}*\\n${notification.summary}`;\n const blocks = this.formatter.formatNotification(text);\n return {\n body: text,\n format: \"structured\",\n components: blocks,\n };\n }\n\n renderSystemMessage(content: OutgoingMessage): RenderedMessage {\n const mrkdwn = markdownToMrkdwn(content.text ?? \"\");\n return {\n body: mrkdwn,\n format: \"structured\",\n components: [\n {\n type: \"section\" as const,\n text: { type: \"mrkdwn\" as const, text: mrkdwn },\n },\n ],\n };\n }\n\n renderModeChange(content: OutgoingMessage): RenderedMessage {\n const modeId = (content.metadata as Record<string, unknown>)?.modeId ?? \"\";\n const text = `🔄 *Mode:* ${modeId}`;\n return {\n body: text,\n format: \"structured\",\n components: [\n {\n type: \"context\" as const,\n elements: [{ type: \"mrkdwn\" as const, text }],\n },\n ],\n };\n }\n\n renderConfigUpdate(): RenderedMessage {\n const text = \"⚙️ *Config updated*\";\n return {\n body: text,\n format: \"structured\",\n components: [\n {\n type: \"context\" as const,\n elements: [{ type: \"mrkdwn\" as const, text }],\n },\n ],\n };\n }\n\n renderModelUpdate(content: OutgoingMessage): RenderedMessage {\n const modelId =\n (content.metadata as Record<string, unknown>)?.modelId ?? \"\";\n const text = `🤖 *Model:* ${modelId}`;\n return {\n body: text,\n format: \"structured\",\n components: [\n {\n type: \"context\" as const,\n elements: [{ type: \"mrkdwn\" as const, text }],\n },\n ],\n };\n }\n}\n","import PQueue from \"p-queue\";\nimport type { WebClient } from \"@slack/web-api\";\n\nexport type SlackMethod =\n | \"chat.postMessage\"\n | \"chat.update\"\n | \"conversations.create\"\n | \"conversations.rename\"\n | \"conversations.archive\"\n | \"conversations.invite\"\n | \"conversations.join\"\n | \"conversations.unarchive\"\n | \"conversations.info\";\n\n// Requests per minute per method (Slack Tier definitions)\nconst METHOD_RPM: Record<SlackMethod, number> = {\n \"chat.postMessage\": 50, // Tier 3\n \"chat.update\": 50, // Tier 3\n \"conversations.create\": 20, // Tier 2\n \"conversations.rename\": 20, // Tier 2\n \"conversations.archive\": 20, // Tier 2\n \"conversations.invite\": 20, // Tier 2\n \"conversations.join\": 20, // Tier 2\n \"conversations.unarchive\": 20, // Tier 2\n \"conversations.info\": 50, // Tier 3\n};\n\nexport interface ISlackSendQueue {\n enqueue<T = unknown>(method: SlackMethod, params: Record<string, unknown>): Promise<T>;\n}\n\nexport class SlackSendQueue implements ISlackSendQueue {\n private queues = new Map<SlackMethod, PQueue>();\n\n constructor(private client: WebClient) {\n for (const [method, rpm] of Object.entries(METHOD_RPM) as [SlackMethod, number][]) {\n // Spread requests evenly across the minute\n this.queues.set(method, new PQueue({\n interval: Math.ceil(60_000 / rpm),\n intervalCap: 1,\n carryoverConcurrencyCount: true,\n }));\n }\n }\n\n async enqueue<T = unknown>(method: SlackMethod, params: Record<string, unknown>): Promise<T> {\n const queue = this.queues.get(method);\n if (!queue) throw new Error(`Unknown Slack method: ${method}`);\n return queue.add(() => this.client.apiCall(method, params) as Promise<T>);\n }\n}\n","// src/adapters/slack/slug.ts\nimport { customAlphabet } from \"nanoid\";\n\nconst nanoidAlpha = customAlphabet(\"abcdefghijklmnopqrstuvwxyz0123456789\", 4);\n\n/**\n * Convert a human-readable session name to a valid Slack channel name.\n * Rules: lowercase, ≤80 chars, only [a-z0-9-], unique suffix appended.\n *\n * Examples:\n * \"Fix authentication bug\" → \"openacp-fix-authentication-bug-a3k9\"\n * \"New Session\" → \"openacp-new-session-x7p2\"\n * \"Implement OAuth 2.0 & JWT refresh\" → \"openacp-implement-oauth-20-jwt-refresh-b8qr\"\n */\nexport function toSlug(name: string, prefix = \"openacp\"): string {\n const base = name\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\") // strip special chars\n .trim()\n .replace(/\\s+/g, \"-\") // spaces → dashes\n .replace(/-+/g, \"-\") // collapse consecutive dashes\n .slice(0, 60); // leave room for prefix and suffix\n\n const suffix = nanoidAlpha();\n return `${prefix}-${base}-${suffix}`.replace(/-+/g, \"-\");\n}\n","// src/adapters/slack/channel-manager.ts\nimport type { ISlackSendQueue } from \"./send-queue.js\";\nimport { toSlug } from \"./slug.js\";\nimport type { SlackSessionMeta } from \"./types.js\";\nimport type { SlackChannelConfig } from \"./types.js\";\n\nexport interface ISlackChannelManager {\n createChannel(sessionId: string, sessionName: string): Promise<SlackSessionMeta>;\n archiveChannel(channelId: string): Promise<void>;\n notifyChannel(text: string): Promise<void>;\n}\n\nexport class SlackChannelManager implements ISlackChannelManager {\n constructor(\n private queue: ISlackSendQueue,\n private config: SlackChannelConfig,\n ) {}\n\n async createChannel(sessionId: string, sessionName: string): Promise<SlackSessionMeta> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const finalSlug = toSlug(sessionName, this.config.channelPrefix ?? \"openacp\");\n\n try {\n const res = await this.queue.enqueue<{ channel: { id: string } }>(\n \"conversations.create\",\n { name: finalSlug, is_private: true },\n );\n const channelId = res.channel.id;\n\n // Bot is automatically a member of private channels it creates — no join/invite needed.\n // Invite configured users so they can access the channel.\n const userIds = this.config.allowedUserIds ?? [];\n if (userIds.length > 0) {\n await this.queue.enqueue(\"conversations.invite\", {\n channel: channelId,\n users: userIds.join(\",\"),\n });\n }\n\n return { channelId, channelSlug: finalSlug };\n } catch (err: any) {\n if (err?.data?.error === \"name_taken\" && attempt < 2) {\n lastError = err;\n continue;\n }\n throw err;\n }\n }\n\n throw lastError;\n }\n\n async archiveChannel(channelId: string): Promise<void> {\n await this.queue.enqueue(\"conversations.archive\", { channel: channelId });\n }\n\n async notifyChannel(text: string): Promise<void> {\n if (this.config.notificationChannelId) {\n await this.queue.enqueue(\"chat.postMessage\", {\n channel: this.config.notificationChannelId,\n text,\n });\n }\n }\n}\n","import type { App, BlockAction, ButtonAction } from \"@slack/bolt\";\nimport type { ISlackSendQueue } from \"./send-queue.js\";\n\nexport type PermissionResponseCallback = (requestId: string, optionId: string) => void;\n\nexport interface ISlackPermissionHandler {\n register(app: App): void;\n trackPendingMessage(requestId: string, channelId: string, messageTs: string): void;\n cleanupSession(channelId: string): Promise<void>;\n}\n\nexport class SlackPermissionHandler implements ISlackPermissionHandler {\n private pendingMessages = new Map<string, { channelId: string; messageTs: string }>();\n\n constructor(\n private queue: ISlackSendQueue,\n private onResponse: PermissionResponseCallback,\n ) {}\n\n trackPendingMessage(requestId: string, channelId: string, messageTs: string): void {\n this.pendingMessages.set(requestId, { channelId, messageTs });\n }\n\n async cleanupSession(channelId: string): Promise<void> {\n for (const [requestId, info] of this.pendingMessages) {\n if (info.channelId !== channelId) continue;\n await this.queue.enqueue(\"chat.update\", {\n channel: info.channelId,\n ts: info.messageTs,\n blocks: [],\n });\n this.pendingMessages.delete(requestId);\n }\n }\n\n register(app: App): void {\n // Match any action starting with \"perm_action_\"\n app.action<BlockAction<ButtonAction>>(\n /^perm_action_/,\n async ({ ack, body, action }) => {\n await ack();\n\n const value: string = action.value ?? \"\";\n const colonIdx = value.indexOf(\":\");\n if (colonIdx === -1) return;\n\n const requestId = value.slice(0, colonIdx);\n const optionId = value.slice(colonIdx + 1);\n\n this.onResponse(requestId, optionId);\n\n // Remove from pending tracking since the user has responded\n this.pendingMessages.delete(requestId);\n\n // Update message to remove action buttons and show confirmation\n const message = body.message;\n if (message) {\n await this.queue.enqueue(\"chat.update\", {\n channel: body.channel?.id ?? \"\",\n ts: message.ts,\n text: `✅ Permission response: *${optionId}*`,\n blocks: [],\n });\n }\n }\n );\n }\n}\n","// src/adapters/slack/event-router.ts\nimport type { App } from \"@slack/bolt\";\nimport type { SlackSessionMeta, SlackFileInfo } from \"./types.js\";\nimport type { SlackChannelConfig } from \"./types.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nconst log = createChildLogger({ module: \"slack-event-router\" });\n\n/** Subset of Bolt's message event fields used by the router */\ninterface SlackMessageEvent {\n bot_id?: string;\n subtype?: string;\n channel: string;\n text?: string;\n user?: string;\n files?: Array<{\n id: string;\n name: string;\n mimetype: string;\n size: number;\n url_private: string;\n }>;\n}\n\n// Callback to look up which session (if any) owns a Slack channelId\nexport type SessionLookup = (channelId: string) => SlackSessionMeta | undefined;\n\n// Callback to dispatch an incoming message to core\nexport type IncomingMessageCallback = (sessionId: string, text: string, userId: string, files?: SlackFileInfo[]) => void;\n\n// Callback to create a new session when user messages the notification channel\nexport type NewSessionCallback = (text: string, userId: string) => void;\n\nexport interface ISlackEventRouter {\n register(app: App): void;\n}\n\nexport class SlackEventRouter implements ISlackEventRouter {\n constructor(\n private sessionLookup: SessionLookup,\n private onIncoming: IncomingMessageCallback,\n private botUserId: string,\n private notificationChannelId: string | undefined,\n private onNewSession: NewSessionCallback,\n private config: SlackChannelConfig,\n private globalAllowedUserIds: string[] = [],\n ) {}\n\n private isAllowedUser(userId: string): boolean {\n const slackAllowed = this.config.allowedUserIds ?? [];\n const allowed = slackAllowed.length > 0 ? slackAllowed : this.globalAllowedUserIds;\n if (allowed.length === 0) return true;\n return allowed.includes(userId);\n }\n\n register(app: App): void {\n app.message(async ({ message }) => {\n log.debug({ message }, \"Slack raw message event\");\n\n const msg = message as unknown as SlackMessageEvent;\n\n if (msg.bot_id) return;\n const subtype = msg.subtype;\n if (subtype && subtype !== \"file_share\") return; // edited, deleted, etc.\n\n const channelId = msg.channel;\n const text: string = msg.text ?? \"\";\n const userId: string = msg.user ?? \"\";\n\n const files: SlackFileInfo[] | undefined = msg.files?.map((f) => ({\n id: f.id,\n name: f.name,\n mimetype: f.mimetype,\n size: f.size,\n url_private: f.url_private,\n }));\n\n log.debug({ channelId, userId, text }, \"Slack message received\");\n\n // Ignore messages from the bot itself\n if (userId === this.botUserId) return;\n\n // Enforce allowedUserIds\n if (!this.isAllowedUser(userId)) {\n log.warn({ userId }, \"slack: message from non-allowed user rejected\");\n return;\n }\n\n const session = this.sessionLookup(channelId);\n if (session) {\n // Message to an existing session channel\n log.debug({ channelId, sessionSlug: session.channelSlug }, \"Routing to session\");\n this.onIncoming(session.channelSlug, text, userId, files);\n return;\n }\n\n log.debug({ channelId, notificationChannelId: this.notificationChannelId }, \"No session found for channel\");\n\n // Message to the notification channel → create new session\n if (this.notificationChannelId && channelId === this.notificationChannelId) {\n this.onNewSession(text, userId);\n return;\n }\n });\n }\n}\n","// src/adapters/slack/text-buffer.ts\n// Buffers streamed text chunks per session and flushes as a single Slack message.\n// This prevents the \"many tiny messages\" problem from streaming AI responses.\n\nimport type { ISlackSendQueue } from \"./send-queue.js\";\nimport { markdownToMrkdwn } from \"./formatter.js\";\nimport { splitSafe } from \"./utils.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"slack-text-buffer\" });\n\nconst FLUSH_IDLE_MS = 2000; // flush after 2s of no new chunks\n\nexport class SlackTextBuffer {\n private buffer = \"\";\n private timer: ReturnType<typeof setTimeout> | undefined;\n private flushPromise: Promise<void> | undefined;\n private lastMessageTs: string | undefined;\n private lastPostedText: string | undefined;\n\n constructor(\n private channelId: string,\n private sessionId: string,\n private queue: ISlackSendQueue,\n ) {}\n\n append(text: string): void {\n if (!text) return;\n this.buffer += text;\n this.resetTimer();\n }\n\n private resetTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.timer = undefined;\n this.flush().catch((err) => log.error({ err, sessionId: this.sessionId }, \"Text buffer flush error\"));\n }, FLUSH_IDLE_MS);\n }\n\n async flush(): Promise<void> {\n if (this.flushPromise) return this.flushPromise;\n const text = this.buffer.trim();\n if (!text) return;\n this.buffer = \"\";\n if (this.timer) { clearTimeout(this.timer); this.timer = undefined; }\n\n this.flushPromise = (async () => {\n try {\n const converted = markdownToMrkdwn(text);\n const chunks = splitSafe(converted);\n for (const chunk of chunks) {\n if (!chunk.trim()) continue;\n const result = await this.queue.enqueue(\"chat.postMessage\", {\n channel: this.channelId,\n text: chunk,\n blocks: [{ type: \"section\", text: { type: \"mrkdwn\", text: chunk } }],\n });\n // Track last posted message for potential TTS block editing\n this.lastMessageTs = (result as { ts?: string } | undefined)?.ts;\n this.lastPostedText = chunk;\n }\n } finally {\n this.flushPromise = undefined;\n // Re-flush if content arrived while we were flushing\n if (this.buffer.trim()) {\n await this.flush();\n }\n }\n })();\n\n return this.flushPromise;\n }\n\n destroy(): void {\n if (this.timer) { clearTimeout(this.timer); this.timer = undefined; }\n this.buffer = \"\";\n }\n\n /** Remove [TTS]...[/TTS] blocks — from buffer if unflushed, or edit posted message */\n async stripTtsBlock(): Promise<void> {\n // Case 1: TTS block still in unflushed buffer\n if (/\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/.test(this.buffer)) {\n this.buffer = this.buffer.replace(/\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/g, \"\").replace(/\\s{2,}/g, \" \").trim();\n return;\n }\n\n // Case 2: Already flushed — edit the posted message via chat.update\n if (this.lastMessageTs && this.lastPostedText && /\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/.test(this.lastPostedText)) {\n const cleaned = this.lastPostedText.replace(/\\[TTS\\][\\s\\S]*?\\[\\/TTS\\]/g, \"\").replace(/\\s{2,}/g, \" \").trim();\n if (cleaned) {\n await this.queue.enqueue(\"chat.update\", {\n channel: this.channelId,\n ts: this.lastMessageTs,\n text: cleaned,\n blocks: [{ type: \"section\", text: { type: \"mrkdwn\", text: cleaned } }],\n });\n }\n this.lastPostedText = cleaned;\n }\n }\n}\n"],"mappings":"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","names":["SECTION_LIMIT","log","log"]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AgentCatalog
|
|
3
|
-
} from "./chunk-SHTGQGAU.js";
|
|
4
|
-
import "./chunk-A6Y4GZM3.js";
|
|
5
|
-
import "./chunk-ZSLHHQPQ.js";
|
|
6
|
-
import "./chunk-XMMAGAT4.js";
|
|
7
|
-
import "./chunk-VUNV25KB.js";
|
|
8
|
-
export {
|
|
9
|
-
AgentCatalog
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=agent-catalog-YHBFERYO.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ApiServer
|
|
3
|
-
} from "./chunk-2YCW3QDV.js";
|
|
4
|
-
import "./chunk-FNRSWA2K.js";
|
|
5
|
-
import "./chunk-ZSLHHQPQ.js";
|
|
6
|
-
import "./chunk-XMMAGAT4.js";
|
|
7
|
-
import "./chunk-VUNV25KB.js";
|
|
8
|
-
export {
|
|
9
|
-
ApiServer
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=api-server-CAYNPUF2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/api-server/api-server.ts","../../src/plugins/api-server/sse-manager.ts","../../src/plugins/api-server/static-server.ts","../../src/plugins/api-server/router.ts","../../src/plugins/api-server/routes/health.ts","../../src/plugins/api-server/routes/sessions.ts","../../src/plugins/api-server/routes/config.ts","../../src/plugins/api-server/routes/topics.ts","../../src/plugins/api-server/routes/tunnel.ts","../../src/plugins/api-server/routes/agents.ts","../../src/plugins/api-server/routes/notify.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as crypto from \"node:crypto\";\nimport { fileURLToPath } from \"node:url\";\nimport type { OpenACPCore } from \"../../core/core.js\";\nimport type { TopicManager } from \"../telegram/topic-manager.js\";\nimport { createChildLogger } from \"../../core/utils/log.js\";\nimport { SSEManager } from \"./sse-manager.js\";\nimport { StaticServer } from \"./static-server.js\";\nimport { Router } from \"./router.js\";\nimport { registerHealthRoutes } from \"./routes/health.js\";\nimport { registerSessionRoutes } from \"./routes/sessions.js\";\nimport { registerConfigRoutes } from \"./routes/config.js\";\nimport { registerTopicRoutes } from \"./routes/topics.js\";\nimport { registerTunnelRoutes } from \"./routes/tunnel.js\";\nimport { registerAgentRoutes } from \"./routes/agents.js\";\nimport { registerNotifyRoutes } from \"./routes/notify.js\";\n\nconst log = createChildLogger({ module: \"api-server\" });\n\nconst DEFAULT_PORT_FILE = path.join(os.homedir(), \".openacp\", \"api.port\");\n\nlet cachedVersion: string | undefined;\n\nfunction getVersion(): string {\n if (cachedVersion) return cachedVersion;\n try {\n const __filename = fileURLToPath(import.meta.url);\n const pkgPath = path.resolve(\n path.dirname(__filename),\n \"../../../package.json\",\n );\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n cachedVersion = pkg.version ?? \"0.0.0-dev\";\n } catch {\n cachedVersion = \"0.0.0-dev\";\n }\n return cachedVersion!;\n}\n\nexport interface ApiConfig {\n port: number;\n host: string;\n}\n\n/** Dependencies passed to route registration functions. */\nexport interface RouteDeps {\n core: OpenACPCore;\n topicManager?: TopicManager;\n startedAt: number;\n getVersion: () => string;\n sendJson: (res: http.ServerResponse, status: number, data: unknown) => void;\n readBody: (req: http.IncomingMessage) => Promise<string | null>;\n}\n\nexport class ApiServer {\n private server: http.Server | null = null;\n private actualPort: number = 0;\n private portFilePath: string;\n private startedAt = Date.now();\n private secret: string = \"\";\n private secretFilePath: string;\n private sseManager: SSEManager;\n private staticServer: StaticServer;\n private router: Router;\n\n constructor(\n private core: OpenACPCore,\n private config: ApiConfig,\n portFilePath?: string,\n private topicManager?: TopicManager,\n secretFilePath?: string,\n uiDir?: string,\n ) {\n this.portFilePath = portFilePath ?? DEFAULT_PORT_FILE;\n this.secretFilePath =\n secretFilePath ?? path.join(os.homedir(), \".openacp\", \"api-secret\");\n this.staticServer = new StaticServer(uiDir);\n this.sseManager = new SSEManager(\n core.eventBus,\n () => {\n const sessions = this.core.sessionManager.listSessions();\n return {\n active: sessions.filter(\n (s) => s.status === \"active\" || s.status === \"initializing\",\n ).length,\n total: sessions.length,\n };\n },\n this.startedAt,\n );\n\n this.router = new Router();\n const deps: RouteDeps = {\n core: this.core,\n topicManager: this.topicManager,\n startedAt: this.startedAt,\n getVersion,\n sendJson: this.sendJson.bind(this),\n readBody: this.readBody.bind(this),\n };\n\n registerHealthRoutes(this.router, deps);\n registerSessionRoutes(this.router, deps);\n registerConfigRoutes(this.router, deps);\n registerTopicRoutes(this.router, deps);\n registerTunnelRoutes(this.router, deps);\n registerAgentRoutes(this.router, deps);\n registerNotifyRoutes(this.router, deps);\n }\n\n async start(): Promise<void> {\n this.loadOrCreateSecret();\n this.server = http.createServer((req, res) => this.handleRequest(req, res));\n\n await new Promise<void>((resolve, reject) => {\n this.server!.on(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n log.warn(\n { port: this.config.port },\n \"API port in use, continuing without API server\",\n );\n this.server = null;\n // actualPort stays 0, port file not written\n resolve();\n } else {\n reject(err);\n }\n });\n\n this.server!.listen(this.config.port, this.config.host, () => {\n const addr = this.server!.address();\n if (addr && typeof addr === \"object\") {\n this.actualPort = addr.port;\n }\n this.writePortFile();\n log.info(\n { host: this.config.host, port: this.actualPort },\n \"API server listening\",\n );\n this.sseManager.setup();\n\n if (\n this.config.host !== \"127.0.0.1\" &&\n this.config.host !== \"localhost\"\n ) {\n log.warn(\n \"API server binding to non-localhost. Ensure api-secret file is secured.\",\n );\n }\n\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n this.sseManager.stop();\n this.removePortFile();\n if (this.server) {\n await new Promise<void>((resolve) => {\n this.server!.close(() => resolve());\n });\n this.server = null;\n }\n }\n\n getPort(): number {\n return this.actualPort;\n }\n\n getSecret(): string {\n return this.secret;\n }\n\n private writePortFile(): void {\n const dir = path.dirname(this.portFilePath);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(this.portFilePath, String(this.actualPort));\n }\n\n private removePortFile(): void {\n try {\n fs.unlinkSync(this.portFilePath);\n } catch {\n /* ignore */\n }\n }\n\n private loadOrCreateSecret(): void {\n const dir = path.dirname(this.secretFilePath);\n fs.mkdirSync(dir, { recursive: true });\n\n try {\n this.secret = fs.readFileSync(this.secretFilePath, \"utf-8\").trim();\n if (this.secret) {\n // Warn if file permissions are too open (like SSH does for private keys)\n try {\n const stat = fs.statSync(this.secretFilePath);\n const mode = stat.mode & 0o777;\n if (mode & 0o077) {\n log.warn(\n { path: this.secretFilePath, mode: \"0\" + mode.toString(8) },\n \"API secret file has insecure permissions (should be 0600). Run: chmod 600 %s\",\n this.secretFilePath,\n );\n }\n } catch {\n /* stat failed, skip check */\n }\n return;\n }\n } catch {\n // File doesn't exist, create it\n }\n\n this.secret = crypto.randomBytes(32).toString(\"hex\");\n fs.writeFileSync(this.secretFilePath, this.secret, { mode: 0o600 });\n }\n\n private authenticate(\n req: http.IncomingMessage,\n allowQueryParam = false,\n ): boolean {\n // Check Authorization header\n const authHeader = req.headers.authorization;\n if (authHeader?.startsWith(\"Bearer \")) {\n const token = authHeader.slice(7);\n if (\n token.length === this.secret.length &&\n crypto.timingSafeEqual(\n Buffer.from(token, \"utf-8\"),\n Buffer.from(this.secret, \"utf-8\"),\n )\n ) {\n return true;\n }\n }\n // Query param auth only for SSE (EventSource can't set headers)\n if (allowQueryParam) {\n const parsedUrl = new URL(req.url || \"\", \"http://localhost\");\n const qToken = parsedUrl.searchParams.get(\"token\");\n if (\n qToken &&\n qToken.length === this.secret.length &&\n crypto.timingSafeEqual(\n Buffer.from(qToken, \"utf-8\"),\n Buffer.from(this.secret, \"utf-8\"),\n )\n ) {\n return true;\n }\n }\n return false;\n }\n\n private async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n ): Promise<void> {\n const method = req.method?.toUpperCase();\n const url = req.url || \"\";\n\n // Auth check: exempt health/version, SSE (has own auth), and non-/api/ routes (static files)\n if (url.startsWith(\"/api/\")) {\n const isExempt =\n method === \"GET\" &&\n (url === \"/api/health\" ||\n url === \"/api/version\" ||\n url.startsWith(\"/api/events\"));\n if (!isExempt && !this.authenticate(req)) {\n this.sendJson(res, 401, { error: \"Unauthorized\" });\n return;\n }\n }\n\n try {\n // SSE endpoint — handled separately (streaming connection)\n if (method === \"GET\" && url.startsWith(\"/api/events\")) {\n if (!this.authenticate(req, true)) {\n this.sendJson(res, 401, { error: \"Unauthorized\" });\n return;\n }\n this.sseManager.handleRequest(req, res);\n return; // Don't end the response — SSE keeps it open\n }\n\n // Try router for API routes\n if (url.startsWith(\"/api/\")) {\n const match = this.router.match(method!, url);\n if (match) {\n await match.handler(req, res, match.params);\n } else {\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n return;\n }\n\n // Try static file serving (UI dashboard) for non-API routes\n if (!this.staticServer.serve(req, res)) {\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n } catch (err) {\n log.error({ err }, \"API request error\");\n this.sendJson(res, 500, { error: \"Internal server error\" });\n }\n }\n\n private sendJson(\n res: http.ServerResponse,\n status: number,\n data: unknown,\n ): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n }\n\n private readBody(req: http.IncomingMessage): Promise<string | null> {\n const MAX_BODY_SIZE = 1024 * 1024; // 1MB\n return new Promise((resolve) => {\n let data = \"\";\n let size = 0;\n let destroyed = false;\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_SIZE && !destroyed) {\n destroyed = true;\n req.destroy();\n resolve(null);\n return;\n }\n if (!destroyed) data += chunk;\n });\n req.on(\"end\", () => {\n if (!destroyed) resolve(data);\n });\n req.on(\"error\", () => {\n if (!destroyed) resolve(\"\");\n });\n });\n }\n}\n","import * as http from \"node:http\";\nimport type { EventBus, EventBusEvents } from \"../../core/event-bus.js\";\n\ninterface SSEResponse extends http.ServerResponse {\n sessionFilter?: string;\n}\n\ninterface SessionStats {\n active: number;\n total: number;\n}\n\nexport class SSEManager {\n private sseConnections = new Set<http.ServerResponse>();\n private sseCleanupHandlers = new Map<http.ServerResponse, () => void>();\n private healthInterval?: ReturnType<typeof setInterval>;\n private boundHandlers: Array<{\n event: keyof EventBusEvents;\n handler: (data: unknown) => void;\n }> = [];\n\n constructor(\n private eventBus: EventBus | undefined,\n private getSessionStats: () => SessionStats,\n private startedAt: number,\n ) {}\n\n setup(): void {\n if (!this.eventBus) return;\n\n const events = [\n \"session:created\",\n \"session:updated\",\n \"session:deleted\",\n \"agent:event\",\n \"permission:request\",\n ] as const;\n\n for (const eventName of events) {\n const handler = (data: unknown) => {\n this.broadcast(eventName, data);\n };\n this.eventBus.on(eventName, handler);\n this.boundHandlers.push({ event: eventName, handler });\n }\n\n // Health heartbeat every 30s\n this.healthInterval = setInterval(() => {\n const mem = process.memoryUsage();\n const stats = this.getSessionStats();\n this.broadcast(\"health\", {\n uptime: Date.now() - this.startedAt,\n memory: {\n rss: mem.rss,\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n },\n sessions: stats,\n });\n }, 30_000);\n }\n\n handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {\n const parsedUrl = new URL(req.url || \"\", \"http://localhost\");\n const sessionFilter = parsedUrl.searchParams.get(\"sessionId\");\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n res.flushHeaders();\n\n // Store filter metadata on the response for broadcast\n (res as SSEResponse).sessionFilter = sessionFilter ?? undefined;\n\n this.sseConnections.add(res);\n\n const cleanup = () => {\n this.sseConnections.delete(res);\n this.sseCleanupHandlers.delete(res);\n };\n this.sseCleanupHandlers.set(res, cleanup);\n req.on(\"close\", cleanup);\n }\n\n broadcast(event: string, data: unknown): void {\n const payload = `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n // Events that carry sessionId and should be filtered\n const sessionEvents = [\n \"agent:event\",\n \"permission:request\",\n \"session:updated\",\n ];\n for (const res of this.sseConnections) {\n const filter = (res as SSEResponse).sessionFilter;\n if (filter && sessionEvents.includes(event)) {\n const eventData = data as { sessionId: string };\n if (eventData.sessionId !== filter) continue;\n }\n try {\n if (res.writable) res.write(payload);\n } catch {\n /* connection closed */\n }\n }\n }\n\n stop(): void {\n if (this.healthInterval) clearInterval(this.healthInterval);\n\n // Remove only our own event bus listeners\n if (this.eventBus) {\n for (const { event, handler } of this.boundHandlers) {\n this.eventBus.off(event, handler);\n }\n }\n this.boundHandlers = [];\n\n // Copy to avoid modifying Map while iterating\n const entries = [...this.sseCleanupHandlers];\n for (const [res, cleanup] of entries) {\n res.end();\n cleanup();\n }\n }\n}\n\nexport type { SessionStats };\n","import * as http from \"node:http\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport class StaticServer {\n private uiDir: string | undefined;\n\n constructor(uiDir?: string) {\n this.uiDir = uiDir;\n\n if (!this.uiDir) {\n const __filename = fileURLToPath(import.meta.url);\n const candidate = path.resolve(path.dirname(__filename), \"../../ui/dist\");\n if (fs.existsSync(path.join(candidate, \"index.html\"))) {\n this.uiDir = candidate;\n }\n // Also check dist-publish layout\n if (!this.uiDir) {\n const publishCandidate = path.resolve(\n path.dirname(__filename),\n \"../ui\",\n );\n if (fs.existsSync(path.join(publishCandidate, \"index.html\"))) {\n this.uiDir = publishCandidate;\n }\n }\n }\n }\n\n isAvailable(): boolean {\n return this.uiDir !== undefined;\n }\n\n serve(req: http.IncomingMessage, res: http.ServerResponse): boolean {\n if (!this.uiDir) return false;\n\n const urlPath = (req.url || \"/\").split(\"?\")[0];\n const safePath = path.normalize(urlPath);\n\n // Try exact file match\n const filePath = path.join(this.uiDir, safePath);\n if (!filePath.startsWith(this.uiDir + path.sep) && filePath !== this.uiDir)\n return false; // path traversal guard\n\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {\n const ext = path.extname(filePath);\n const contentType = MIME_TYPES[ext] ?? \"application/octet-stream\";\n // Vite-hashed assets get long cache, others get no-cache\n const isHashed = /\\.[a-zA-Z0-9]{8,}\\.(js|css)$/.test(filePath);\n const cacheControl = isHashed\n ? \"public, max-age=31536000, immutable\"\n : \"no-cache\";\n res.writeHead(200, {\n \"Content-Type\": contentType,\n \"Cache-Control\": cacheControl,\n });\n fs.createReadStream(filePath).pipe(res);\n return true;\n }\n\n // SPA fallback — serve index.html\n const indexPath = path.join(this.uiDir, \"index.html\");\n if (fs.existsSync(indexPath)) {\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-cache\",\n });\n fs.createReadStream(indexPath).pipe(res);\n return true;\n }\n\n return false;\n }\n}\n","import type * as http from \"node:http\";\n\nexport type Handler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n params: Record<string, string>,\n) => Promise<void>;\n\ninterface Route {\n method: string;\n pattern: RegExp;\n keys: string[];\n handler: Handler;\n}\n\nexport class Router {\n private routes: Route[] = [];\n\n get(path: string, handler: Handler): void {\n this.add(\"GET\", path, handler);\n }\n post(path: string, handler: Handler): void {\n this.add(\"POST\", path, handler);\n }\n put(path: string, handler: Handler): void {\n this.add(\"PUT\", path, handler);\n }\n patch(path: string, handler: Handler): void {\n this.add(\"PATCH\", path, handler);\n }\n delete(path: string, handler: Handler): void {\n this.add(\"DELETE\", path, handler);\n }\n\n match(\n method: string,\n url: string,\n ): { handler: Handler; params: Record<string, string> } | null {\n const pathname = url.split(\"?\")[0];\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const m = pathname.match(route.pattern);\n if (!m) continue;\n const params: Record<string, string> = {};\n for (let i = 0; i < route.keys.length; i++) {\n params[route.keys[i]] = m[i + 1];\n }\n return { handler: route.handler, params };\n }\n return null;\n }\n\n private add(method: string, path: string, handler: Handler): void {\n const keys: string[] = [];\n const pattern = path.replace(/:(\\w+)/g, (_, key) => {\n keys.push(key);\n return \"([^/]+)\";\n });\n this.routes.push({\n method,\n pattern: new RegExp(`^${pattern}$`),\n keys,\n handler,\n });\n }\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\n\nexport function registerHealthRoutes(router: Router, deps: RouteDeps): void {\n router.get(\"/api/health\", async (_req, res) => {\n const activeSessions = deps.core.sessionManager.listSessions();\n const allRecords = deps.core.sessionManager.listRecords();\n const mem = process.memoryUsage();\n const tunnel = deps.core.tunnelService;\n\n deps.sendJson(res, 200, {\n status: \"ok\",\n uptime: Date.now() - deps.startedAt,\n version: deps.getVersion(),\n memory: {\n rss: mem.rss,\n heapUsed: mem.heapUsed,\n heapTotal: mem.heapTotal,\n },\n sessions: {\n active: activeSessions.filter(\n (s) => s.status === \"active\" || s.status === \"initializing\",\n ).length,\n total: allRecords.length,\n },\n adapters: Array.from(deps.core.adapters.keys()),\n tunnel: tunnel\n ? { enabled: true, url: tunnel.getPublicUrl() }\n : { enabled: false },\n });\n });\n\n router.get(\"/api/version\", async (_req, res) => {\n deps.sendJson(res, 200, { version: deps.getVersion() });\n });\n\n router.post(\"/api/restart\", async (_req, res) => {\n if (!deps.core.requestRestart) {\n deps.sendJson(res, 501, { error: \"Restart not available\" });\n return;\n }\n\n deps.sendJson(res, 200, { ok: true, message: \"Restarting...\" });\n setImmediate(() => deps.core.requestRestart!());\n });\n\n router.get(\"/api/adapters\", async (_req, res) => {\n const adapters = Array.from(deps.core.adapters.entries()).map(([name]) => ({\n name,\n type: \"built-in\" as const,\n }));\n deps.sendJson(res, 200, { adapters });\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\nimport { createChildLogger } from \"../../../core/utils/log.js\";\n\nconst log = createChildLogger({ module: \"api-server\" });\n\nexport function registerSessionRoutes(router: Router, deps: RouteDeps): void {\n router.post(\"/api/sessions/adopt\", async (req, res) => {\n const body = await deps.readBody(req);\n if (body === null) {\n return deps.sendJson(res, 413, { error: \"Request body too large\" });\n }\n if (!body) {\n return deps.sendJson(res, 400, {\n error: \"bad_request\",\n message: \"Empty request body\",\n });\n }\n\n let parsed: { agent?: string; agentSessionId?: string; cwd?: string; channel?: string };\n try {\n parsed = JSON.parse(body);\n } catch {\n return deps.sendJson(res, 400, {\n error: \"bad_request\",\n message: \"Invalid JSON\",\n });\n }\n\n const { agent, agentSessionId, cwd, channel } = parsed;\n\n if (!agent || !agentSessionId) {\n return deps.sendJson(res, 400, {\n error: \"bad_request\",\n message: \"Missing required fields: agent, agentSessionId\",\n });\n }\n\n const result = await deps.core.adoptSession(\n agent,\n agentSessionId,\n cwd ?? process.cwd(),\n channel,\n );\n\n if (result.ok) {\n return deps.sendJson(res, 200, result);\n } else {\n const status =\n result.error === \"session_limit\"\n ? 429\n : result.error === \"agent_not_supported\"\n ? 400\n : 500;\n return deps.sendJson(res, status, result);\n }\n });\n\n router.post(\"/api/sessions\", async (req, res) => {\n const body = await deps.readBody(req);\n let agent: string | undefined;\n let workspace: string | undefined;\n let channel: string | undefined;\n\n if (body) {\n try {\n const parsed = JSON.parse(body);\n agent = parsed.agent;\n workspace = parsed.workspace;\n channel = parsed.channel;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n // Check max concurrent sessions\n const config = deps.core.configManager.get();\n const activeSessions = deps.core.sessionManager\n .listSessions()\n .filter((s) => s.status === \"active\" || s.status === \"initializing\");\n if (activeSessions.length >= config.security.maxConcurrentSessions) {\n deps.sendJson(res, 429, {\n error: `Max concurrent sessions (${config.security.maxConcurrentSessions}) reached. Cancel a session first.`,\n });\n return;\n }\n\n // Resolve adapter: use explicit channel if provided, otherwise fall back to first registered adapter\n let adapterId: string | null = null;\n let adapter: InstanceType<any> | null = null;\n\n if (channel) {\n if (!deps.core.adapters.has(channel)) {\n const available = Array.from(deps.core.adapters.keys()).join(\", \") || \"none\";\n deps.sendJson(res, 400, {\n error: `Adapter '${channel}' is not connected. Available: ${available}`,\n });\n return;\n }\n adapterId = channel;\n adapter = deps.core.adapters.get(channel) ?? null;\n } else {\n const firstEntry = deps.core.adapters.entries().next().value;\n if (firstEntry) {\n [adapterId, adapter] = firstEntry;\n }\n }\n\n const channelId = adapterId ?? \"api\";\n\n const resolvedAgent = agent || config.defaultAgent;\n const resolvedWorkspace = deps.core.configManager.resolveWorkspace(\n workspace || config.agents[resolvedAgent]?.workingDirectory,\n );\n\n const session = await deps.core.createSession({\n channelId,\n agentName: resolvedAgent,\n workingDirectory: resolvedWorkspace,\n createThread: !!adapter,\n initialName: `🔄 ${resolvedAgent} — New Session`,\n });\n\n // If no adapter wired events (headless), auto-approve permissions\n if (!adapter) {\n session.agentInstance.onPermissionRequest = async (request) => {\n const allowOption = request.options.find((o) => o.isAllow);\n log.debug(\n {\n sessionId: session.id,\n permissionId: request.id,\n option: allowOption?.id,\n },\n \"Auto-approving permission for API session\",\n );\n return allowOption?.id ?? request.options[0]?.id ?? \"\";\n };\n }\n\n // Warmup in background so session moves from 'initializing' to 'active'\n session\n .warmup()\n .catch((err) =>\n log.warn({ err, sessionId: session.id }, \"API session warmup failed\"),\n );\n\n deps.sendJson(res, 200, {\n sessionId: session.id,\n agent: session.agentName,\n status: session.status,\n workspace: session.workingDirectory,\n });\n });\n\n router.post(\"/api/sessions/:sessionId/prompt\", async (req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const session = deps.core.sessionManager.getSession(sessionId);\n if (!session) {\n deps.sendJson(res, 404, { error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n if (\n session.status === \"cancelled\" ||\n session.status === \"finished\" ||\n session.status === \"error\"\n ) {\n deps.sendJson(res, 400, { error: `Session is ${session.status}` });\n return;\n }\n\n const body = await deps.readBody(req);\n let prompt: string | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n prompt = parsed.prompt;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n if (!prompt) {\n deps.sendJson(res, 400, { error: \"Missing prompt\" });\n return;\n }\n\n session.enqueuePrompt(prompt).catch(() => {});\n deps.sendJson(res, 200, {\n ok: true,\n sessionId,\n queueDepth: session.queueDepth,\n });\n });\n\n router.post(\n \"/api/sessions/:sessionId/permission\",\n async (req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const session = deps.core.sessionManager.getSession(sessionId);\n if (!session) {\n deps.sendJson(res, 404, { error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n const body = await deps.readBody(req);\n let permissionId: string | undefined;\n let optionId: string | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n permissionId = parsed.permissionId;\n optionId = parsed.optionId;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n if (!permissionId || !optionId) {\n deps.sendJson(res, 400, {\n error: \"Missing permissionId or optionId\",\n });\n return;\n }\n\n if (\n !session.permissionGate.isPending ||\n session.permissionGate.requestId !== permissionId\n ) {\n deps.sendJson(res, 400, {\n error: \"No matching pending permission request\",\n });\n return;\n }\n\n session.permissionGate.resolve(optionId);\n deps.sendJson(res, 200, { ok: true });\n },\n );\n\n router.patch(\n \"/api/sessions/:sessionId/dangerous\",\n async (req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const session = deps.core.sessionManager.getSession(sessionId);\n if (!session) {\n deps.sendJson(res, 404, { error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n const body = await deps.readBody(req);\n let enabled: boolean | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n enabled = parsed.enabled;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n if (typeof enabled !== \"boolean\") {\n deps.sendJson(res, 400, { error: \"Missing enabled boolean\" });\n return;\n }\n\n session.dangerousMode = enabled;\n await deps.core.sessionManager.patchRecord(sessionId, {\n dangerousMode: enabled,\n });\n deps.sendJson(res, 200, { ok: true, dangerousMode: enabled });\n },\n );\n\n router.get(\"/api/sessions/:sessionId\", async (_req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const session = deps.core.sessionManager.getSession(sessionId);\n if (!session) {\n deps.sendJson(res, 404, { error: `Session \"${sessionId}\" not found` });\n return;\n }\n\n deps.sendJson(res, 200, {\n session: {\n id: session.id,\n agent: session.agentName,\n status: session.status,\n name: session.name ?? null,\n workspace: session.workingDirectory,\n createdAt: session.createdAt.toISOString(),\n dangerousMode: session.dangerousMode,\n queueDepth: session.queueDepth,\n promptRunning: session.promptRunning,\n threadId: session.threadId,\n channelId: session.channelId,\n agentSessionId: session.agentSessionId,\n },\n });\n });\n\n router.post(\"/api/sessions/:sessionId/archive\", async (_req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const result = await deps.core.archiveSession(sessionId);\n if (result.ok) {\n deps.sendJson(res, 200, result);\n } else {\n deps.sendJson(res, 400, result);\n }\n });\n\n router.delete(\"/api/sessions/:sessionId\", async (_req, res, params) => {\n const sessionId = decodeURIComponent(params.sessionId);\n const session = deps.core.sessionManager.getSession(sessionId);\n if (!session) {\n deps.sendJson(res, 404, { error: `Session \"${sessionId}\" not found` });\n return;\n }\n await deps.core.sessionManager.cancelSession(sessionId);\n deps.sendJson(res, 200, { ok: true });\n });\n\n router.get(\"/api/sessions\", async (_req, res) => {\n const sessions = deps.core.sessionManager.listSessions();\n deps.sendJson(res, 200, {\n sessions: sessions.map((s) => ({\n id: s.id,\n agent: s.agentName,\n status: s.status,\n name: s.name ?? null,\n workspace: s.workingDirectory,\n createdAt: s.createdAt.toISOString(),\n dangerousMode: s.dangerousMode,\n queueDepth: s.queueDepth,\n promptRunning: s.promptRunning,\n lastActiveAt:\n deps.core.sessionManager.getSessionRecord(s.id)?.lastActiveAt ??\n null,\n })),\n });\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\n\nconst SENSITIVE_KEYS = [\n \"botToken\",\n \"token\",\n \"apiKey\",\n \"secret\",\n \"password\",\n \"webhookSecret\",\n];\n\nfunction redactConfig(config: unknown): unknown {\n const redacted = structuredClone(config);\n redactDeep(redacted as Record<string, unknown>);\n return redacted;\n}\n\nfunction redactDeep(obj: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(obj)) {\n if (SENSITIVE_KEYS.includes(key) && typeof value === \"string\") {\n obj[key] = \"***\";\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === \"object\")\n redactDeep(item as Record<string, unknown>);\n }\n } else if (value && typeof value === \"object\") {\n redactDeep(value as Record<string, unknown>);\n }\n }\n}\n\nexport function registerConfigRoutes(router: Router, deps: RouteDeps): void {\n router.get(\"/api/config/editable\", async (_req, res) => {\n const { getSafeFields, resolveOptions, getConfigValue } =\n await import(\"../../../core/config/config-registry.js\");\n const config = deps.core.configManager.get();\n const safeFields = getSafeFields();\n\n const fields = safeFields.map((def) => ({\n path: def.path,\n displayName: def.displayName,\n group: def.group,\n type: def.type,\n options: resolveOptions(def, config),\n value: getConfigValue(config, def.path),\n hotReload: def.hotReload,\n }));\n\n deps.sendJson(res, 200, { fields });\n });\n\n router.get(\"/api/config\", async (_req, res) => {\n const config = deps.core.configManager.get();\n deps.sendJson(res, 200, { config: redactConfig(config) });\n });\n\n router.patch(\"/api/config\", async (req, res) => {\n const body = await deps.readBody(req);\n let configPath: string | undefined;\n let value: unknown;\n\n if (body) {\n try {\n const parsed = JSON.parse(body);\n configPath = parsed.path;\n value = parsed.value;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n if (!configPath) {\n deps.sendJson(res, 400, { error: \"Missing path\" });\n return;\n }\n\n // Block prototype pollution\n const BLOCKED_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n const parts = configPath.split(\".\");\n if (parts.some((p) => BLOCKED_KEYS.has(p))) {\n deps.sendJson(res, 400, { error: \"Invalid config path\" });\n return;\n }\n\n // Enforce safe-fields scope — only fields marked 'safe' can be modified via API\n const { getFieldDef } = await import(\"../../../core/config/config-registry.js\");\n const fieldDef = getFieldDef(configPath);\n if (!fieldDef || fieldDef.scope !== \"safe\") {\n deps.sendJson(res, 403, {\n error: \"This config field cannot be modified via the API\",\n });\n return;\n }\n\n // Pre-validate by cloning config and applying the change\n const currentConfig = deps.core.configManager.get();\n const cloned = structuredClone(currentConfig) as Record<string, unknown>;\n let target: Record<string, unknown> = cloned;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (\n target[part] &&\n typeof target[part] === \"object\" &&\n !Array.isArray(target[part])\n ) {\n target = target[part] as Record<string, unknown>;\n } else if (target[part] === undefined || target[part] === null) {\n // Create intermediate objects for new paths (e.g. speech.stt.providers.groq.apiKey)\n target[part] = {};\n target = target[part] as Record<string, unknown>;\n } else {\n deps.sendJson(res, 400, { error: \"Invalid config path\" });\n return;\n }\n }\n\n const lastKey = parts[parts.length - 1];\n target[lastKey] = value;\n\n // Validate with Zod\n const { ConfigSchema } = await import(\"../../../core/config/config.js\");\n const result = ConfigSchema.safeParse(cloned);\n if (!result.success) {\n deps.sendJson(res, 400, {\n error: \"Validation failed\",\n details: result.error.issues.map((i) => ({\n path: i.path.join(\".\"),\n message: i.message,\n })),\n });\n return;\n }\n\n // Convert dot-path to nested object for save\n const updates: Record<string, unknown> = {};\n let updateTarget = updates;\n for (let i = 0; i < parts.length - 1; i++) {\n updateTarget[parts[i]] = {};\n updateTarget = updateTarget[parts[i]] as Record<string, unknown>;\n }\n updateTarget[lastKey] = value;\n\n await deps.core.configManager.save(updates, configPath);\n\n const { isHotReloadable } = await import(\"../../../core/config/config-registry.js\");\n const needsRestart = !isHotReloadable(configPath!);\n\n deps.sendJson(res, 200, {\n ok: true,\n needsRestart,\n config: redactConfig(deps.core.configManager.get()),\n });\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\n\nexport function registerTopicRoutes(router: Router, deps: RouteDeps): void {\n router.get(\"/api/topics\", async (req, res) => {\n if (!deps.topicManager) {\n deps.sendJson(res, 501, { error: \"Topic management not available\" });\n return;\n }\n const url = req.url || \"\";\n const params = new URL(url, \"http://localhost\").searchParams;\n const statusParam = params.get(\"status\");\n const filter = statusParam\n ? { statuses: statusParam.split(\",\") }\n : undefined;\n const topics = deps.topicManager.listTopics(filter);\n deps.sendJson(res, 200, { topics });\n });\n\n router.post(\"/api/topics/cleanup\", async (req, res) => {\n if (!deps.topicManager) {\n deps.sendJson(res, 501, { error: \"Topic management not available\" });\n return;\n }\n const body = await deps.readBody(req);\n let statuses: string[] | undefined;\n if (body) {\n try {\n statuses = JSON.parse(body).statuses;\n } catch {\n /* use defaults */\n }\n }\n const result = await deps.topicManager.cleanup(statuses);\n deps.sendJson(res, 200, result);\n });\n\n router.delete(\"/api/topics/:sessionId\", async (req, res, params) => {\n if (!deps.topicManager) {\n deps.sendJson(res, 501, { error: \"Topic management not available\" });\n return;\n }\n const sessionId = decodeURIComponent(params.sessionId);\n const url = req.url || \"\";\n const urlParams = new URL(url, \"http://localhost\").searchParams;\n const force = urlParams.get(\"force\") === \"true\";\n const result = await deps.topicManager.deleteTopic(\n sessionId,\n force ? { confirmed: true } : undefined,\n );\n if (result.ok) {\n deps.sendJson(res, 200, result);\n } else if (result.needsConfirmation) {\n deps.sendJson(res, 409, {\n error: \"Session is active\",\n needsConfirmation: true,\n session: result.session,\n });\n } else if (result.error === \"Cannot delete system topic\") {\n deps.sendJson(res, 403, { error: result.error });\n } else {\n deps.sendJson(res, 404, { error: result.error ?? \"Not found\" });\n }\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\n\nexport function registerTunnelRoutes(router: Router, deps: RouteDeps): void {\n router.get(\"/api/tunnel\", async (_req, res) => {\n const tunnel = deps.core.tunnelService;\n if (tunnel) {\n deps.sendJson(res, 200, {\n enabled: true,\n url: tunnel.getPublicUrl(),\n provider: deps.core.configManager.get().tunnel.provider,\n });\n } else {\n deps.sendJson(res, 200, { enabled: false });\n }\n });\n\n router.get(\"/api/tunnel/list\", async (_req, res) => {\n const tunnel = deps.core.tunnelService;\n if (!tunnel) {\n deps.sendJson(res, 200, []);\n return;\n }\n deps.sendJson(res, 200, tunnel.listTunnels());\n });\n\n router.post(\"/api/tunnel\", async (req, res) => {\n const tunnel = deps.core.tunnelService;\n if (!tunnel) {\n deps.sendJson(res, 400, { error: \"Tunnel service is not enabled\" });\n return;\n }\n const body = await deps.readBody(req);\n if (body === null) {\n deps.sendJson(res, 413, { error: \"Request body too large\" });\n return;\n }\n if (!body) {\n deps.sendJson(res, 400, { error: \"Missing request body\" });\n return;\n }\n try {\n const { port, label, sessionId } = JSON.parse(body);\n if (!port || typeof port !== \"number\") {\n deps.sendJson(res, 400, {\n error: \"port is required and must be a number\",\n });\n return;\n }\n const entry = await tunnel.addTunnel(port, { label, sessionId });\n deps.sendJson(res, 200, entry);\n } catch (err) {\n deps.sendJson(res, 400, { error: (err as Error).message });\n }\n });\n\n router.delete(\"/api/tunnel/:port\", async (_req, res, params) => {\n const tunnel = deps.core.tunnelService;\n if (!tunnel) {\n deps.sendJson(res, 400, { error: \"Tunnel service is not enabled\" });\n return;\n }\n const port = parseInt(params.port, 10);\n try {\n await tunnel.stopTunnel(port);\n deps.sendJson(res, 200, { ok: true });\n } catch (err) {\n deps.sendJson(res, 400, { error: (err as Error).message });\n }\n });\n\n router.delete(\"/api/tunnel\", async (_req, res) => {\n const tunnel = deps.core.tunnelService;\n if (!tunnel) {\n deps.sendJson(res, 400, { error: \"Tunnel service is not enabled\" });\n return;\n }\n const count = tunnel.listTunnels().length;\n await tunnel.stopAllUser();\n deps.sendJson(res, 200, { ok: true, stopped: count });\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\nimport { getAgentCapabilities } from \"../../../core/agents/agent-registry.js\";\n\nexport function registerAgentRoutes(router: Router, deps: RouteDeps): void {\n router.get(\"/api/agents\", async (_req, res) => {\n const agents = deps.core.agentManager.getAvailableAgents();\n const defaultAgent = deps.core.configManager.get().defaultAgent;\n const agentsWithCaps = agents.map((a) => ({\n ...a,\n capabilities: getAgentCapabilities(a.name),\n }));\n deps.sendJson(res, 200, { agents: agentsWithCaps, default: defaultAgent });\n });\n}\n","import type { Router } from \"../router.js\";\nimport type { RouteDeps } from \"../api-server.js\";\n\nexport function registerNotifyRoutes(router: Router, deps: RouteDeps): void {\n router.post(\"/api/notify\", async (req, res) => {\n const body = await deps.readBody(req);\n let message: string | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n message = parsed.message;\n } catch {\n deps.sendJson(res, 400, { error: \"Invalid JSON body\" });\n return;\n }\n }\n\n if (!message) {\n deps.sendJson(res, 400, { error: \"Missing message\" });\n return;\n }\n\n await deps.core.notificationManager.notifyAll({\n sessionId: \"system\",\n type: \"completed\",\n summary: message,\n });\n deps.sendJson(res, 200, { ok: true });\n });\n}\n"],"mappings":"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","names":["fs","path","fileURLToPath","path","log","fileURLToPath","resolve"]}
|