@poolzin/pool-bot 2026.2.21 → 2026.2.23

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.
Files changed (378) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agents/api-key-rotation.js +47 -0
  3. package/dist/agents/apply-patch-update.js +19 -9
  4. package/dist/agents/apply-patch.js +72 -47
  5. package/dist/agents/bash-tools.exec.js +141 -559
  6. package/dist/agents/cli-backends.js +49 -6
  7. package/dist/agents/cli-runner/helpers.js +69 -152
  8. package/dist/agents/cli-runner.js +70 -19
  9. package/dist/agents/identity.js +20 -1
  10. package/dist/agents/image-sanitization.js +9 -0
  11. package/dist/agents/live-auth-keys.js +123 -26
  12. package/dist/agents/live-model-filter.js +13 -4
  13. package/dist/agents/model-catalog.js +40 -9
  14. package/dist/agents/model-forward-compat.js +60 -23
  15. package/dist/agents/model-selection.js +134 -41
  16. package/dist/agents/pi-auth-json.js +2 -2
  17. package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
  18. package/dist/agents/pi-embedded-helpers/errors.js +140 -15
  19. package/dist/agents/pi-embedded-helpers/images.js +22 -12
  20. package/dist/agents/pi-embedded-helpers.js +2 -2
  21. package/dist/agents/pi-embedded-runner/abort.js +10 -3
  22. package/dist/agents/pi-embedded-runner/compact.js +230 -32
  23. package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
  24. package/dist/agents/pi-embedded-runner/google.js +109 -19
  25. package/dist/agents/pi-embedded-runner/history.js +35 -17
  26. package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
  27. package/dist/agents/pi-embedded-runner/run/images.js +81 -55
  28. package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
  29. package/dist/agents/pi-embedded-runner/run.js +193 -25
  30. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
  31. package/dist/agents/pi-embedded-runner/runs.js +17 -8
  32. package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
  33. package/dist/agents/pi-embedded-runner.js +1 -1
  34. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
  35. package/dist/agents/pi-embedded-subscribe.js +37 -0
  36. package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
  37. package/dist/agents/pi-model-discovery.js +9 -2
  38. package/dist/agents/pi-tool-definition-adapter.js +60 -8
  39. package/dist/agents/pi-tools.before-tool-call.js +1 -1
  40. package/dist/agents/pi-tools.js +113 -94
  41. package/dist/agents/pi-tools.read.js +337 -38
  42. package/dist/agents/poolbot-tools.js +14 -5
  43. package/dist/agents/sandbox/docker.js +10 -5
  44. package/dist/agents/sandbox/registry.js +96 -46
  45. package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
  46. package/dist/agents/sandbox-paths.js +43 -10
  47. package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
  48. package/dist/agents/session-tool-result-guard.js +39 -39
  49. package/dist/agents/session-transcript-repair.js +36 -33
  50. package/dist/agents/session-write-lock.js +62 -44
  51. package/dist/agents/skills/frontmatter.js +49 -88
  52. package/dist/agents/skills/workspace.js +335 -28
  53. package/dist/agents/subagent-announce.js +508 -174
  54. package/dist/agents/subagent-registry.js +45 -4
  55. package/dist/agents/subagent-spawn.js +16 -33
  56. package/dist/agents/system-prompt-report.js +27 -10
  57. package/dist/agents/system-prompt.js +26 -32
  58. package/dist/agents/tool-call-id.js +69 -17
  59. package/dist/agents/tool-display-common.js +1 -1
  60. package/dist/agents/tool-images.js +64 -31
  61. package/dist/agents/tools/canvas-tool.js +17 -11
  62. package/dist/agents/tools/common.js +37 -19
  63. package/dist/agents/tools/cron-tool.js +40 -38
  64. package/dist/agents/tools/gateway.js +70 -2
  65. package/dist/agents/tools/message-tool.js +181 -40
  66. package/dist/agents/tools/nodes-tool.js +128 -36
  67. package/dist/agents/tools/nodes-utils.js +12 -38
  68. package/dist/agents/tools/session-status-tool.js +24 -71
  69. package/dist/agents/tools/sessions-helpers.js +38 -210
  70. package/dist/agents/tools/sessions-spawn-tool.js +28 -198
  71. package/dist/agents/tools/telegram-actions.js +58 -7
  72. package/dist/agents/tools/web-fetch-utils.js +112 -7
  73. package/dist/agents/tools/web-fetch.js +279 -175
  74. package/dist/agents/tools/web-shared.js +71 -8
  75. package/dist/agents/usage.js +25 -16
  76. package/dist/auto-reply/commands-registry.data.js +85 -11
  77. package/dist/auto-reply/dispatch.js +40 -21
  78. package/dist/auto-reply/reply/abort.js +102 -33
  79. package/dist/auto-reply/reply/commands-core.js +82 -33
  80. package/dist/auto-reply/reply/commands-export-session.js +1 -1
  81. package/dist/auto-reply/reply/commands-info.js +41 -12
  82. package/dist/auto-reply/reply/commands-subagents.js +352 -100
  83. package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
  84. package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
  85. package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
  86. package/dist/auto-reply/reply/inbound-meta.js +12 -1
  87. package/dist/auto-reply/reply/mentions.js +18 -11
  88. package/dist/auto-reply/reply/normalize-reply.js +17 -8
  89. package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
  90. package/dist/auto-reply/reply/session.js +102 -21
  91. package/dist/auto-reply/reply/streaming-directives.js +16 -5
  92. package/dist/auto-reply/status.js +73 -50
  93. package/dist/browser/extension-relay.js +3 -3
  94. package/dist/browser/http-auth.js +1 -1
  95. package/dist/browser/paths.js +2 -2
  96. package/dist/build-info.json +3 -3
  97. package/dist/channels/allowlist-match.js +20 -0
  98. package/dist/channels/allowlists/resolve-utils.js +65 -2
  99. package/dist/channels/chat-type.js +8 -4
  100. package/dist/channels/dock.js +127 -35
  101. package/dist/channels/draft-stream-loop.js +6 -2
  102. package/dist/channels/plugins/actions/telegram.js +42 -18
  103. package/dist/channels/plugins/allowlist-match.js +1 -1
  104. package/dist/channels/plugins/group-mentions.js +51 -41
  105. package/dist/channels/plugins/message-action-names.js +2 -0
  106. package/dist/channels/plugins/message-actions.js +24 -5
  107. package/dist/channels/plugins/normalize/discord.js +26 -4
  108. package/dist/channels/plugins/normalize/signal.js +35 -22
  109. package/dist/channels/plugins/onboarding/helpers.js +8 -26
  110. package/dist/channels/plugins/outbound/imessage.js +15 -14
  111. package/dist/channels/registry.js +20 -7
  112. package/dist/cli/acp-cli.js +7 -5
  113. package/dist/cli/browser-cli-extension.js +25 -12
  114. package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
  115. package/dist/cli/browser-cli-state.js +101 -145
  116. package/dist/cli/command-options.js +28 -0
  117. package/dist/cli/completion-cli.js +6 -6
  118. package/dist/cli/cron-cli/register.cron-add.js +25 -1
  119. package/dist/cli/cron-cli/register.cron-edit.js +44 -0
  120. package/dist/cli/cron-cli/shared.js +7 -1
  121. package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
  122. package/dist/cli/daemon-cli/lifecycle.js +23 -247
  123. package/dist/cli/daemon-cli/register-service-commands.js +25 -4
  124. package/dist/cli/daemon-cli.js +1 -0
  125. package/dist/cli/devices-cli.js +33 -20
  126. package/dist/cli/gateway-cli/register.js +37 -105
  127. package/dist/cli/gateway-cli/run.js +49 -11
  128. package/dist/cli/nodes-camera.js +59 -4
  129. package/dist/cli/nodes-cli/register.camera.js +27 -24
  130. package/dist/cli/nodes-cli/rpc.js +21 -38
  131. package/dist/cli/qr-cli.js +2 -2
  132. package/dist/cli/skills-cli.format.js +2 -2
  133. package/dist/cli/update-cli/progress.js +2 -2
  134. package/dist/cli/update-cli/restart-helper.js +28 -7
  135. package/dist/cli/update-cli/shared.js +7 -7
  136. package/dist/cli/update-cli/status.js +1 -1
  137. package/dist/cli/update-cli/update-command.js +14 -8
  138. package/dist/cli/update-cli/wizard.js +2 -2
  139. package/dist/cli/update-cli.js +21 -1027
  140. package/dist/commands/auth-choice.apply.anthropic.js +10 -2
  141. package/dist/commands/channels/add-mutators.js +3 -35
  142. package/dist/commands/channels/add.js +39 -51
  143. package/dist/commands/config-validation.js +1 -1
  144. package/dist/commands/configure.gateway-auth.js +52 -15
  145. package/dist/commands/configure.gateway.js +84 -40
  146. package/dist/commands/doctor-completion.js +3 -3
  147. package/dist/commands/doctor-config-flow.js +536 -16
  148. package/dist/commands/doctor-gateway-services.js +103 -79
  149. package/dist/commands/doctor-memory-search.js +9 -9
  150. package/dist/commands/doctor-platform-notes.js +57 -30
  151. package/dist/commands/doctor-prompter.js +26 -15
  152. package/dist/commands/doctor-session-locks.js +1 -1
  153. package/dist/commands/doctor.js +21 -9
  154. package/dist/commands/model-picker.js +120 -95
  155. package/dist/commands/models/set.js +2 -21
  156. package/dist/commands/models/shared.js +65 -37
  157. package/dist/commands/onboard-helpers.js +81 -39
  158. package/dist/commands/openai-codex-oauth.js +1 -1
  159. package/dist/commands/sessions.js +52 -53
  160. package/dist/commands/status.summary.js +52 -34
  161. package/dist/commands/test-wizard-helpers.js +2 -2
  162. package/dist/config/defaults.js +79 -42
  163. package/dist/config/group-policy.js +50 -18
  164. package/dist/config/includes.js +37 -10
  165. package/dist/config/schema.help.js +5 -4
  166. package/dist/config/schema.hints.js +2 -2
  167. package/dist/config/schema.labels.js +1 -0
  168. package/dist/config/sessions/group.js +12 -11
  169. package/dist/config/sessions/paths.js +137 -11
  170. package/dist/config/sessions/store.js +185 -65
  171. package/dist/config/sessions/types.js +15 -1
  172. package/dist/config/sessions.js +1 -0
  173. package/dist/config/telegram-custom-commands.js +3 -2
  174. package/dist/config/types.js +2 -0
  175. package/dist/config/zod-schema.agent-defaults.js +6 -27
  176. package/dist/config/zod-schema.agent-runtime.js +171 -79
  177. package/dist/config/zod-schema.providers-core.js +138 -65
  178. package/dist/config/zod-schema.session.js +49 -22
  179. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  180. package/dist/cron/isolated-agent/run.js +224 -57
  181. package/dist/cron/normalize.js +48 -45
  182. package/dist/cron/run-log.js +14 -0
  183. package/dist/cron/service/jobs.js +190 -28
  184. package/dist/cron/service/normalize.js +29 -11
  185. package/dist/cron/service/store.js +30 -44
  186. package/dist/cron/service/timer.js +182 -96
  187. package/dist/cron/service.js +3 -0
  188. package/dist/cron/stagger.js +37 -0
  189. package/dist/daemon/inspect.js +132 -92
  190. package/dist/daemon/runtime-paths.js +25 -4
  191. package/dist/daemon/service-audit.js +47 -16
  192. package/dist/discord/accounts.js +23 -20
  193. package/dist/discord/monitor/agent-components.js +1115 -219
  194. package/dist/discord/monitor/allow-list.js +114 -34
  195. package/dist/discord/monitor/listeners.js +204 -97
  196. package/dist/discord/monitor/message-handler.js +21 -10
  197. package/dist/discord/monitor/message-handler.preflight.js +195 -101
  198. package/dist/discord/monitor/message-handler.process.js +384 -123
  199. package/dist/discord/monitor/message-utils.js +86 -23
  200. package/dist/discord/monitor/native-command.js +77 -57
  201. package/dist/discord/monitor/provider.js +122 -117
  202. package/dist/discord/monitor/reply-context.js +20 -16
  203. package/dist/discord/monitor/reply-delivery.js +40 -8
  204. package/dist/discord/monitor/rest-fetch.js +22 -0
  205. package/dist/discord/monitor/threading.js +117 -24
  206. package/dist/discord/send.js +2 -1
  207. package/dist/discord/send.outbound.js +124 -11
  208. package/dist/discord/send.shared.js +112 -72
  209. package/dist/discord/voice-message.js +3 -3
  210. package/dist/gateway/auth.js +119 -44
  211. package/dist/gateway/call.js +76 -34
  212. package/dist/gateway/channel-health-monitor.js +57 -50
  213. package/dist/gateway/client.js +63 -29
  214. package/dist/gateway/control-ui-contract.js +1 -1
  215. package/dist/gateway/gateway-config-prompts.shared.js +2 -2
  216. package/dist/gateway/net.js +109 -1
  217. package/dist/gateway/protocol/index.js +5 -8
  218. package/dist/gateway/protocol/schema/agent.js +19 -1
  219. package/dist/gateway/protocol/schema/channels.js +21 -0
  220. package/dist/gateway/protocol/schema/cron.js +43 -30
  221. package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
  222. package/dist/gateway/protocol/schema/sessions.js +5 -1
  223. package/dist/gateway/protocol/schema.js +0 -1
  224. package/dist/gateway/server/presence-events.js +12 -0
  225. package/dist/gateway/server/ws-connection/message-handler.js +203 -212
  226. package/dist/gateway/server/ws-connection.js +58 -21
  227. package/dist/gateway/server-broadcast.js +18 -13
  228. package/dist/gateway/server-cron.js +177 -10
  229. package/dist/gateway/server-methods/agent-job.js +131 -38
  230. package/dist/gateway/server-methods/send.js +60 -14
  231. package/dist/gateway/server-methods/sessions.js +160 -96
  232. package/dist/gateway/server-methods/system.js +5 -7
  233. package/dist/gateway/server-methods-list.js +8 -0
  234. package/dist/gateway/server-methods.js +24 -8
  235. package/dist/gateway/server-node-events.js +278 -68
  236. package/dist/gateway/session-utils.fs.js +316 -75
  237. package/dist/gateway/session-utils.js +224 -70
  238. package/dist/gateway/sessions-patch.js +63 -20
  239. package/dist/gateway/test-temp-config.js +1 -1
  240. package/dist/gateway/tools-invoke-http.js +118 -70
  241. package/dist/gateway/ws-log.js +135 -107
  242. package/dist/hooks/frontmatter.js +36 -82
  243. package/dist/hooks/install.js +149 -139
  244. package/dist/hooks/internal-hooks.js +29 -4
  245. package/dist/hooks/plugin-hooks.js +2 -1
  246. package/dist/imessage/monitor/deliver.js +10 -4
  247. package/dist/imessage/monitor/monitor-provider.js +138 -375
  248. package/dist/imessage/monitor/runtime.js +4 -8
  249. package/dist/imessage/send.js +65 -19
  250. package/dist/infra/exec-approvals-allowlist.js +7 -0
  251. package/dist/infra/exec-approvals.js +35 -920
  252. package/dist/infra/exec-safe-bin-trust.js +64 -0
  253. package/dist/infra/heartbeat-runner.js +207 -134
  254. package/dist/infra/heartbeat-wake.js +183 -22
  255. package/dist/infra/install-source-utils.js +47 -0
  256. package/dist/infra/net/ssrf.js +170 -36
  257. package/dist/infra/outbound/deliver.js +224 -58
  258. package/dist/infra/outbound/message-action-spec.js +12 -5
  259. package/dist/infra/outbound/outbound-session.js +27 -25
  260. package/dist/infra/poolbot-root.js +32 -22
  261. package/dist/infra/ports.js +14 -11
  262. package/dist/infra/skills-remote.js +48 -37
  263. package/dist/infra/system-events.js +25 -11
  264. package/dist/infra/system-presence.js +26 -33
  265. package/dist/infra/tmp-poolbot-dir.js +81 -2
  266. package/dist/infra/wsl.js +37 -1
  267. package/dist/line/bot-message-context.js +163 -191
  268. package/dist/logging/subsystem.js +59 -22
  269. package/dist/markdown/ir.js +124 -50
  270. package/dist/media/store.js +1 -1
  271. package/dist/media-understanding/runner.entries.js +42 -25
  272. package/dist/media-understanding/runner.js +53 -488
  273. package/dist/memory/embeddings-gemini.js +53 -38
  274. package/dist/memory/manager-embedding-ops.js +48 -69
  275. package/dist/pairing/pairing-store.js +178 -119
  276. package/dist/plugin-sdk/index.js +34 -6
  277. package/dist/plugins/hooks.js +135 -14
  278. package/dist/plugins/install.js +190 -152
  279. package/dist/polls.js +11 -0
  280. package/dist/routing/resolve-route.js +190 -56
  281. package/dist/routing/session-key.js +38 -22
  282. package/dist/runtime.js +35 -9
  283. package/dist/security/audit-channel.js +1 -1
  284. package/dist/sessions/session-key-utils.js +29 -11
  285. package/dist/shared/frontmatter.js +5 -5
  286. package/dist/shared/node-list-types.js +1 -0
  287. package/dist/shared/string-normalization.js +15 -0
  288. package/dist/signal/monitor/event-handler.js +68 -36
  289. package/dist/signal/send.js +29 -37
  290. package/dist/slack/monitor/allow-list.js +10 -11
  291. package/dist/slack/monitor/commands.js +14 -3
  292. package/dist/slack/monitor/events/interactions.js +4 -4
  293. package/dist/slack/monitor/media.js +224 -16
  294. package/dist/slack/monitor/message-handler/dispatch.js +247 -13
  295. package/dist/slack/monitor/message-handler/prepare.js +128 -45
  296. package/dist/slack/monitor/slash.js +357 -144
  297. package/dist/slack/streaming.js +77 -0
  298. package/dist/telegram/accounts.js +40 -13
  299. package/dist/telegram/allowed-updates.js +3 -0
  300. package/dist/telegram/bot/delivery.js +129 -66
  301. package/dist/telegram/bot/helpers.js +136 -122
  302. package/dist/telegram/bot-handlers.js +600 -339
  303. package/dist/telegram/bot-message-context.js +115 -73
  304. package/dist/telegram/bot-message-dispatch.js +235 -104
  305. package/dist/telegram/bot-native-command-menu.js +3 -1
  306. package/dist/telegram/bot-native-commands.js +213 -193
  307. package/dist/telegram/bot.js +24 -132
  308. package/dist/telegram/draft-stream.js +84 -75
  309. package/dist/telegram/format.js +150 -6
  310. package/dist/telegram/send.js +415 -255
  311. package/dist/telegram/targets.js +21 -2
  312. package/dist/telegram/update-offset-store.js +19 -3
  313. package/dist/terminal/restore.js +5 -2
  314. package/dist/test-utils/fetch-mock.js +5 -0
  315. package/dist/version.js +18 -5
  316. package/dist/web/auto-reply/monitor/broadcast.js +7 -3
  317. package/dist/web/auto-reply/monitor/on-message.js +6 -3
  318. package/dist/web/inbound/media.js +34 -8
  319. package/dist/web/inbound/monitor.js +34 -17
  320. package/dist/web/inbound/send-api.js +18 -17
  321. package/dist/web/outbound.js +12 -5
  322. package/dist/wizard/clack-prompter.js +40 -7
  323. package/extensions/bluebubbles/package.json +1 -1
  324. package/extensions/copilot-proxy/package.json +1 -1
  325. package/extensions/device-pair/index.ts +2 -2
  326. package/extensions/diagnostics-otel/package.json +1 -1
  327. package/extensions/discord/package.json +1 -1
  328. package/extensions/feishu/package.json +1 -1
  329. package/extensions/google-antigravity-auth/package.json +1 -1
  330. package/extensions/google-gemini-cli-auth/package.json +1 -1
  331. package/extensions/googlechat/package.json +1 -1
  332. package/extensions/imessage/package.json +1 -1
  333. package/extensions/irc/package.json +1 -1
  334. package/extensions/irc/src/accounts.ts +1 -1
  335. package/extensions/irc/src/onboarding.ts +4 -4
  336. package/extensions/line/package.json +1 -1
  337. package/extensions/llm-task/package.json +1 -1
  338. package/extensions/lobster/package.json +1 -1
  339. package/extensions/matrix/CHANGELOG.md +10 -0
  340. package/extensions/matrix/package.json +1 -1
  341. package/extensions/mattermost/package.json +1 -1
  342. package/extensions/memory-core/package.json +1 -1
  343. package/extensions/memory-lancedb/package.json +1 -1
  344. package/extensions/minimax-portal-auth/package.json +1 -1
  345. package/extensions/msteams/CHANGELOG.md +10 -0
  346. package/extensions/msteams/package.json +1 -1
  347. package/extensions/nextcloud-talk/package.json +1 -1
  348. package/extensions/nostr/CHANGELOG.md +10 -0
  349. package/extensions/nostr/package.json +1 -1
  350. package/extensions/open-prose/package.json +1 -1
  351. package/extensions/openai-codex-auth/package.json +1 -1
  352. package/extensions/signal/package.json +1 -1
  353. package/extensions/slack/package.json +1 -1
  354. package/extensions/telegram/package.json +1 -1
  355. package/extensions/tlon/package.json +1 -1
  356. package/extensions/twitch/CHANGELOG.md +10 -0
  357. package/extensions/twitch/package.json +1 -1
  358. package/extensions/voice-call/CHANGELOG.md +10 -0
  359. package/extensions/voice-call/package.json +1 -1
  360. package/extensions/whatsapp/package.json +1 -1
  361. package/extensions/zalo/CHANGELOG.md +10 -0
  362. package/extensions/zalo/package.json +1 -1
  363. package/extensions/zalouser/CHANGELOG.md +10 -0
  364. package/extensions/zalouser/package.json +1 -1
  365. package/package.json +1 -1
  366. package/skills/apple-reminders/SKILL.md +100 -49
  367. package/skills/coding-agent/SKILL.md +34 -28
  368. package/skills/github/SKILL.md +131 -16
  369. package/skills/imsg/SKILL.md +112 -15
  370. package/skills/openhue/SKILL.md +101 -19
  371. package/skills/tmux/SKILL.md +111 -79
  372. package/skills/weather/SKILL.md +88 -25
  373. package/dist/agents/openclaw-tools.js +0 -151
  374. package/dist/agents/tool-security.js +0 -96
  375. package/dist/gateway/url-validation.js +0 -94
  376. package/dist/infra/openclaw-root.js +0 -109
  377. package/dist/infra/tmp-openclaw-dir.js +0 -81
  378. package/dist/media/path-sanitization.js +0 -78
