@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,32 +1,34 @@
1
1
  import { resolveAckReaction } from "../../../agents/identity.js";
2
2
  import { hasControlCommand } from "../../../auto-reply/command-detection.js";
3
3
  import { shouldHandleTextCommands } from "../../../auto-reply/commands-registry.js";
4
- import { formatInboundEnvelope, formatThreadStarterEnvelope, resolveEnvelopeFormatOptions, } from "../../../auto-reply/envelope.js";
4
+ import { formatInboundEnvelope, resolveEnvelopeFormatOptions, } from "../../../auto-reply/envelope.js";
5
5
  import { buildPendingHistoryContextFromMap, recordPendingHistoryEntryIfEnabled, } from "../../../auto-reply/reply/history.js";
6
6
  import { finalizeInboundContext } from "../../../auto-reply/reply/inbound-context.js";
7
7
  import { buildMentionRegexes, matchesMentionWithExplicit, } from "../../../auto-reply/reply/mentions.js";
8
+ import { shouldAckReaction as shouldAckReactionGate, } from "../../../channels/ack-reactions.js";
9
+ import { formatAllowlistMatchMeta } from "../../../channels/allowlist-match.js";
10
+ import { resolveControlCommandGate } from "../../../channels/command-gating.js";
11
+ import { resolveConversationLabel } from "../../../channels/conversation-label.js";
12
+ import { logInboundDrop } from "../../../channels/logging.js";
13
+ import { resolveMentionGatingWithBypass } from "../../../channels/mention-gating.js";
14
+ import { recordInboundSession } from "../../../channels/session.js";
15
+ import { readSessionUpdatedAt, resolveStorePath } from "../../../config/sessions.js";
8
16
  import { logVerbose, shouldLogVerbose } from "../../../globals.js";
9
17
  import { enqueueSystemEvent } from "../../../infra/system-events.js";
10
18
  import { buildPairingReply } from "../../../pairing/pairing-messages.js";
11
19
  import { upsertChannelPairingRequest } from "../../../pairing/pairing-store.js";
12
20
  import { resolveAgentRoute } from "../../../routing/resolve-route.js";
13
21
  import { resolveThreadSessionKeys } from "../../../routing/session-key.js";
14
- import { shouldAckReaction as shouldAckReactionGate, } from "../../../channels/ack-reactions.js";
15
- import { resolveMentionGatingWithBypass } from "../../../channels/mention-gating.js";
16
- import { resolveConversationLabel } from "../../../channels/conversation-label.js";
17
- import { resolveControlCommandGate } from "../../../channels/command-gating.js";
18
- import { logInboundDrop } from "../../../channels/logging.js";
19
- import { formatAllowlistMatchMeta } from "../../../channels/allowlist-match.js";
20
- import { recordInboundSession } from "../../../channels/session.js";
21
- import { readSessionUpdatedAt, resolveStorePath } from "../../../config/sessions.js";
22
22
  import { reactSlackMessage } from "../../actions.js";
23
23
  import { sendMessageSlack } from "../../send.js";
24
24
  import { resolveSlackThreadContext } from "../../threading.js";
25
25
  import { resolveSlackAllowListMatch, resolveSlackUserAllowed } from "../allow-list.js";
26
26
  import { resolveSlackEffectiveAllowFrom } from "../auth.js";
27
27
  import { resolveSlackChannelConfig } from "../channel-config.js";
28
+ import { stripSlackMentionsForCommandDetection } from "../commands.js";
28
29
  import { normalizeSlackChannelType } from "../context.js";
