@poolzin/pool-bot 2026.2.21 → 2026.2.22

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 (369) hide show
  1. package/CHANGELOG.md +17 -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/diagnostics-otel/package.json +1 -1
  326. package/extensions/discord/package.json +1 -1
  327. package/extensions/feishu/package.json +1 -1
  328. package/extensions/google-antigravity-auth/package.json +1 -1
  329. package/extensions/google-gemini-cli-auth/package.json +1 -1
  330. package/extensions/googlechat/package.json +1 -1
  331. package/extensions/imessage/package.json +1 -1
  332. package/extensions/irc/package.json +1 -1
  333. package/extensions/line/package.json +1 -1
  334. package/extensions/llm-task/package.json +1 -1
  335. package/extensions/lobster/package.json +1 -1
  336. package/extensions/matrix/CHANGELOG.md +5 -0
  337. package/extensions/matrix/package.json +1 -1
  338. package/extensions/mattermost/package.json +1 -1
  339. package/extensions/memory-core/package.json +1 -1
  340. package/extensions/memory-lancedb/package.json +1 -1
  341. package/extensions/minimax-portal-auth/package.json +1 -1
  342. package/extensions/msteams/CHANGELOG.md +5 -0
  343. package/extensions/msteams/package.json +1 -1
  344. package/extensions/nextcloud-talk/package.json +1 -1
  345. package/extensions/nostr/CHANGELOG.md +5 -0
  346. package/extensions/nostr/package.json +1 -1
  347. package/extensions/open-prose/package.json +1 -1
  348. package/extensions/openai-codex-auth/package.json +1 -1
  349. package/extensions/signal/package.json +1 -1
  350. package/extensions/slack/package.json +1 -1
  351. package/extensions/telegram/package.json +1 -1
  352. package/extensions/tlon/package.json +1 -1
  353. package/extensions/twitch/CHANGELOG.md +5 -0
  354. package/extensions/twitch/package.json +1 -1
  355. package/extensions/voice-call/CHANGELOG.md +5 -0
  356. package/extensions/voice-call/package.json +1 -1
  357. package/extensions/whatsapp/package.json +1 -1
  358. package/extensions/zalo/CHANGELOG.md +5 -0
  359. package/extensions/zalo/package.json +1 -1
  360. package/extensions/zalouser/CHANGELOG.md +5 -0
  361. package/extensions/zalouser/package.json +1 -1
  362. package/package.json +1 -1
  363. package/skills/apple-reminders/SKILL.md +100 -49
  364. package/skills/coding-agent/SKILL.md +34 -28
  365. package/skills/github/SKILL.md +131 -16
  366. package/skills/imsg/SKILL.md +112 -15
  367. package/skills/openhue/SKILL.md +101 -19
  368. package/skills/tmux/SKILL.md +111 -79
  369. package/skills/weather/SKILL.md +88 -25
@@ -3,11 +3,13 @@ export function mergeAllowlist(params) {
3
3
  const merged = [];
4
4
  const push = (value) => {
5
5
  const normalized = value.trim();
6
- if (!normalized)
6
+ if (!normalized) {
7
7
  return;
8
+ }
8
9
  const key = normalized.toLowerCase();
9
- if (seen.has(key))
10
+ if (seen.has(key)) {
10
11
  return;
12
+ }
11
13
  seen.add(key);
12
14
  merged.push(normalized);
13
15
  };
@@ -19,6 +21,67 @@ export function mergeAllowlist(params) {
19
21
  }
20
22
  return merged;
21
23
  }