@@ -1,29 +1,25 @@
1
1
  import { resolveChannelGroupRequireMention, resolveChannelGroupToolsPolicy, resolveToolsBySender, } from "../../config/group-policy.js";
2
+ import { normalizeHyphenSlug } from "../../shared/string-normalization.js";
2
3
  import { resolveSlackAccount } from "../../slack/accounts.js";
3
4
  function normalizeDiscordSlug(value) {
4
- if (!value)
5
+ if (!value) {
5
6
  return "";
7
+ }
6
8
  let text = value.trim().toLowerCase();
7
- if (!text)
9
+ if (!text) {
8
10
  return "";
11
+ }
9
12
  text = text.replace(/^[@#]+/, "");
10
13
  text = text.replace(/[\s_]+/g, "-");
11
14
  text = text.replace(/[^a-z0-9-]+/g, "-");
12
15
  text = text.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
13
16
  return text;
14
17
  }
15
- function normalizeSlackSlug(raw) {
16
- const trimmed = raw?.trim().toLowerCase() ?? "";
17
- if (!trimmed)
18
- return "";
19
- const dashed = trimmed.replace(/\s+/g, "-");
20
- const cleaned = dashed.replace(/[^a-z0-9#@._+-]+/g, "-");
21
- return cleaned.replace(/-{2,}/g, "-").replace(/^[-.]+|[-.]+$/g, "");
22
- }
23
18
  function parseTelegramGroupId(value) {
24
19
  const raw = value?.trim() ?? "";
25
- if (!raw)
20
+ if (!raw) {
26
21
  return { chatId: undefined, topicId: undefined };
22
+ }
27
23
  const parts = raw.split(":").filter(Boolean);
28
24
  if (parts.length >= 3 &&
29
25
  parts[1] === "topic" &&
@@ -38,8 +34,9 @@ function parseTelegramGroupId(value) {
38
34
  }
39
35
  function resolveTelegramRequireMention(params) {
40
36
  const { cfg, chatId, topicId } = params;
41
- if (!chatId)
37
+ if (!chatId) {
42
38
  return undefined;
39
+ }
43
40
  const groupConfig = cfg.channels?.telegram?.groups?.[chatId];
44
41
  const groupDefault = cfg.channels?.telegram?.groups?.["*"];
45
42
  const topicConfig = topicId && groupConfig?.topics ? groupConfig.topics[topicId] : undefined;
@@ -59,21 +56,37 @@ function resolveTelegramRequireMention(params) {
59
56
  return undefined;
60
57
  }
61
58
  function resolveDiscordGuildEntry(guilds, groupSpace) {
62
- if (!guilds || Object.keys(guilds).length === 0)
59
+ if (!guilds || Object.keys(guilds).length === 0) {
63
60
  return null;
61
+ }
64
62
  const space = groupSpace?.trim() ?? "";
65
- if (space && guilds[space])
63
+ if (space && guilds[space]) {
66
64
  return guilds[space];
65
+ }
67
66
  const normalized = normalizeDiscordSlug(space);
68
- if (normalized && guilds[normalized])
67
+ if (normalized && guilds[normalized]) {
69
68
  return guilds[normalized];
69
+ }
70
70
  if (normalized) {
71
71
  const match = Object.values(guilds).find((entry) => normalizeDiscordSlug(entry?.slug ?? undefined) === normalized);
72
- if (match)
72
+ if (match) {
73
73
  return match;
74
+ }
74
75
  }
75
76
  return guilds["*"] ?? null;
76
77
  }
78
+ function resolveDiscordChannelEntry(channelEntries, params) {
79
+ if (!channelEntries || Object.keys(channelEntries).length === 0) {
80
+ return undefined;
81
+ }
82
+ const groupChannel = params.groupChannel;
83
+ const channelSlug = normalizeDiscordSlug(groupChannel);
84
+ return ((params.groupId ? channelEntries[params.groupId] : undefined) ??
85
+ (channelSlug
86
+ ? (channelEntries[channelSlug] ?? channelEntries[`#${channelSlug}`])
87
+ : undefined) ??
88
+ (groupChannel ? channelEntries[normalizeDiscordSlug(groupChannel)] : undefined));
89
+ }
77
90
  export function resolveTelegramGroupRequireMention(params) {
78
91
  const { chatId, topicId } = parseTelegramGroupId(params.groupId);
79
92
  const requireMention = resolveTelegramRequireMention({
@@ -81,8 +94,9 @@ export function resolveTelegramGroupRequireMention(params) {
81
94
  chatId,
82
95
  topicId,
83
96
  });
84
- if (typeof requireMention === "boolean")
97
+ if (typeof requireMention === "boolean") {
85
98
  return requireMention;
99
+ }
86
100
  return resolveChannelGroupRequireMention({
87
101
  cfg: params.cfg,
88
102
  channel: "telegram",
@@ -110,13 +124,7 @@ export function resolveDiscordGroupRequireMention(params) {
110
124
  const guildEntry = resolveDiscordGuildEntry(params.cfg.channels?.discord?.guilds, params.groupSpace);
111
125
  const channelEntries = guildEntry?.channels;
112
126
  if (channelEntries && Object.keys(channelEntries).length > 0) {
113
- const groupChannel = params.groupChannel;
114
- const channelSlug = normalizeDiscordSlug(groupChannel);
115
- const entry = (params.groupId ? channelEntries[params.groupId] : undefined) ??
116
- (channelSlug
117
- ? (channelEntries[channelSlug] ?? channelEntries[`#${channelSlug}`])
118
- : undefined) ??
119
- (groupChannel ? channelEntries[normalizeDiscordSlug(groupChannel)] : undefined);
127
+ const entry = resolveDiscordChannelEntry(channelEntries, params);
120
128
  if (entry && typeof entry.requireMention === "boolean") {
121
129
  return entry.requireMention;
122
130
  }
@@ -153,12 +161,13 @@ export function resolveSlackGroupRequireMention(params) {
153
161
  });
154
162
  const channels = account.channels ?? {};
155
163
  const keys = Object.keys(channels);
156
- if (keys.length === 0)
164
+ if (keys.length === 0) {
157
165
  return true;
166
+ }
158
167
  const channelId = params.groupId?.trim();
159
168
  const groupChannel = params.groupChannel;
160
169
  const channelName = groupChannel?.replace(/^#/, "");
161
- const normalizedName = normalizeSlackSlug(channelName);
170
+ const normalizedName = normalizeHyphenSlug(channelName);
162
171
  const candidates = [
163
172
  channelId ?? "",
164
173
  channelName ? `#${channelName}` : "",
@@ -228,13 +237,7 @@ export function resolveDiscordGroupToolPolicy(params) {
228
237
  const guildEntry = resolveDiscordGuildEntry(params.cfg.channels?.discord?.guilds, params.groupSpace);
229
238
  const channelEntries = guildEntry?.channels;
230
239
  if (channelEntries && Object.keys(channelEntries).length > 0) {
231
- const groupChannel = params.groupChannel;
232
- const channelSlug = normalizeDiscordSlug(groupChannel);
233
- const entry = (params.groupId ? channelEntries[params.groupId] : undefined) ??
234
- (channelSlug
235
- ? (channelEntries[channelSlug] ?? channelEntries[`#${channelSlug}`])
236
- : undefined) ??
237
- (groupChannel ? channelEntries[normalizeDiscordSlug(groupChannel)] : undefined);
240
+ const entry = resolveDiscordChannelEntry(channelEntries, params);
238
241
  const senderPolicy = resolveToolsBySender({
239
242
  toolsBySender: entry?.toolsBySender,
240
243
  senderId: params.senderId,
@@ -242,10 +245,12 @@ export function resolveDiscordGroupToolPolicy(params) {
242
245
  senderUsername: params.senderUsername,
243
246
  senderE164: params.senderE164,
244
247
  });
245
- if (senderPolicy)
248
+ if (senderPolicy) {
246
249
  return senderPolicy;
247
- if (entry?.tools)
250
+ }
251
+ if (entry?.tools) {
248
252
  return entry.tools;
253
+ }
249
254
  }
250
255
  const guildSenderPolicy = resolveToolsBySender({
251
256
  toolsBySender: guildEntry?.toolsBySender,
@@ -254,10 +259,12 @@ export function resolveDiscordGroupToolPolicy(params) {
254
259
  senderUsername: params.senderUsername,
255
260
  senderE164: params.senderE164,
256
261
  });
257
- if (guildSenderPolicy)
262
+ if (guildSenderPolicy) {
258
263
  return guildSenderPolicy;
259
- if (guildEntry?.tools)
264
+ }
265
+ if (guildEntry?.tools) {
260
266
  return guildEntry.tools;
267
+ }
261
268
  return undefined;
262
269
  }
263
270
  export function resolveSlackGroupToolPolicy(params) {
@@ -267,12 +274,13 @@ export function resolveSlackGroupToolPolicy(params) {
267
274
  });
268
275
  const channels = account.channels ?? {};
269
276
  const keys = Object.keys(channels);
270
- if (keys.length === 0)
277
+ if (keys.length === 0) {
271
278
  return undefined;
279
+ }
272
280
  const channelId = params.groupId?.trim();
273
281
  const groupChannel = params.groupChannel;
274
282
  const channelName = groupChannel?.replace(/^#/, "");
275
- const normalizedName = normalizeSlackSlug(channelName);
283
+ const normalizedName = normalizeHyphenSlug(channelName);
276
284
  const candidates = [
277
285
  channelId ?? "",
278
286
  channelName ? `#${channelName}` : "",
@@ -294,10 +302,12 @@ export function resolveSlackGroupToolPolicy(params) {
294
302
  senderUsername: params.senderUsername,
295
303
  senderE164: params.senderE164,
296
304
  });
297
- if (senderPolicy)
305
+ if (senderPolicy) {
298
306
  return senderPolicy;
299
- if (resolved?.tools)
307
+ }
308
+ if (resolved?.tools) {
300
309
  return resolved.tools;
310
+ }
301
311
  return undefined;
302
312
  }
303
313
  export function resolveBlueBubblesGroupToolPolicy(params) {
@@ -42,10 +42,12 @@ export const CHANNEL_MESSAGE_ACTION_NAMES = [
42
42
  "category-create",
43
43
  "category-edit",
44
44
  "category-delete",
45
+ "topic-create",
45
46
  "voice-status",
46
47
  "event-list",
47
48
  "event-create",
48
49
  "timeout",
49
50
  "kick",
50
51
  "ban",
52
+ "set-presence",
51
53
  ];
@@ -3,31 +3,50 @@ export function listChannelMessageActions(cfg) {
3
3
  const actions = new Set(["send", "broadcast"]);
4
4
  for (const plugin of listChannelPlugins()) {
5
5
  const list = plugin.actions?.listActions?.({ cfg });
6
- if (!list)
6
+ if (!list) {
7
7
  continue;
8
- for (const action of list)
8
+ }
9
+ for (const action of list) {
9
10
  actions.add(action);
11
+ }
10
12
  }
11
13
  return Array.from(actions);
12
14
  }
13
15
  export function supportsChannelMessageButtons(cfg) {
14
16
  for (const plugin of listChannelPlugins()) {
15
- if (plugin.actions?.supportsButtons?.({ cfg }))
17
+ if (plugin.actions?.supportsButtons?.({ cfg })) {
16
18
  return true;
19
+ }
17
20
  }
18
21
  return false;
19
22
  }
23
+ export function supportsChannelMessageButtonsForChannel(params) {
24
+ if (!params.channel) {
25
+ return false;
26
+ }
27
+ const plugin = getChannelPlugin(params.channel);
28
+ return plugin?.actions?.supportsButtons?.({ cfg: params.cfg }) === true;
29
+ }
20
30
  export function supportsChannelMessageCards(cfg) {
21
31
  for (const plugin of listChannelPlugins()) {
22
- if (plugin.actions?.supportsCards?.({ cfg }))
32
+ if (plugin.actions?.supportsCards?.({ cfg })) {
23
33
  return true;
34
+ }
24
35
  }
25
36
  return false;
26
37
  }
38
+ export function supportsChannelMessageCardsForChannel(params) {
39
+ if (!params.channel) {
40
+ return false;
41
+ }
42
+ const plugin = getChannelPlugin(params.channel);
43
+ return plugin?.actions?.supportsCards?.({ cfg: params.cfg }) === true;
44
+ }
27
45
  export async function dispatchChannelMessageAction(ctx) {
28
46
  const plugin = getChannelPlugin(ctx.channel);
29
- if (!plugin?.actions?.handleAction)
47
+ if (!plugin?.actions?.handleAction) {
30
48
  return null;
49
+ }
31
50
  if (plugin.actions.supportsAction && !plugin.actions.supportsAction({ action: ctx.action })) {
32
51
  return null;
33
52
  }
@@ -4,15 +4,37 @@ export function normalizeDiscordMessagingTarget(raw) {
4
4
  const target = parseDiscordTarget(raw, { defaultKind: "channel" });
5
5
  return target?.normalized;
6
6
  }
7
+ /**
8
+ * Normalize a Discord outbound target for delivery. Bare numeric IDs are
9
+ * prefixed with "channel:" to avoid the ambiguous-target error in
10
+ * parseDiscordTarget. All other formats pass through unchanged.
11
+ */
12
+ export function normalizeDiscordOutboundTarget(to) {
13
+ const trimmed = to?.trim();
14
+ if (!trimmed) {
15
+ return {
16
+ ok: false,
17
+ error: new Error('Discord recipient is required. Use "channel:<id>" for channels or "user:<id>" for DMs.'),
18
+ };
19
+ }
20
+ if (/^\d+$/.test(trimmed)) {
21
+ return { ok: true, to: `channel:${trimmed}` };
22
+ }
23
+ return { ok: true, to: trimmed };
24
+ }
7
25
  export function looksLikeDiscordTargetId(raw) {
8
26
  const trimmed = raw.trim();
9
- if (!trimmed)
27
+ if (!trimmed) {
10
28
  return false;
11
- if (/^<@!?\d+>$/.test(trimmed))
29
+ }
30
+ if (/^<@!?\d+>$/.test(trimmed)) {
12
31
  return true;
13
- if (/^(user|channel|discord):/i.test(trimmed))
32
+ }
33
+ if (/^(user|channel|discord):/i.test(trimmed)) {
14
34
  return true;
15
- if (/^\d{6,}$/.test(trimmed))
35
+ }
36
+ if (/^\d{6,}$/.test(trimmed)) {
16
37
  return true;
38
+ }
17
39
  return false;
18
40
  }
@@ -1,17 +1,20 @@
1
1
  export function normalizeSignalMessagingTarget(raw) {
2
2
  const trimmed = raw.trim();
3
- if (!trimmed)
3
+ if (!trimmed) {
4
4
  return undefined;
5
+ }
5
6
  let normalized = trimmed;
6
7
  if (normalized.toLowerCase().startsWith("signal:")) {
7
8
  normalized = normalized.slice("signal:".length).trim();
8
9
  }
9
- if (!normalized)
10
+ if (!normalized) {
10
11
  return undefined;
12
+ }
11
13
  const lower = normalized.toLowerCase();
12
14
  if (lower.startsWith("group:")) {
13
15
  const id = normalized.slice("group:".length).trim();
14
- return id ? `group:${id}`.toLowerCase() : undefined;
16
+ // Signal group IDs are base64-like and case-sensitive. Preserve ID casing.
17
+ return id ? `group:${id}` : undefined;
15
18
  }
16
19
  if (lower.startsWith("username:")) {
17
20
  const id = normalized.slice("username:".length).trim();
@@ -30,23 +33,33 @@ export function normalizeSignalMessagingTarget(raw) {
30
33
  // UUID pattern for signal-cli recipient IDs
31
34
  const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
32
35
  const UUID_COMPACT_PATTERN = /^[0-9a-f]{32}$/i;
33
- export function looksLikeSignalTargetId(raw) {
34
- const trimmed = raw.trim();
35
- if (!trimmed)
36
- return false;
37
- if (/^(signal:)?(group:|username:|u:)/i.test(trimmed))
38
- return true;
39
- if (/^(signal:)?uuid:/i.test(trimmed)) {
40
- const stripped = trimmed
41
- .replace(/^signal:/i, "")
42
- .replace(/^uuid:/i, "")
43
- .trim();
44
- if (!stripped)
45
- return false;
46
- return UUID_PATTERN.test(stripped) || UUID_COMPACT_PATTERN.test(stripped);
47
- }
48
- // Accept UUIDs (used by signal-cli for reactions)
49
- if (UUID_PATTERN.test(trimmed) || UUID_COMPACT_PATTERN.test(trimmed))
50
- return true;
51
- return /^\+?\d{3,}$/.test(trimmed);
36
+ export function looksLikeSignalTargetId(raw, normalized) {
37
+ const candidates = [raw, normalized ?? ""].map((value) => value.trim()).filter(Boolean);
38
+ for (const candidate of candidates) {
39
+ if (/^(signal:)?(group:|username:|u:)/i.test(candidate)) {
40
+ return true;
41
+ }
42
+ if (/^(signal:)?uuid:/i.test(candidate)) {
43
+ const stripped = candidate
44
+ .replace(/^signal:/i, "")
45
+ .replace(/^uuid:/i, "")
46
+ .trim();
47
+ if (!stripped) {
48
+ continue;
49
+ }
50
+ if (UUID_PATTERN.test(stripped) || UUID_COMPACT_PATTERN.test(stripped)) {
51
+ return true;
52
+ }
53
+ continue;
54
+ }
55
+ const withoutSignalPrefix = candidate.replace(/^signal:/i, "").trim();
56
+ // Accept UUIDs (used by signal-cli for reactions)
57
+ if (UUID_PATTERN.test(withoutSignalPrefix) || UUID_COMPACT_PATTERN.test(withoutSignalPrefix)) {
58
+ return true;
59
+ }
60
+ if (/^\+?\d{3,}$/.test(withoutSignalPrefix)) {
61
+ return true;
62
+ }
63
+ }
64
+ return false;
52
65
  }
@@ -1,33 +1,15 @@
1
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../routing/session-key.js";
1
+ import { promptAccountId as promptAccountIdSdk } from "../../../plugin-sdk/onboarding.js";
2
2
  export const promptAccountId = async (params) => {
3
- const existingIds = params.listAccountIds(params.cfg);
4
- const initial = params.currentId?.trim() || params.defaultAccountId || DEFAULT_ACCOUNT_ID;
5
- const choice = (await params.prompter.select({
6
- message: `${params.label} account`,
7
- options: [
8
- ...existingIds.map((id) => ({
9
- value: id,
10
- label: id === DEFAULT_ACCOUNT_ID ? "default (primary)" : id,
11
- })),
12
- { value: "__new__", label: "Add a new account" },
13
- ],
14
- initialValue: initial,
15
- }));
16
- if (choice !== "__new__")
17
- return normalizeAccountId(choice);
18
- const entered = await params.prompter.text({
19
- message: `New ${params.label} account id`,
20
- validate: (value) => (value?.trim() ? undefined : "Required"),
21
- });
22
- const normalized = normalizeAccountId(String(entered));
23
- if (String(entered).trim() !== normalized) {
24
- await params.prompter.note(`Normalized account id to "${normalized}".`, `${params.label} account`);
25
- }
26
- return normalized;
3
+ return await promptAccountIdSdk(params);
27
4
  };
28
5
  export function addWildcardAllowFrom(allowFrom) {
29
6
  const next = (allowFrom ?? []).map((v) => String(v).trim()).filter(Boolean);
30
- if (!next.includes("*"))
7
+ if (!next.includes("*")) {
31
8
  next.push("*");
9
+ }
32
10
  return next;
33
11
  }
12
+ export function mergeAllowFromEntries(current, additions) {
13
+ const merged = [...(current ?? []), ...additions].map((v) => String(v).trim()).filter(Boolean);
14
+ return [...new Set(merged)];
15
+ }
@@ -1,37 +1,38 @@
1
1
  import { chunkText } from "../../../auto-reply/chunk.js";
2
2
  import { sendMessageIMessage } from "../../../imessage/send.js";
3
3
  import { resolveChannelMediaMaxBytes } from "../media-limits.js";
4
+ function resolveIMessageMaxBytes(params) {
5
+ return resolveChannelMediaMaxBytes({
6
+ cfg: params.cfg,
7
+ resolveChannelLimitMb: ({ cfg, accountId }) => cfg.channels?.imessage?.accounts?.[accountId]?.mediaMaxMb ??
8
+ cfg.channels?.imessage?.mediaMaxMb,
9
+ accountId: params.accountId,
10
+ });
11
+ }
4
12
  export const imessageOutbound = {
5
13
  deliveryMode: "direct",
6
14
  chunker: chunkText,
7
15
  chunkerMode: "text",
8
16
  textChunkLimit: 4000,
9
- sendText: async ({ cfg, to, text, accountId, deps }) => {
17
+ sendText: async ({ cfg, to, text, accountId, deps, replyToId }) => {
10
18
  const send = deps?.sendIMessage ?? sendMessageIMessage;
11
- const maxBytes = resolveChannelMediaMaxBytes({
12
- cfg,
13
- resolveChannelLimitMb: ({ cfg, accountId }) => cfg.channels?.imessage?.accounts?.[accountId]?.mediaMaxMb ??
14
- cfg.channels?.imessage?.mediaMaxMb,
15
- accountId,
16
- });
19
+ const maxBytes = resolveIMessageMaxBytes({ cfg, accountId });
17
20
  const result = await send(to, text, {
18
21
  maxBytes,
19
22
  accountId: accountId ?? undefined,
23
+ replyToId: replyToId ?? undefined,
20
24
  });
21
25
  return { channel: "imessage", ...result };
22
26
  },
23
- sendMedia: async ({ cfg, to, text, mediaUrl, accountId, deps }) => {
27
+ sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, accountId, deps, replyToId }) => {
24
28
  const send = deps?.sendIMessage ?? sendMessageIMessage;
25
- const maxBytes = resolveChannelMediaMaxBytes({
26
- cfg,
27
- resolveChannelLimitMb: ({ cfg, accountId }) => cfg.channels?.imessage?.accounts?.[accountId]?.mediaMaxMb ??
28
- cfg.channels?.imessage?.mediaMaxMb,
29
- accountId,
30
- });
29
+ const maxBytes = resolveIMessageMaxBytes({ cfg, accountId });
31
30
  const result = await send(to, text, {
32
31
  mediaUrl,
33
32
  maxBytes,
34
33
  accountId: accountId ?? undefined,
34
+ replyToId: replyToId ?? undefined,
35
+ mediaLocalRoots,
35
36
  });
36
37
  return { channel: "imessage", ...result };
37
38
  },
@@ -5,6 +5,7 @@ export const CHAT_CHANNEL_ORDER = [
5
5
  "telegram",
6
6
  "whatsapp",
7
7
  "discord",
8
+ "irc",
8
9
  "googlechat",
9
10
  "slack",
10
11
  "signal",
@@ -12,7 +13,7 @@ export const CHAT_CHANNEL_ORDER = [
12
13
  ];
13
14
  export const CHANNEL_IDS = [...CHAT_CHANNEL_ORDER];
14
15
  export const DEFAULT_CHAT_CHANNEL = "whatsapp";
15
- const WEBSITE_URL = "https://molt.bot";
16
+ const WEBSITE_URL = "https://poolbot.dev";
16
17
  const CHAT_CHANNEL_META = {
17
18
  telegram: {
18
19
  id: "telegram",
@@ -47,6 +48,16 @@ const CHAT_CHANNEL_META = {
47
48
  blurb: "very well supported right now.",
48
49
  systemImage: "bubble.left.and.bubble.right",
49
50
  },
51
+ irc: {
52
+ id: "irc",
53
+ label: "IRC",
54
+ selectionLabel: "IRC (Server + Nick)",
55
+ detailLabel: "IRC",
56
+ docsPath: "/channels/irc",
57
+ docsLabel: "irc",
58
+ blurb: "classic IRC networks with DM/channel routing and pairing controls.",
59
+ systemImage: "network",
60
+ },
50
61
  googlechat: {
51
62
  id: "googlechat",
52
63
  label: "Google Chat",
@@ -90,6 +101,7 @@ const CHAT_CHANNEL_META = {
90
101
  };
91
102
  export const CHAT_CHANNEL_ALIASES = {
92
103
  imsg: "imessage",
104
+ "internet-relay-chat": "irc",
93
105
  "google-chat": "googlechat",
94
106
  gchat: "googlechat",
95
107
  };
@@ -108,12 +120,11 @@ export function getChatChannelMeta(id) {
108
120
  }
109
121
  export function normalizeChatChannelId(raw) {
110
122
  const normalized = normalizeChannelKey(raw);
111
- if (!normalized)
123
+ if (!normalized) {
112
124
  return null;
125
+ }
113
126
  const resolved = CHAT_CHANNEL_ALIASES[normalized] ?? normalized;
114
- return CHAT_CHANNEL_ORDER.includes(resolved)
115
- ? resolved
116
- : null;
127
+ return CHAT_CHANNEL_ORDER.includes(resolved) ? resolved : null;
117
128
  }
118
129
  // Channel docking: prefer this helper in shared code. Importing from
119
130
  // `src/channels/plugins/*` can eagerly load channel implementations.
@@ -126,15 +137,17 @@ export function normalizeChannelId(raw) {
126
137
  // monitors, web login, etc). The plugin registry must be initialized first.
127
138
  export function normalizeAnyChannelId(raw) {
128
139
  const key = normalizeChannelKey(raw);
129
- if (!key)
140
+ if (!key) {
130
141
  return null;
142
+ }
131
143
  const registry = requireActivePluginRegistry();
132
144
  const hit = registry.channels.find((entry) => {
133
145
  const id = String(entry.plugin.id ?? "")
134
146
  .trim()
135
147
  .toLowerCase();
136
- if (id && id === key)
148
+ if (id && id === key) {
137
149
  return true;
150
+ }
138
151
  return (entry.plugin.meta.aliases ?? []).some((alias) => alias.trim().toLowerCase() === key);
139
152
  });
140
153
  return hit?.plugin.id ?? null;
@@ -3,6 +3,7 @@ import { serveAcpGateway } from "../acp/server.js";
3
3
  import { defaultRuntime } from "../runtime.js";
4
4
  import { formatDocsLink } from "../terminal/links.js";
5
5
  import { theme } from "../terminal/theme.js";
6
+ import { inheritOptionFromParent } from "./command-options.js";
6
7
  export function registerAcpCli(program) {
7
8
  const acp = program.command("acp").description("Run an ACP bridge backed by the Gateway");
8
9
  acp
@@ -15,10 +16,10 @@ export function registerAcpCli(program) {
15
16
  .option("--reset-session", "Reset the session key before first use", false)
16
17
  .option("--no-prefix-cwd", "Do not prefix prompts with the working directory", false)
17
18
  .option("--verbose, -v", "Verbose logging to stderr", false)
18
- .addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/acp", "docs.molt.bot/cli/acp")}\n`)
19
- .action((opts) => {
19
+ .addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/acp", "docs.poolbot.dev/cli/acp")}\n`)
20
+ .action(async (opts) => {
20
21
  try {
21
- serveAcpGateway({
22
+ await serveAcpGateway({
22
23
  gatewayUrl: opts.url,
23
24
  gatewayToken: opts.token,
24
25
  gatewayPassword: opts.password,
@@ -43,14 +44,15 @@ export function registerAcpCli(program) {
43
44
  .option("--server-args <args...>", "Extra arguments for the ACP server")
44
45
  .option("--server-verbose", "Enable verbose logging on the ACP server", false)
45
46
  .option("--verbose, -v", "Verbose client logging", false)
46
- .action(async (opts) => {
47
+ .action(async (opts, command) => {
48
+ const inheritedVerbose = inheritOptionFromParent(command, "verbose");
47
49
  try {
48
50
  await runAcpClientInteractive({
49
51
  cwd: opts.cwd,
50
52
  serverCommand: opts.server,
51
53
  serverArgs: opts.serverArgs,
52
54
  serverVerbose: Boolean(opts.serverVerbose),
53
- verbose: Boolean(opts.verbose),
55
+ verbose: Boolean(opts.verbose || inheritedVerbose),
54
56
  });
55
57
  }
56
58
  catch (err) {