29
- import { resolveSlackMedia, resolveSlackThreadStarter } from "../media.js";
30
+ import { resolveSlackAttachmentContent, resolveSlackMedia, resolveSlackThreadHistory, resolveSlackThreadStarter, } from "../media.js";
31
+ import { resolveSlackRoomContextHints } from "../room-context.js";
30
32
  export async function prepareSlackMessage(params) {
31
33
  const { ctx, account, message, opts } = params;
32
34
  const cfg = ctx.cfg;
@@ -56,8 +58,9 @@ export async function prepareSlackMessage(params) {
56
58
  false;
57
59
  const isBotMessage = Boolean(message.bot_id);
58
60
  if (isBotMessage) {
59
- if (message.user && ctx.botUserId && message.user === ctx.botUserId)
61
+ if (message.user && ctx.botUserId && message.user === ctx.botUserId) {
60
62
  return null;
63
+ }
61
64
  if (!allowBots) {
62
65
  logVerbose(`slack: drop bot message ${message.bot_id ?? "unknown"} (allowBots=false)`);
63
66
  return null;
@@ -137,7 +140,7 @@ export async function prepareSlackMessage(params) {
137
140
  accountId: account.accountId,
138
141
  teamId: ctx.teamId || undefined,
139
142
  peer: {
140
- kind: isDirectMessage ? "dm" : isRoom ? "channel" : "group",
143
+ kind: isDirectMessage ? "direct" : isRoom ? "channel" : "group",
141
144
  id: isDirectMessage ? (message.user ?? "unknown") : message.channel,
142
145
  },
143
146
  });
@@ -187,7 +190,9 @@ export async function prepareSlackMessage(params) {
187
190
  cfg,
188
191
  surface: "slack",
189
192
  });
190
- const hasControlCommandInMessage = hasControlCommand(message.text ?? "", cfg);
193
+ // Strip Slack mentions (<@U123>) before command detection so "@Labrador /new" is recognized
194
+ const textForCommandDetection = stripSlackMentionsForCommandDetection(message.text ?? "");
195
+ const hasControlCommandInMessage = hasControlCommand(textForCommandDetection, cfg);
191
196
  const ownerAuthorized = resolveSlackAllowListMatch({
192
197
  allowList: allowFromLower,
193
198
  id: senderId,
@@ -266,10 +271,28 @@ export async function prepareSlackMessage(params) {
266
271
  token: ctx.botToken,
267
272
  maxBytes: ctx.mediaMaxBytes,
268
273
  });
269
- const rawBody = (message.text ?? "").trim() || media?.placeholder || "";
270
- if (!rawBody)
274
+ // Resolve forwarded message content (text + media) from Slack attachments
275
+ const attachmentContent = await resolveSlackAttachmentContent({
276
+ attachments: message.attachments,
277
+ token: ctx.botToken,
278
+ maxBytes: ctx.mediaMaxBytes,
279
+ });
280
+ // Merge forwarded media into the message's media array
281
+ const mergedMedia = [...(media ?? []), ...(attachmentContent?.media ?? [])];
282
+ const effectiveDirectMedia = mergedMedia.length > 0 ? mergedMedia : null;
283
+ const mediaPlaceholder = effectiveDirectMedia
284
+ ? effectiveDirectMedia.map((m) => m.placeholder).join(" ")
285
+ : undefined;
286
+ const rawBody = [(message.text ?? "").trim(), attachmentContent?.text, mediaPlaceholder]
287
+ .filter(Boolean)
288
+ .join("\n") || "";
289
+ if (!rawBody) {
271
290
  return null;
272
- const ackReaction = resolveAckReaction(cfg, route.agentId);
291
+ }
292
+ const ackReaction = resolveAckReaction(cfg, route.agentId, {
293
+ channel: "slack",
294
+ accountId: account.accountId,
295
+ });
273
296
  const ackReactionValue = ackReaction ?? "";
274
297
  const shouldAckReaction = () => Boolean(ackReaction &&
275
298
  shouldAckReactionGate({
@@ -312,7 +335,10 @@ export async function prepareSlackMessage(params) {
312
335
  GroupSubject: isRoomish ? roomLabel : undefined,
313
336
  From: slackFrom,
314
337
  }) ?? (isDirectMessage ? senderName : roomLabel);
315
- const textWithId = `${rawBody}\n[slack message id: ${message.ts} channel: ${message.channel}]`;
338
+ const threadInfo = isThreadReply && threadTs
339
+ ? ` thread_ts: ${threadTs}${message.parent_user_id ? ` parent_user_id: ${message.parent_user_id}` : ""}`
340
+ : "";
341
+ const textWithId = `${rawBody}\n[slack message id: ${message.ts} channel: ${message.channel}${threadInfo}]`;
316
342
  const storePath = resolveStorePath(ctx.cfg.session?.store, {
317
343
  agentId: route.agentId,
318
344
  });
@@ -350,17 +376,14 @@ export async function prepareSlackMessage(params) {
350
376
  });
351
377
  }
352
378
  const slackTo = isDirectMessage ? `user:${message.user}` : `channel:${message.channel}`;
353
- const channelDescription = [channelInfo?.topic, channelInfo?.purpose]
354
- .map((entry) => entry?.trim())
355
- .filter((entry) => Boolean(entry))
356
- .filter((entry, index, list) => list.indexOf(entry) === index)
357
- .join("\n");
358
- const systemPromptParts = [
359
- channelDescription ? `Channel description: ${channelDescription}` : null,
360
- channelConfig?.systemPrompt?.trim() || null,
361
- ].filter((entry) => Boolean(entry));
362
- const groupSystemPrompt = systemPromptParts.length > 0 ? systemPromptParts.join("\n\n") : undefined;
379
+ const { untrustedChannelMetadata, groupSystemPrompt } = resolveSlackRoomContextHints({
380
+ isRoomish,
381
+ channelInfo,
382
+ channelConfig,
383
+ });
363
384
  let threadStarterBody;
385
+ let threadHistoryBody;
386
+ let threadSessionPreviousTimestamp;
364
387
  let threadLabel;
365
388
  let threadStarterMedia = null;
366
389
  if (isThreadReply && threadTs) {
@@ -370,38 +393,89 @@ export async function prepareSlackMessage(params) {
370
393
  client: ctx.app.client,
371
394
  });
372
395
  if (starter?.text) {
373
- const starterUser = starter.userId ? await ctx.resolveUserName(starter.userId) : null;
374
- const starterName = starterUser?.name ?? starter.userId ?? "Unknown";
375
- const starterWithId = `${starter.text}\n[slack message id: ${starter.ts ?? threadTs} channel: ${message.channel}]`;
376
- threadStarterBody = formatThreadStarterEnvelope({
377
- channel: "Slack",
378
- author: starterName,
379
- timestamp: starter.ts ? Math.round(Number(starter.ts) * 1000) : undefined,
380
- body: starterWithId,
381
- envelope: envelopeOptions,
382
- });
396
+ // Keep thread starter as raw text; metadata is provided out-of-band in the system prompt.
397
+ threadStarterBody = starter.text;
383
398
  const snippet = starter.text.replace(/\s+/g, " ").slice(0, 80);
384
399
  threadLabel = `Slack thread ${roomLabel}${snippet ? `: ${snippet}` : ""}`;
385
400
  // If current message has no files but thread starter does, fetch starter's files
386
- if (!media && starter.files && starter.files.length > 0) {
401
+ if (!effectiveDirectMedia && starter.files && starter.files.length > 0) {
387
402
  threadStarterMedia = await resolveSlackMedia({
388
403
  files: starter.files,
389
404
  token: ctx.botToken,
390
405
  maxBytes: ctx.mediaMaxBytes,
391
406
  });
392
407
  if (threadStarterMedia) {
393
- logVerbose(`slack: hydrated thread starter file ${threadStarterMedia.placeholder} from root message`);
408
+ const starterPlaceholders = threadStarterMedia.map((m) => m.placeholder).join(", ");
409
+ logVerbose(`slack: hydrated thread starter file ${starterPlaceholders} from root message`);
394
410
  }
395
411
  }
396
412
  }
397
413
  else {
398
414
  threadLabel = `Slack thread ${roomLabel}`;
399
415
  }
416
+ // Fetch full thread history for new thread sessions
417
+ // This provides context of previous messages (including bot replies) in the thread
418
+ // Use the thread session key (not base session key) to determine if this is a new session
419
+ const threadInitialHistoryLimit = account.config?.thread?.initialHistoryLimit ?? 20;
420
+ threadSessionPreviousTimestamp = readSessionUpdatedAt({
421
+ storePath,
422
+ sessionKey, // Thread-specific session key
423
+ });
424
+ if (threadInitialHistoryLimit > 0 && !threadSessionPreviousTimestamp) {
425
+ const threadHistory = await resolveSlackThreadHistory({
426
+ channelId: message.channel,
427
+ threadTs,
428
+ client: ctx.app.client,
429
+ currentMessageTs: message.ts,
430
+ limit: threadInitialHistoryLimit,
431
+ });
432
+ if (threadHistory.length > 0) {
433
+ // Batch resolve user names to avoid N sequential API calls
434
+ const uniqueUserIds = [
435
+ ...new Set(threadHistory.map((m) => m.userId).filter((id) => Boolean(id))),
436
+ ];
437
+ const userMap = new Map();
438
+ await Promise.all(uniqueUserIds.map(async (id) => {
439
+ const user = await ctx.resolveUserName(id);
440
+ if (user) {
441
+ userMap.set(id, user);
442
+ }
443
+ }));
444
+ const historyParts = [];
445
+ for (const historyMsg of threadHistory) {
446
+ const msgUser = historyMsg.userId ? userMap.get(historyMsg.userId) : null;
447
+ const msgSenderName = msgUser?.name ?? (historyMsg.botId ? `Bot (${historyMsg.botId})` : "Unknown");
448
+ const isBot = Boolean(historyMsg.botId);
449
+ const role = isBot ? "assistant" : "user";
450
+ const msgWithId = `${historyMsg.text}\n[slack message id: ${historyMsg.ts ?? "unknown"} channel: ${message.channel}]`;
451
+ historyParts.push(formatInboundEnvelope({
452
+ channel: "Slack",
453
+ from: `${msgSenderName} (${role})`,
454
+ timestamp: historyMsg.ts ? Math.round(Number(historyMsg.ts) * 1000) : undefined,
455
+ body: msgWithId,
456
+ chatType: "channel",
457
+ envelope: envelopeOptions,
458
+ }));
459
+ }
460
+ threadHistoryBody = historyParts.join("\n\n");
461
+ logVerbose(`slack: populated thread history with ${threadHistory.length} messages for new session`);
462
+ }
463
+ }
400
464
  }
401
- // Use thread starter media if current message has none
402
- const effectiveMedia = media ?? threadStarterMedia;
465
+ // Use direct media (including forwarded attachment media) if available, else thread starter media
466
+ const effectiveMedia = effectiveDirectMedia ?? threadStarterMedia;
467
+ const firstMedia = effectiveMedia?.[0];
468
+ const inboundHistory = isRoomish && ctx.historyLimit > 0
469
+ ? (ctx.channelHistories.get(historyKey) ?? []).map((entry) => ({
470
+ sender: entry.sender,
471
+ body: entry.body,
472
+ timestamp: entry.timestamp,
473
+ }))
474
+ : undefined;
403
475
  const ctxPayload = finalizeInboundContext({
404
476
  Body: combinedBody,
477
+ BodyForAgent: rawBody,
478
+ InboundHistory: inboundHistory,
405
479
  RawBody: rawBody,
406
480
  CommandBody: rawBody,
407
481
  From: slackFrom,
@@ -412,6 +486,7 @@ export async function prepareSlackMessage(params) {
412
486
  ConversationLabel: envelopeFrom,
413
487
  GroupSubject: isRoomish ? roomLabel : undefined,
414
488
  GroupSystemPrompt: isRoomish ? groupSystemPrompt : undefined,
489
+ UntrustedContext: untrustedChannelMetadata ? [untrustedChannelMetadata] : undefined,
415
490
  SenderName: senderName,
416
491
  SenderId: senderId,
417
492
  Provider: "slack",
@@ -422,12 +497,19 @@ export async function prepareSlackMessage(params) {
422
497
  MessageThreadId: threadContext.messageThreadId,
423
498
  ParentSessionKey: threadKeys.parentSessionKey,
424
499
  ThreadStarterBody: threadStarterBody,
500
+ ThreadHistoryBody: threadHistoryBody,
501
+ IsFirstThreadTurn: isThreadReply && threadTs && !threadSessionPreviousTimestamp ? true : undefined,
425
502
  ThreadLabel: threadLabel,
426
503
  Timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
427
504
  WasMentioned: isRoomish ? effectiveWasMentioned : undefined,
428
- MediaPath: effectiveMedia?.path,
429
- MediaType: effectiveMedia?.contentType,
430
- MediaUrl: effectiveMedia?.path,
505
+ MediaPath: firstMedia?.path,
506
+ MediaType: firstMedia?.contentType,
507
+ MediaUrl: firstMedia?.path,
508
+ MediaPaths: effectiveMedia && effectiveMedia.length > 0 ? effectiveMedia.map((m) => m.path) : undefined,
509
+ MediaUrls: effectiveMedia && effectiveMedia.length > 0 ? effectiveMedia.map((m) => m.path) : undefined,
510
+ MediaTypes: effectiveMedia && effectiveMedia.length > 0
511
+ ? effectiveMedia.map((m) => m.contentType ?? "")
512
+ : undefined,
431
513
  CommandAuthorized: commandAuthorized,
432
514
  OriginatingChannel: "slack",
433
515
  OriginatingTo: slackTo,
@@ -453,8 +535,9 @@ export async function prepareSlackMessage(params) {
453
535
  },
454
536
  });
455
537
  const replyTarget = ctxPayload.To ?? undefined;
456
- if (!replyTarget)
538
+ if (!replyTarget) {
457
539
  return null;
540
+ }
458
541
  if (shouldLogVerbose()) {
459
542
  logVerbose(`slack inbound: channel=${message.channel} from=${slackFrom} preview="${preview}"`);
460
543
  }