@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
@@ -7,23 +7,24 @@ import { formatInboundEnvelope, resolveEnvelopeFormatOptions } from "../auto-rep
7
7
  import { buildPendingHistoryContextFromMap, recordPendingHistoryEntryIfEnabled, } from "../auto-reply/reply/history.js";
8
8
  import { finalizeInboundContext } from "../auto-reply/reply/inbound-context.js";
9
9
  import { buildMentionRegexes, matchesMentionWithExplicit } from "../auto-reply/reply/mentions.js";
10
+ import { shouldAckReaction as shouldAckReactionGate } from "../channels/ack-reactions.js";
11
+ import { resolveControlCommandGate } from "../channels/command-gating.js";
10
12
  import { formatLocationText, toLocationContext } from "../channels/location.js";
13
+ import { logInboundDrop } from "../channels/logging.js";
14
+ import { resolveMentionGatingWithBypass } from "../channels/mention-gating.js";
11
15
  import { recordInboundSession } from "../channels/session.js";
12
- import { formatCliCommand } from "../cli/command-format.js";
13
- import { readSessionUpdatedAt, resolveStorePath } from "../config/sessions.js";
14
16
  import { loadConfig } from "../config/config.js";
17
+ import { readSessionUpdatedAt, resolveStorePath } from "../config/sessions.js";
15
18
  import { logVerbose, shouldLogVerbose } from "../globals.js";
16
19
  import { recordChannelActivity } from "../infra/channel-activity.js";
20
+ import { buildPairingReply } from "../pairing/pairing-messages.js";
21
+ import { upsertChannelPairingRequest } from "../pairing/pairing-store.js";
17
22
  import { resolveAgentRoute } from "../routing/resolve-route.js";
18
23
  import { resolveThreadSessionKeys } from "../routing/session-key.js";
19
- import { shouldAckReaction as shouldAckReactionGate } from "../channels/ack-reactions.js";
20
- import { resolveMentionGatingWithBypass } from "../channels/mention-gating.js";
21
- import { resolveControlCommandGate } from "../channels/command-gating.js";
22
- import { logInboundDrop } from "../channels/logging.js";
23
24
  import { withTelegramApiErrorLogging } from "./api-logging.js";
24
- import { buildGroupLabel, buildSenderLabel, buildSenderName, buildTelegramGroupFrom, buildTelegramGroupPeerId, buildTelegramParentPeer, buildTypingThreadParams, expandTextLinks, normalizeForwardedContext, describeReplyTarget, extractTelegramLocation, hasBotMention, resolveTelegramThreadSpec, } from "./bot/helpers.js";
25
25
  import { firstDefined, isSenderAllowed, normalizeAllowFromWithStore, resolveSenderAllowMatch, } from "./bot-access.js";
26
- import { upsertTelegramPairingRequest } from "./pairing-store.js";
26
+ import { buildGroupLabel, buildSenderLabel, buildSenderName, buildTelegramGroupFrom, buildTelegramGroupPeerId, buildTelegramParentPeer, buildTypingThreadParams, resolveTelegramMediaPlaceholder, expandTextLinks, normalizeForwardedContext, describeReplyTarget, extractTelegramLocation, hasBotMention, resolveTelegramThreadSpec, } from "./bot/helpers.js";
27
+ import { evaluateTelegramGroupBaseAccess } from "./group-access.js";
27
28
  async function resolveStickerVisionSupport(params) {
28
29
  try {
29
30
  const catalog = await loadModelCatalog({ config: params.cfg });
@@ -32,8 +33,9 @@ async function resolveStickerVisionSupport(params) {
32
33
  agentId: params.agentId,
33
34
  });
34
35
  const entry = findModelInCatalog(catalog, defaultModel.provider, defaultModel.model);
35
- if (!entry)
36
+ if (!entry) {
36
37
  return false;
38
+ }
37
39
  return modelSupportsVision(entry);
38
40
  }