24
+ export function buildAllowlistResolutionSummary(resolvedUsers, opts) {
25
+ const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry]));
26
+ const resolvedOk = (entry) => Boolean(entry.resolved && entry.id);
27
+ const formatResolved = opts?.formatResolved ?? ((entry) => `${entry.input}→${entry.id}`);
28
+ const mapping = resolvedUsers.filter(resolvedOk).map(formatResolved);
29
+ const additions = resolvedUsers
30
+ .filter(resolvedOk)
31
+ .map((entry) => entry.id)
32
+ .filter((entry) => Boolean(entry));
33
+ const unresolved = resolvedUsers
34
+ .filter((entry) => !resolvedOk(entry))
35
+ .map((entry) => entry.input);
36
+ return { resolvedMap, mapping, unresolved, additions };
37
+ }
38
+ export function resolveAllowlistIdAdditions(params) {
39
+ const additions = [];
40
+ for (const entry of params.existing) {
41
+ const trimmed = String(entry).trim();
42
+ const resolved = params.resolvedMap.get(trimmed);
43
+ if (resolved?.resolved && resolved.id) {
44
+ additions.push(resolved.id);
45
+ }
46
+ }
47
+ return additions;
48
+ }
49
+ export function patchAllowlistUsersInConfigEntries(params) {
50
+ const nextEntries = { ...params.entries };
51
+ for (const [entryKey, entryConfig] of Object.entries(params.entries)) {
52
+ if (!entryConfig || typeof entryConfig !== "object") {
53
+ continue;
54
+ }
55
+ const users = entryConfig.users;
56
+ if (!Array.isArray(users) || users.length === 0) {
57
+ continue;
58
+ }
59
+ const additions = resolveAllowlistIdAdditions({
60
+ existing: users,
61
+ resolvedMap: params.resolvedMap,
62
+ });
63
+ nextEntries[entryKey] = {
64
+ ...entryConfig,
65
+ users: mergeAllowlist({ existing: users, additions }),
66
+ };
67
+ }
68
+ return nextEntries;
69
+ }
70
+ export function addAllowlistUserEntriesFromConfigEntry(target, entry) {
71
+ if (!entry || typeof entry !== "object") {
72
+ return;
73
+ }
74
+ const users = entry.users;
75
+ if (!Array.isArray(users)) {
76
+ return;
77
+ }
78
+ for (const value of users) {
79
+ const trimmed = String(value).trim();
80
+ if (trimmed && trimmed !== "*") {
81
+ target.add(trimmed);
82
+ }
83
+ }
84
+ }
22
85
  export function summarizeMapping(label, mapping, unresolved, runtime) {
23
86
  const lines = [];
24
87
  if (mapping.length > 0) {
@@ -1,12 +1,16 @@
1
1
  export function normalizeChatType(raw) {
2
2
  const value = raw?.trim().toLowerCase();
3
- if (!value)
3
+ if (!value) {
4
4
  return undefined;
5
- if (value === "direct" || value === "dm")
5
+ }
6
+ if (value === "direct" || value === "dm") {
6
7
  return "direct";
7
- if (value === "group")
8
+ }
9
+ if (value === "group") {
8
10
  return "group";
9
- if (value === "channel")
11
+ }
12
+ if (value === "channel") {
10
13
  return "channel";
14
+ }
11
15
  return undefined;
12
16
  }
@@ -1,21 +1,55 @@
1
+ import { resolveChannelGroupRequireMention, resolveChannelGroupToolsPolicy, } from "../config/group-policy.js";
1
2
  import { resolveDiscordAccount } from "../discord/accounts.js";
2
3
  import { resolveIMessageAccount } from "../imessage/accounts.js";
4
+ import { requireActivePluginRegistry } from "../plugins/runtime.js";
5
+ import { normalizeAccountId } from "../routing/session-key.js";
3
6
  import { resolveSignalAccount } from "../signal/accounts.js";
4
7
  import { resolveSlackAccount, resolveSlackReplyToMode } from "../slack/accounts.js";
5
8
  import { buildSlackThreadingToolContext } from "../slack/threading-tool-context.js";
6
9
  import { resolveTelegramAccount } from "../telegram/accounts.js";
7
- import { normalizeAccountId } from "../routing/session-key.js";
8
- import { normalizeE164 } from "../utils.js";
10
+ import { escapeRegExp, normalizeE164 } from "../utils.js";
9
11
  import { resolveWhatsAppAccount } from "../web/accounts.js";
10
12
  import { normalizeWhatsAppTarget } from "../whatsapp/normalize.js";
11
- import { requireActivePluginRegistry } from "../plugins/runtime.js";
12
13
  import { resolveDiscordGroupRequireMention, resolveDiscordGroupToolPolicy, resolveGoogleChatGroupRequireMention, resolveGoogleChatGroupToolPolicy, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy, resolveTelegramGroupRequireMention, resolveTelegramGroupToolPolicy, resolveWhatsAppGroupRequireMention, resolveWhatsAppGroupToolPolicy, } from "./plugins/group-mentions.js";
14
+ import { normalizeSignalMessagingTarget } from "./plugins/normalize/signal.js";
13
15
  import { CHAT_CHANNEL_ORDER, getChatChannelMeta } from "./registry.js";
14
16
  const formatLower = (allowFrom) => allowFrom
15
17
  .map((entry) => String(entry).trim())
16
18
  .filter(Boolean)
17
19
  .map((entry) => entry.toLowerCase());
18
- const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
20
+ const formatDiscordAllowFrom = (allowFrom) => allowFrom
21
+ .map((entry) => String(entry)
22
+ .trim()
23
+ .replace(/^<@!?/, "")
24
+ .replace(/>$/, "")
25
+ .replace(/^discord:/i, "")
26
+ .replace(/^user:/i, "")
27
+ .replace(/^pk:/i, "")
28
+ .trim()
29
+ .toLowerCase())
30
+ .filter(Boolean);
31
+ function resolveDirectOrGroupChannelId(context) {
32
+ const isDirect = context.ChatType?.toLowerCase() === "direct";
33
+ return (isDirect ? (context.From ?? context.To) : context.To)?.trim() || undefined;
34
+ }
35
+ function buildSignalThreadToolContext(params) {
36
+ const currentChannelIdRaw = resolveDirectOrGroupChannelId(params.context);
37
+ const currentChannelId = currentChannelIdRaw
38
+ ? (normalizeSignalMessagingTarget(currentChannelIdRaw) ?? currentChannelIdRaw.trim())
39
+ : undefined;
40
+ return {
41
+ currentChannelId,
42
+ currentThreadTs: params.context.ReplyToId,
43
+ hasRepliedRef: params.hasRepliedRef,
44
+ };
45
+ }
46
+ function buildIMessageThreadToolContext(params) {
47
+ return {
48
+ currentChannelId: resolveDirectOrGroupChannelId(params.context),
49
+ currentThreadTs: params.context.ReplyToId,
50
+ hasRepliedRef: params.hasRepliedRef,
51
+ };
52
+ }
19
53
  // Channel docks: lightweight channel metadata/behavior for shared code paths.
20
54
  //
21
55
  // Rules:
@@ -48,7 +82,7 @@ const DOCKS = {
48
82
  resolveToolPolicy: resolveTelegramGroupToolPolicy,
49
83
  },
50
84
  threading: {
51
- resolveReplyToMode: ({ cfg }) => cfg.channels?.telegram?.replyToMode ?? "first",
85
+ resolveReplyToMode: ({ cfg }) => cfg.channels?.telegram?.replyToMode ?? "off",
52
86
  buildToolContext: ({ context, hasRepliedRef }) => {
53
87
  const threadId = context.MessageThreadId ?? context.ReplyToId;
54
88
  return {
@@ -83,13 +117,14 @@ const DOCKS = {
83
117
  groups: {
84
118
  resolveRequireMention: resolveWhatsAppGroupRequireMention,
85
119
  resolveToolPolicy: resolveWhatsAppGroupToolPolicy,
86
- resolveGroupIntroHint: () => "WhatsApp IDs: SenderId is the participant JID; [message_id: ...] is the message id for reactions (use SenderId as participant).",
120
+ resolveGroupIntroHint: () => "WhatsApp IDs: SenderId is the participant JID (group participant id).",
87
121
  },
88
122
  mentions: {
89
123
  stripPatterns: ({ ctx }) => {
90
124
  const selfE164 = (ctx.To ?? "").replace(/^whatsapp:/, "");
91
- if (!selfE164)
125
+ if (!selfE164) {
92
126
  return [];
127
+ }
93
128
  const escaped = escapeRegExp(selfE164);
94
129
  return [escaped, `@${escaped}`];
95
130
  },
@@ -120,11 +155,14 @@ const DOCKS = {
120
155
  blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1000 },
121
156
  },
122
157
  elevated: {
123
- allowFromFallback: ({ cfg }) => cfg.channels?.discord?.dm?.allowFrom,
158
+ allowFromFallback: ({ cfg }) => cfg.channels?.discord?.allowFrom ?? cfg.channels?.discord?.dm?.allowFrom,
124
159
  },
125
160
  config: {
126
- resolveAllowFrom: ({ cfg, accountId }) => (resolveDiscordAccount({ cfg, accountId }).config.dm?.allowFrom ?? []).map((entry) => String(entry)),
127
- formatAllowFrom: ({ allowFrom }) => formatLower(allowFrom),
161
+ resolveAllowFrom: ({ cfg, accountId }) => {
162
+ const account = resolveDiscordAccount({ cfg, accountId });
163
+ return (account.config.allowFrom ?? account.config.dm?.allowFrom ?? []).map((entry) => String(entry));
164
+ },
165
+ formatAllowFrom: ({ allowFrom }) => formatDiscordAllowFrom(allowFrom),
128
166
  },
129
167
  groups: {
130
168
  resolveRequireMention: resolveDiscordGroupRequireMention,
@@ -142,6 +180,65 @@ const DOCKS = {
142
180
  }),
143
181
  },
144
182
  },
183
+ irc: {
184
+ id: "irc",
185
+ capabilities: {
186
+ chatTypes: ["direct", "group"],
187
+ media: true,
188
+ blockStreaming: true,
189
+ },
190
+ outbound: { textChunkLimit: 350 },
191
+ streaming: {
192
+ blockStreamingCoalesceDefaults: { minChars: 300, idleMs: 1000 },
193
+ },
194
+ config: {
195
+ resolveAllowFrom: ({ cfg, accountId }) => {
196
+ const channel = cfg.channels?.irc;
197
+ const normalized = normalizeAccountId(accountId);
198
+ const account = channel?.accounts?.[normalized] ??
199
+ channel?.accounts?.[Object.keys(channel?.accounts ?? {}).find((key) => key.toLowerCase() === normalized.toLowerCase()) ?? ""];
200
+ return (account?.allowFrom ?? channel?.allowFrom ?? []).map((entry) => String(entry));
201
+ },
202
+ formatAllowFrom: ({ allowFrom }) => allowFrom
203
+ .map((entry) => String(entry).trim())
204
+ .filter(Boolean)
205
+ .map((entry) => entry
206
+ .replace(/^irc:/i, "")
207
+ .replace(/^user:/i, "")
208
+ .toLowerCase()),
209
+ },
210
+ groups: {
211
+ resolveRequireMention: ({ cfg, accountId, groupId }) => {
212
+ if (!groupId) {
213
+ return true;
214
+ }
215
+ return resolveChannelGroupRequireMention({
216
+ cfg,
217
+ channel: "irc",
218
+ groupId,
219
+ accountId,
220
+ groupIdCaseInsensitive: true,
221
+ });
222
+ },
223
+ resolveToolPolicy: ({ cfg, accountId, groupId, senderId, senderName, senderUsername }) => {
224
+ if (!groupId) {
225
+ return undefined;
226
+ }
227
+ // IRC supports per-channel tool policies. Prefer the shared resolver so
228
+ // toolsBySender is honored consistently across surfaces.
229
+ return resolveChannelGroupToolsPolicy({
230
+ cfg,
231
+ channel: "irc",
232
+ groupId,
233
+ accountId,
234
+ groupIdCaseInsensitive: true,
235
+ senderId,
236
+ senderName,
237
+ senderUsername,
238
+ });
239
+ },
240
+ },
241
+ },
145
242
  googlechat: {
146
243
  id: "googlechat",
147
244
  capabilities: {
@@ -199,16 +296,22 @@ const DOCKS = {
199
296
  blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1000 },
200
297
  },
201
298
  config: {
202
- resolveAllowFrom: ({ cfg, accountId }) => (resolveSlackAccount({ cfg, accountId }).dm?.allowFrom ?? []).map((entry) => String(entry)),
299
+ resolveAllowFrom: ({ cfg, accountId }) => {
300
+ const account = resolveSlackAccount({ cfg, accountId });
301
+ return (account.config.allowFrom ?? account.dm?.allowFrom ?? []).map((entry) => String(entry));
302
+ },
203
303
  formatAllowFrom: ({ allowFrom }) => formatLower(allowFrom),
204
304
  },
205
305
  groups: {
206
306
  resolveRequireMention: resolveSlackGroupRequireMention,
207
307
  resolveToolPolicy: resolveSlackGroupToolPolicy,
208
308
  },
309
+ mentions: {
310
+ stripPatterns: () => ["<@[^>]+>"],
311
+ },
209
312
  threading: {
210
313
  resolveReplyToMode: ({ cfg, accountId, chatType }) => resolveSlackReplyToMode(resolveSlackAccount({ cfg, accountId }), chatType),
211
- allowTagsWhenOff: true,
314
+ allowExplicitReplyTagsWhenOff: true,
212
315
  buildToolContext: (params) => buildSlackThreadingToolContext(params),
213
316
  },
214
317
  },
@@ -232,15 +335,7 @@ const DOCKS = {
232
335
  .filter(Boolean),
233
336
  },
234
337
  threading: {
235
- buildToolContext: ({ context, hasRepliedRef }) => {
236
- const isDirect = context.ChatType?.toLowerCase() === "direct";
237
- const channelId = (isDirect ? (context.From ?? context.To) : context.To)?.trim() || undefined;
238
- return {
239
- currentChannelId: channelId,
240
- currentThreadTs: context.ReplyToId,
241
- hasRepliedRef,
242
- };
243
- },
338
+ buildToolContext: ({ context, hasRepliedRef }) => buildSignalThreadToolContext({ context, hasRepliedRef }),
244
339
  },
245
340
  },
246
341
  imessage: {
@@ -260,15 +355,7 @@ const DOCKS = {
260
355
  resolveToolPolicy: resolveIMessageGroupToolPolicy,
261
356
  },
262
357
  threading: {
263
- buildToolContext: ({ context, hasRepliedRef }) => {
264
- const isDirect = context.ChatType?.toLowerCase() === "direct";
265
- const channelId = (isDirect ? (context.From ?? context.To) : context.To)?.trim() || undefined;
266
- return {
267
- currentChannelId: channelId,
268
- currentThreadTs: context.ReplyToId,
269
- hasRepliedRef,
270
- };
271
- },
358
+ buildToolContext: ({ context, hasRepliedRef }) => buildIMessageThreadToolContext({ context, hasRepliedRef }),
272
359
  },
273
360
  },
274
361
  };
@@ -303,11 +390,13 @@ function listPluginDockEntries() {
303
390
  for (const entry of registry.channels) {
304
391
  const plugin = entry.plugin;
305
392
  const id = String(plugin.id).trim();
306
- if (!id || seen.has(id))
393
+ if (!id || seen.has(id)) {
307
394
  continue;
395
+ }
308
396
  seen.add(id);
309
- if (CHAT_CHANNEL_ORDER.includes(plugin.id))
397
+ if (CHAT_CHANNEL_ORDER.includes(plugin.id)) {
310
398
  continue;
399
+ }
311
400
  const dock = entry.dock ?? buildDockFromPlugin(plugin);
312
401
  entries.push({ id: plugin.id, dock, order: plugin.meta.order });
313
402
  }
@@ -326,19 +415,22 @@ export function listChannelDocks() {
326
415
  const indexB = CHAT_CHANNEL_ORDER.indexOf(b.id);
327
416
  const orderA = a.order ?? (indexA === -1 ? 999 : indexA);
328
417
  const orderB = b.order ?? (indexB === -1 ? 999 : indexB);
329
- if (orderA !== orderB)
418
+ if (orderA !== orderB) {
330
419
  return orderA - orderB;
420
+ }
331
421
  return String(a.id).localeCompare(String(b.id));
332
422
  });
333
423
  return combined.map((entry) => entry.dock);
334
424
  }
335
425
  export function getChannelDock(id) {
336
426
  const core = DOCKS[id];
337
- if (core)
427
+ if (core) {
338
428
  return core;
429
+ }
339
430
  const registry = requireActivePluginRegistry();
340
431
  const pluginEntry = registry.channels.find((entry) => entry.plugin.id === id);
341
- if (!pluginEntry)
432
+ if (!pluginEntry) {
342
433
  return undefined;
434
+ }
343
435
  return pluginEntry.dock ?? buildDockFromPlugin(pluginEntry.plugin);
344
436
  }
@@ -19,14 +19,18 @@ export function createDraftStreamLoop(params) {
19
19
  return;
20
20
  }
21
21
  pendingText = "";
22
- lastSentAt = Date.now();
23
22
  const current = params.sendOrEditStreamMessage(text).finally(() => {
24
23
  if (inFlightPromise === current) {
25
24
  inFlightPromise = undefined;
26
25
  }
27
26
  });
28
27
  inFlightPromise = current;
29
- await current;
28
+ const sent = await current;
29
+ if (sent === false) {
30
+ pendingText = text;
31
+ return;
32
+ }
33
+ lastSentAt = Date.now();
30
34
  if (!pendingText) {
31
35
  return;
32
36
  }
@@ -1,6 +1,7 @@
1
- import { createActionGate, readNumberParam, readStringArrayParam, readStringOrNumberParam, readStringParam, } from "../../../agents/tools/common.js";
1
+ import { readNumberParam, readStringArrayParam, readStringOrNumberParam, readStringParam, } from "../../../agents/tools/common.js";
2
2
  import { handleTelegramAction } from "../../../agents/tools/telegram-actions.js";
3
- import { listEnabledTelegramAccounts } from "../../../telegram/accounts.js";
3
+ import { extractToolSend } from "../../../plugin-sdk/tool-send.js";
4
+ import { createTelegramActionGate, listEnabledTelegramAccounts, } from "../../../telegram/accounts.js";
4
5
  import { isTelegramInlineButtonsEnabled } from "../../../telegram/inline-buttons.js";
5
6
  const providerId = "telegram";
6
7
  function readTelegramSendParams(params) {
@@ -14,6 +15,7 @@ function readTelegramSendParams(params) {
14
15
  const buttons = params.buttons;
15
16
  const asVoice = typeof params.asVoice === "boolean" ? params.asVoice : undefined;
16
17
  const silent = typeof params.silent === "boolean" ? params.silent : undefined;
18
+ const quoteText = readStringParam(params, "quoteText");
17
19
  return {
18
20
  to,
19
21
  content,
@@ -23,42 +25,46 @@ function readTelegramSendParams(params) {
23
25
  buttons,
24
26
  asVoice,
25
27
  silent,
28
+ quoteText: quoteText ?? undefined,
26
29
  };
27
30
  }
28
31
  export const telegramMessageActions = {
29
32
  listActions: ({ cfg }) => {
30
33
  const accounts = listEnabledTelegramAccounts(cfg).filter((account) => account.tokenSource !== "none");
31
- if (accounts.length === 0)
34
+ if (accounts.length === 0) {
32
35
  return [];
33
- const gate = createActionGate(cfg.channels?.telegram?.actions);
36
+ }
37
+ // Union of all accounts' action gates (any account enabling an action makes it available)
38
+ const gates = accounts.map((account) => createTelegramActionGate({ cfg, accountId: account.accountId }));
39
+ const gate = (key, defaultValue = true) => gates.some((g) => g(key, defaultValue));
34
40
  const actions = new Set(["send"]);
35
- if (gate("reactions"))
41
+ if (gate("reactions")) {
36
42
  actions.add("react");
37
- if (gate("deleteMessage"))
43
+ }
44
+ if (gate("deleteMessage")) {
38
45
  actions.add("delete");
39
- if (gate("editMessage"))
46
+ }
47
+ if (gate("editMessage")) {
40
48
  actions.add("edit");
49
+ }
41
50
  if (gate("sticker", false)) {
42
51
  actions.add("sticker");
43
52
  actions.add("sticker-search");
44
53
  }
54
+ if (gate("createForumTopic")) {
55
+ actions.add("topic-create");
56
+ }
45
57
  return Array.from(actions);
46
58
  },
47
59
  supportsButtons: ({ cfg }) => {
48
60
  const accounts = listEnabledTelegramAccounts(cfg).filter((account) => account.tokenSource !== "none");
49
- if (accounts.length === 0)
61
+ if (accounts.length === 0) {
50
62
  return false;
63
+ }
51
64
  return accounts.some((account) => isTelegramInlineButtonsEnabled({ cfg, accountId: account.accountId }));
52
65
  },
53
66
  extractToolSend: ({ args }) => {
54
- const action = typeof args.action === "string" ? args.action.trim() : "";
55
- if (action !== "sendMessage")
56
- return null;
57
- const to = typeof args.to === "string" ? args.to : undefined;
58
- if (!to)
59
- return null;
60
- const accountId = typeof args.accountId === "string" ? args.accountId.trim() : undefined;
61
- return { to, accountId };
67
+ return extractToolSend(args, "sendMessage");
62
68
  },
63
69
  handleAction: async ({ action, params, cfg, accountId }) => {
64
70
  if (action === "send") {
@@ -70,14 +76,16 @@ export const telegramMessageActions = {
70
76
  }, cfg);
71
77
  }
72
78
  if (action === "react") {
73
- const messageId = readStringParam(params, "messageId", {
79
+ const messageId = readStringOrNumberParam(params, "messageId", {
74
80
  required: true,
75
81
  });
76
82
  const emoji = readStringParam(params, "emoji", { allowEmpty: true });
77
83
  const remove = typeof params.remove === "boolean" ? params.remove : undefined;
78
84
  return await handleTelegramAction({
79
85
  action: "react",
80
- chatId: readStringParam(params, "chatId") ?? readStringParam(params, "to", { required: true }),
86
+ chatId: readStringOrNumberParam(params, "chatId") ??
87
+ readStringOrNumberParam(params, "channelId") ??
88
+ readStringParam(params, "to", { required: true }),
81
89
  messageId,
82
90
  emoji,
83
91
  remove,
@@ -144,6 +152,22 @@ export const telegramMessageActions = {
144
152
  accountId: accountId ?? undefined,
145
153
  }, cfg);
146
154
  }
155
+ if (action === "topic-create") {
156
+ const chatId = readStringOrNumberParam(params, "chatId") ??
157
+ readStringOrNumberParam(params, "channelId") ??
158
+ readStringParam(params, "to", { required: true });
159
+ const name = readStringParam(params, "name", { required: true });
160
+ const iconColor = readNumberParam(params, "iconColor", { integer: true });
161
+ const iconCustomEmojiId = readStringParam(params, "iconCustomEmojiId");
162
+ return await handleTelegramAction({
163
+ action: "createForumTopic",
164
+ chatId,
165
+ name,
166
+ iconColor: iconColor ?? undefined,
167
+ iconCustomEmojiId: iconCustomEmojiId ?? undefined,
168
+ accountId: accountId ?? undefined,
169
+ }, cfg);
170
+ }
147
171
  throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
148
172
  },
149
173
  };
@@ -1 +1 @@
1
- export { formatAllowlistMatchMeta } from "../allowlist-match.js";
1
+ export { formatAllowlistMatchMeta, resolveAllowlistMatchSimple } from "../allowlist-match.js";