39
41
  catch {
@@ -61,17 +63,19 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
61
63
  const { groupConfig, topicConfig } = resolveTelegramGroupConfig(chatId, resolvedThreadId);
62
64
  const peerId = isGroup ? buildTelegramGroupPeerId(chatId, resolvedThreadId) : String(chatId);
63
65
  const parentPeer = buildTelegramParentPeer({ isGroup, resolvedThreadId, chatId });
66
+ // Fresh config for bindings lookup; other routing inputs are payload-derived.
64
67
  const route = resolveAgentRoute({
65
68
  cfg: loadConfig(),
66
69
  channel: "telegram",
67
70
  accountId: account.accountId,
68
71
  peer: {
69
- kind: isGroup ? "group" : "dm",
72
+ kind: isGroup ? "group" : "direct",
70
73
  id: peerId,
71
74
  },
72
75
  parentPeer,
73
76
  });
74
77
  const baseSessionKey = route.sessionKey;
78
+ // DMs: use raw messageThreadId for thread sessions (not forum topic ids)
75
79
  const dmThreadId = threadSpec.scope === "dm" ? threadSpec.id : undefined;
76
80
  const threadKeys = dmThreadId != null
77
81
  ? resolveThreadSessionKeys({ baseSessionKey, threadId: String(dmThreadId) })
@@ -85,14 +89,40 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
85
89
  storeAllowFrom,
86
90
  });
87
91
  const hasGroupAllowOverride = typeof groupAllowOverride !== "undefined";
88
- if (isGroup && groupConfig?.enabled === false) {
89
- logVerbose(`Blocked telegram group ${chatId} (group disabled)`);
90
- return null;
91
- }
92
- if (isGroup && topicConfig?.enabled === false) {
93
- logVerbose(`Blocked telegram topic ${chatId} (${resolvedThreadId ?? "unknown"}) (topic disabled)`);
92
+ const senderId = msg.from?.id ? String(msg.from.id) : "";
93
+ const senderUsername = msg.from?.username ?? "";
94
+ const baseAccess = evaluateTelegramGroupBaseAccess({
95
+ isGroup,
96
+ groupConfig,
97
+ topicConfig,
98
+ hasGroupAllowOverride,
99
+ effectiveGroupAllow,
100
+ senderId,
101
+ senderUsername,
102
+ enforceAllowOverride: true,
103
+ requireSenderForAllowOverride: false,
104
+ });
105
+ if (!baseAccess.allowed) {
106
+ if (baseAccess.reason === "group-disabled") {
107
+ logVerbose(`Blocked telegram group ${chatId} (group disabled)`);
108
+ return null;
109
+ }
110
+ if (baseAccess.reason === "topic-disabled") {
111
+ logVerbose(`Blocked telegram topic ${chatId} (${resolvedThreadId ?? "unknown"}) (topic disabled)`);
112
+ return null;
113
+ }
114
+ logVerbose(`Blocked telegram group sender ${senderId || "unknown"} (group allowFrom override)`);
94
115
  return null;
95
116
  }
117
+ // Compute requireMention early for preflight transcription gating
118
+ const activationOverride = resolveGroupActivation({
119
+ chatId,
120
+ messageThreadId: resolvedThreadId,
121
+ sessionKey: sessionKey,
122
+ agentId: route.agentId,
123
+ });
124
+ const baseRequireMention = resolveGroupRequireMention(chatId);
125
+ const requireMention = firstDefined(activationOverride, topicConfig?.requireMention, groupConfig?.requireMention, baseRequireMention);
96
126
  const sendTyping = async () => {
97
127
  await withTelegramApiErrorLogging({
98
128
  operation: "sendChatAction",
@@ -112,12 +142,13 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
112
142
  };
113
143
  // DM access control (secure defaults): "pairing" (default) / "allowlist" / "open" / "disabled"
114
144
  if (!isGroup) {
115
- if (dmPolicy === "disabled")
145
+ if (dmPolicy === "disabled") {
116
146
  return null;
147
+ }
117
148
  if (dmPolicy !== "open") {
149
+ const senderUsername = msg.from?.username ?? "";
118
150
  const senderUserId = msg.from?.id != null ? String(msg.from.id) : null;
119
151
  const candidate = senderUserId ?? String(chatId);
120
- const senderUsername = msg.from?.username ?? "";
121
152
  const allowMatch = resolveSenderAllowMatch({
122
153
  allow: effectiveDmAllow,
123
154
  senderId: candidate,
@@ -130,11 +161,15 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
130
161
  try {
131
162
  const from = msg.from;
132
163
  const telegramUserId = from?.id ? String(from.id) : candidate;
133
- const { code, created } = await upsertTelegramPairingRequest({
134
- chatId: candidate,
135
- username: from?.username,
136
- firstName: from?.first_name,
137
- lastName: from?.last_name,
164
+ const { code, created } = await upsertChannelPairingRequest({
165
+ channel: "telegram",
166
+ id: telegramUserId,
167
+ accountId: account.accountId,
168
+ meta: {
169
+ username: from?.username,
170
+ firstName: from?.first_name,
171
+ lastName: from?.last_name,
172
+ },
138
173
  });
139
174
  if (created) {
140
175
  logger.info({
@@ -148,16 +183,11 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
148
183
  }, "telegram pairing request");
149
184
  await withTelegramApiErrorLogging({
150
185
  operation: "sendMessage",
151
- fn: () => bot.api.sendMessage(chatId, [
152
- "Poolbot: access not configured.",
153
- "",
154
- `Your Telegram user id: ${telegramUserId}`,
155
- "",
156
- `Pairing code: ${code}`,
157
- "",
158
- "Ask the bot owner to approve with:",
159
- formatCliCommand("poolbot pairing approve telegram <code>"),
160
- ].join("\n")),
186
+ fn: () => bot.api.sendMessage(chatId, buildPairingReply({
187
+ channel: "telegram",
188
+ idLine: `Your Telegram user id: ${telegramUserId}`,
189
+ code,
190
+ })),
161
191
  });
162
192
  }
163
193
  }
@@ -173,19 +203,6 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
173
203
  }
174
204
  }
175
205
  const botUsername = primaryCtx.me?.username?.toLowerCase();
176
- const senderId = msg.from?.id ? String(msg.from.id) : "";
177
- const senderUsername = msg.from?.username ?? "";
178
- if (isGroup && hasGroupAllowOverride) {
179
- const allowed = isSenderAllowed({
180
- allow: effectiveGroupAllow,
181
- senderId,
182
- senderUsername,
183
- });
184
- if (!allowed) {
185
- logVerbose(`Blocked telegram group sender ${senderId || "unknown"} (group allowFrom override)`);
186
- return null;
187
- }
188
- }
189
206
  const allowForCommands = isGroup ? effectiveGroupAllow : effectiveDmAllow;
190
207
  const senderAllowedForCommands = isSenderAllowed({
191
208
  allow: allowForCommands,
@@ -204,19 +221,7 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
204
221
  });
205
222
  const commandAuthorized = commandGate.commandAuthorized;
206
223
  const historyKey = isGroup ? buildTelegramGroupPeerId(chatId, resolvedThreadId) : undefined;
207
- let placeholder = "";
208
- if (msg.photo)
209
- placeholder = "<media:image>";
210
- else if (msg.video)
211
- placeholder = "<media:video>";
212
- else if (msg.video_note)
213
- placeholder = "<media:video>";
214
- else if (msg.audio || msg.voice)
215
- placeholder = "<media:audio>";
216
- else if (msg.document)
217
- placeholder = "<media:document>";
218
- else if (msg.sticker)
219
- placeholder = "<media:sticker>";
224
+ let placeholder = resolveTelegramMediaPlaceholder(msg) ?? "";
220
225
  // Check if sticker has a cached description - if so, use it instead of sending the image
221
226
  const cachedStickerDescription = allMedia[0]?.stickerMetadata?.cachedDescription;
222
227
  const stickerSupportsVision = msg.sticker
@@ -234,14 +239,52 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
234
239
  const locationText = locationData ? formatLocationText(locationData) : undefined;
235
240
  const rawTextSource = msg.text ?? msg.caption ?? "";
236
241
  const rawText = expandTextLinks(rawTextSource, msg.entities ?? msg.caption_entities).trim();
242
+ const hasUserText = Boolean(rawText || locationText);
237
243
  let rawBody = [rawText, locationText].filter(Boolean).join("\n").trim();
238
- if (!rawBody)
244
+ if (!rawBody) {
239
245
  rawBody = placeholder;
240
- if (!rawBody && allMedia.length === 0)
246
+ }
247
+ if (!rawBody && allMedia.length === 0) {
241
248
  return null;
249
+ }
242
250
  let bodyText = rawBody;
251
+ const hasAudio = allMedia.some((media) => media.contentType?.startsWith("audio/"));
252
+ // Preflight audio transcription for mention detection in groups
253
+ // This allows voice notes to be checked for mentions before being dropped
254
+ let preflightTranscript;
255
+ const needsPreflightTranscription = isGroup && requireMention && hasAudio && !hasUserText && mentionRegexes.length > 0;
256
+ if (needsPreflightTranscription) {
257
+ try {
258
+ const { transcribeFirstAudio } = await import("../media-understanding/audio-preflight.js");
259
+ // Build a minimal context for transcription
260
+ const tempCtx = {
261
+ MediaPaths: allMedia.length > 0 ? allMedia.map((m) => m.path) : undefined,
262
+ MediaTypes: allMedia.length > 0
263
+ ? allMedia.map((m) => m.contentType).filter(Boolean)
264
+ : undefined,
265
+ };
266
+ preflightTranscript = await transcribeFirstAudio({
267
+ ctx: tempCtx,
268
+ cfg,
269
+ agentDir: undefined,
270
+ });
271
+ }
272
+ catch (err) {
273
+ logVerbose(`telegram: audio preflight transcription failed: ${String(err)}`);
274
+ }
275
+ }
276
+ // Replace audio placeholder with transcript when preflight succeeds.
277
+ if (hasAudio && bodyText === "<media:audio>" && preflightTranscript) {
278
+ bodyText = preflightTranscript;
279
+ }
280
+ // Build bodyText fallback for messages that still have no text.
243
281
  if (!bodyText && allMedia.length > 0) {
244
- bodyText = `<media:image>${allMedia.length > 1 ? ` (${allMedia.length} images)` : ""}`;
282
+ if (hasAudio) {
283
+ bodyText = preflightTranscript || "<media:audio>";
284
+ }
285
+ else {
286
+ bodyText = `<media:image>${allMedia.length > 1 ? ` (${allMedia.length} images)` : ""}`;
287
+ }
245
288
  }
246
289
  const hasAnyMention = (msg.entities ?? msg.caption_entities ?? []).some((ent) => ent.type === "mention");
247
290
  const explicitlyMentioned = botUsername ? hasBotMention(msg, botUsername) : false;
@@ -253,6 +296,7 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
253
296
  isExplicitlyMentioned: explicitlyMentioned,
254
297
  canResolveExplicit: Boolean(botUsername),
255
298
  },
299
+ transcript: preflightTranscript,
256
300
  });
257
301
  const wasMentioned = options?.forceWasMentioned === true ? true : computedWasMentioned;
258
302
  if (isGroup && commandGate.shouldBlock) {
@@ -264,14 +308,6 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
264
308
  });
265
309
  return null;
266
310
  }
267
- const activationOverride = resolveGroupActivation({
268
- chatId,
269
- messageThreadId: resolvedThreadId,
270
- sessionKey: sessionKey,
271
- agentId: route.agentId,
272
- });
273
- const baseRequireMention = resolveGroupRequireMention(chatId);
274
- const requireMention = firstDefined(activationOverride, topicConfig?.requireMention, groupConfig?.requireMention, baseRequireMention);
275
311
  // Reply-chain detection: replying to a bot message acts like an implicit mention.
276
312
  const botId = primaryCtx.me?.id;
277
313
  const replyFromId = msg.reply_to_message?.from?.id;
@@ -309,7 +345,10 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
309
345
  }
310
346
  }
311
347
  // ACK reactions
312
- const ackReaction = resolveAckReaction(cfg, route.agentId);
348
+ const ackReaction = resolveAckReaction(cfg, route.agentId, {
349
+ channel: "telegram",
350
+ accountId: account.accountId,
351
+ });
313
352
  const removeAckAfterReply = cfg.messages?.removeAckAfterReply ?? false;
314
353
  const shouldAckReaction = () => Boolean(ackReaction &&
315
354
  shouldAckReactionGate({
@@ -404,8 +443,10 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
404
443
  : undefined;
405
444
  const ctxPayload = finalizeInboundContext({
406
445
  Body: combinedBody,
407
- RawBody: rawBody,
446
+ // Agent prompt should be the raw user text only; metadata/context is provided via system prompt.
408
447
  BodyForAgent: bodyText,
448
+ InboundHistory: inboundHistory,
449
+ RawBody: rawBody,
409
450
  CommandBody: commandBody,
410
451
  From: isGroup ? buildTelegramGroupFrom(chatId, resolvedThreadId) : `telegram:${chatId}`,
411
452
  To: `telegram:${chatId}`,
@@ -458,7 +499,7 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
458
499
  Sticker: allMedia[0]?.stickerMetadata,
459
500
  ...(locationData ? toLocationContext(locationData) : undefined),
460
501
  CommandAuthorized: commandAuthorized,
461
- InboundHistory: inboundHistory,
502
+ // For groups: use resolved forum topic id; for DMs: use raw messageThreadId
462
503
  MessageThreadId: threadSpec.id,
463
504
  IsForum: isForum,
464
505
  // Originating channel for reply routing.
@@ -475,6 +516,7 @@ export const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeA
475
516
  channel: "telegram",
476
517
  to: String(chatId),
477
518
  accountId: route.accountId,
519
+ // Preserve DM topic threadId for replies (fixes #8891)
478
520
  threadId: dmThreadId != null ? String(dmThreadId) : undefined,
479
521
  }
480
522
  : undefined,