@poolzin/pool-bot 2026.2.25 → 2026.2.26

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 (506) hide show
  1. package/dist/acp/event-mapper.js +87 -22
  2. package/dist/acp/meta.js +12 -6
  3. package/dist/agents/agent-paths.js +8 -9
  4. package/dist/agents/agent-scope.js +7 -5
  5. package/dist/agents/auth-profiles/oauth.js +148 -64
  6. package/dist/agents/auth-profiles/session-override.js +13 -7
  7. package/dist/agents/bash-tools.exec-host-gateway.js +14 -4
  8. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  9. package/dist/agents/bedrock-discovery.js +3 -1
  10. package/dist/agents/byteplus-models.js +97 -0
  11. package/dist/agents/chutes-oauth.js +1 -0
  12. package/dist/agents/cli-runner/helpers.js +4 -0
  13. package/dist/agents/compaction.js +41 -14
  14. package/dist/agents/doubao-models.js +121 -0
  15. package/dist/agents/failover-error.js +2 -0
  16. package/dist/agents/huggingface-models.js +5 -3
  17. package/dist/agents/live-model-filter.js +5 -0
  18. package/dist/agents/minimax-vlm.js +10 -8
  19. package/dist/agents/model-auth.js +6 -0
  20. package/dist/agents/model-catalog.js +3 -1
  21. package/dist/agents/model-selection.js +7 -1
  22. package/dist/agents/models-config.providers.js +93 -11
  23. package/dist/agents/ollama-stream.js +117 -4
  24. package/dist/agents/opencode-zen-models.js +22 -11
  25. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  26. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  27. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  28. package/dist/agents/pi-embedded-helpers.js +1 -1
  29. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  30. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  31. package/dist/agents/pi-embedded-runner/google.js +20 -8
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  33. package/dist/agents/pi-embedded-runner/run.js +71 -12
  34. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  35. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  36. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  37. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  38. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  39. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  40. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  41. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  42. package/dist/agents/pi-embedded-subscribe.js +9 -4
  43. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  44. package/dist/agents/pi-embedded-utils.js +3 -0
  45. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  46. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  47. package/dist/agents/pi-settings.js +40 -0
  48. package/dist/agents/pi-tools.policy.js +2 -1
  49. package/dist/agents/provider/config-loader.js +1 -1
  50. package/dist/agents/sandbox/browser.js +170 -33
  51. package/dist/agents/sandbox/config-hash.js +14 -27
  52. package/dist/agents/sandbox/config.js +21 -2
  53. package/dist/agents/sandbox/constants.js +2 -0
  54. package/dist/agents/sandbox/docker.js +16 -2
  55. package/dist/agents/sandbox/novnc-auth.js +62 -0
  56. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  57. package/dist/agents/sandbox/shared.js +10 -6
  58. package/dist/agents/sandbox-paths.js +24 -11
  59. package/dist/agents/schema/clean-for-gemini.js +132 -85
  60. package/dist/agents/session-slug.js +10 -5
  61. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  62. package/dist/agents/session-tool-result-guard.js +3 -1
  63. package/dist/agents/session-transcript-repair.js +40 -6
  64. package/dist/agents/skills/bundled-dir.js +19 -5
  65. package/dist/agents/skills/env-overrides.js +124 -43
  66. package/dist/agents/skills/frontmatter.js +6 -6
  67. package/dist/agents/skills/plugin-skills.js +14 -7
  68. package/dist/agents/skills/workspace.js +1 -0
  69. package/dist/agents/subagent-announce.js +251 -49
  70. package/dist/agents/subagent-lifecycle-events.js +19 -0
  71. package/dist/agents/subagent-registry-cleanup.js +31 -0
  72. package/dist/agents/subagent-registry-completion.js +68 -0
  73. package/dist/agents/subagent-registry-queries.js +117 -0
  74. package/dist/agents/subagent-registry-state.js +46 -0
  75. package/dist/agents/subagent-registry.js +252 -221
  76. package/dist/agents/subagent-registry.store.js +1 -0
  77. package/dist/agents/subagent-registry.types.js +1 -0
  78. package/dist/agents/subagent-spawn.js +195 -7
  79. package/dist/agents/system-prompt.js +22 -6
  80. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  81. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  82. package/dist/agents/timeout.js +18 -6
  83. package/dist/agents/tool-call-id.js +1 -1
  84. package/dist/agents/tool-display-common.js +162 -29
  85. package/dist/agents/tool-images.js +82 -9
  86. package/dist/agents/tool-policy.js +51 -26
  87. package/dist/agents/tools/browser-tool.js +2 -2
  88. package/dist/agents/tools/canvas-tool.js +27 -1
  89. package/dist/agents/tools/common.js +45 -0
  90. package/dist/agents/tools/discord-actions-guild.js +4 -1
  91. package/dist/agents/tools/gateway-tool.js +3 -1
  92. package/dist/agents/tools/nodes-utils.js +1 -10
  93. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  94. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  95. package/dist/agents/tools/subagents-tool.js +2 -1
  96. package/dist/agents/tools/whatsapp-actions.js +10 -2
  97. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  98. package/dist/agents/transcript-policy.js +22 -8
  99. package/dist/agents/venice-models.js +11 -3
  100. package/dist/auto-reply/commands-registry.data.js +51 -0
  101. package/dist/auto-reply/commands-registry.js +4 -3
  102. package/dist/auto-reply/group-activation.js +10 -5
  103. package/dist/auto-reply/inbound-debounce.js +10 -5
  104. package/dist/auto-reply/reply/abort.js +1 -1
  105. package/dist/auto-reply/reply/agent-runner-execution.js +4 -1
  106. package/dist/auto-reply/reply/bash-command.js +41 -39
  107. package/dist/auto-reply/reply/command-gates.js +25 -0
  108. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  109. package/dist/auto-reply/reply/commands-bash.js +6 -5
  110. package/dist/auto-reply/reply/commands-config.js +30 -28
  111. package/dist/auto-reply/reply/commands-core.js +2 -1
  112. package/dist/auto-reply/reply/commands-info.js +1 -0
  113. package/dist/auto-reply/reply/commands-models.js +65 -14
  114. package/dist/auto-reply/reply/commands-session.js +237 -82
  115. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  116. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  117. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  118. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  119. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  120. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  121. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  122. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  123. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  124. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  125. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  126. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  127. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  128. package/dist/auto-reply/reply/commands-tts.js +10 -5
  129. package/dist/auto-reply/reply/config-value.js +10 -5
  130. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  131. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  132. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  133. package/dist/auto-reply/reply/followup-runner.js +1 -0
  134. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  135. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  136. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  137. package/dist/auto-reply/reply/get-reply.js +71 -12
  138. package/dist/auto-reply/reply/model-selection.js +80 -39
  139. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  140. package/dist/auto-reply/reply/queue/state.js +13 -12
  141. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  142. package/dist/auto-reply/reply/reply-reference.js +9 -8
  143. package/dist/auto-reply/reply/route-reply.js +15 -8
  144. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  145. package/dist/auto-reply/reply/session.js +22 -6
  146. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  147. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  148. package/dist/auto-reply/reply/typing.js +46 -21
  149. package/dist/auto-reply/send-policy.js +14 -7
  150. package/dist/auto-reply/status.js +140 -16
  151. package/dist/auto-reply/templating.js +10 -5
  152. package/dist/auto-reply/thinking.js +7 -16
  153. package/dist/auto-reply/tokens.js +21 -5
  154. package/dist/browser/bridge-server.js +36 -20
  155. package/dist/browser/cdp.helpers.js +7 -14
  156. package/dist/browser/cdp.js +35 -15
  157. package/dist/browser/chrome.profile-decoration.js +7 -4
  158. package/dist/browser/config.js +4 -0
  159. package/dist/browser/extension-relay-auth.js +55 -0
  160. package/dist/browser/extension-relay.js +74 -29
  161. package/dist/browser/navigation-guard.js +9 -1
  162. package/dist/browser/paths.js +77 -0
  163. package/dist/browser/profiles.js +13 -8
  164. package/dist/browser/pw-ai-module.js +10 -5
  165. package/dist/browser/pw-session.js +76 -39
  166. package/dist/browser/pw-tools-core.interactions.js +14 -7
  167. package/dist/browser/pw-tools-core.state.js +12 -6
  168. package/dist/browser/routes/agent.act.js +2 -2
  169. package/dist/browser/server-context.js +7 -0
  170. package/dist/build-info.json +3 -3
  171. package/dist/channels/allow-from.js +2 -1
  172. package/dist/channels/allowlists/resolve-utils.js +43 -19
  173. package/dist/channels/channel-config.js +14 -7
  174. package/dist/channels/draft-stream-loop.js +7 -0
  175. package/dist/channels/model-overrides.js +82 -0
  176. package/dist/channels/plugins/normalize/imessage.js +14 -7
  177. package/dist/channels/plugins/normalize/slack.js +10 -5
  178. package/dist/channels/plugins/normalize/telegram.js +14 -7
  179. package/dist/channels/plugins/outbound/discord.js +80 -8
  180. package/dist/channels/plugins/outbound/signal.js +11 -11
  181. package/dist/channels/plugins/setup-helpers.js +10 -5
  182. package/dist/channels/sender-label.js +14 -7
  183. package/dist/channels/session.js +4 -2
  184. package/dist/channels/status-reactions.js +297 -0
  185. package/dist/cli/banner.js +1 -1
  186. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  187. package/dist/cli/cli-name.js +11 -11
  188. package/dist/cli/cli-utils.js +13 -3
  189. package/dist/cli/command-format.js +1 -1
  190. package/dist/cli/config-cli.js +1 -1
  191. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  192. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  193. package/dist/cli/daemon-cli/restart-health.js +126 -0
  194. package/dist/cli/daemon-cli/status.gather.js +9 -13
  195. package/dist/cli/daemon-cli/status.print.js +2 -10
  196. package/dist/cli/deps.js +27 -22
  197. package/dist/cli/gateway-cli/run-loop.js +23 -5
  198. package/dist/cli/node-cli/register.js +14 -5
  199. package/dist/cli/nodes-media-utils.js +7 -2
  200. package/dist/cli/outbound-send-deps.js +2 -9
  201. package/dist/cli/outbound-send-mapping.js +11 -0
  202. package/dist/cli/pairing-cli.js +40 -14
  203. package/dist/cli/plugins-cli.js +34 -41
  204. package/dist/cli/ports.js +11 -10
  205. package/dist/cli/program/command-registry.js +2 -11
  206. package/dist/cli/program/command-tree.js +16 -0
  207. package/dist/cli/program/preaction.js +13 -9
  208. package/dist/cli/program/register.configure.js +3 -18
  209. package/dist/cli/program/register.maintenance.js +2 -2
  210. package/dist/cli/program/register.onboard.js +2 -0
  211. package/dist/cli/program/register.status-health-sessions.js +16 -17
  212. package/dist/cli/program/register.subclis.js +93 -52
  213. package/dist/cli/route.js +11 -7
  214. package/dist/cli/system-cli.js +36 -46
  215. package/dist/cli/update-cli/shared.js +22 -9
  216. package/dist/cli/update-cli/update-command.js +89 -14
  217. package/dist/cli/update-cli/wizard.js +6 -12
  218. package/dist/commands/agent/run-context.js +18 -5
  219. package/dist/commands/agent/session-store.js +17 -4
  220. package/dist/commands/agent.js +22 -2
  221. package/dist/commands/agents.bindings.js +14 -7
  222. package/dist/commands/agents.commands.add.js +13 -9
  223. package/dist/commands/agents.commands.identity.js +12 -6
  224. package/dist/commands/agents.commands.list.js +11 -6
  225. package/dist/commands/agents.config.js +8 -10
  226. package/dist/commands/agents.providers.js +12 -6
  227. package/dist/commands/auth-choice-options.js +103 -75
  228. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  229. package/dist/commands/auth-choice.apply.js +4 -0
  230. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  231. package/dist/commands/auth-choice.apply.openai.js +3 -1
  232. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  233. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  234. package/dist/commands/channels/remove.js +13 -6
  235. package/dist/commands/channels/shared.js +4 -14
  236. package/dist/commands/configure.commands.js +14 -0
  237. package/dist/commands/configure.gateway.js +2 -4
  238. package/dist/commands/configure.js +1 -1
  239. package/dist/commands/configure.shared.js +11 -0
  240. package/dist/commands/daemon-install-helpers.js +2 -2
  241. package/dist/commands/dashboard.js +12 -10
  242. package/dist/commands/docs.js +14 -8
  243. package/dist/commands/doctor-config-flow.js +11 -9
  244. package/dist/commands/doctor-legacy-config.js +281 -0
  245. package/dist/commands/doctor-state-integrity.js +99 -23
  246. package/dist/commands/doctor-update.js +12 -9
  247. package/dist/commands/models/list.list-command.js +7 -5
  248. package/dist/commands/models/set-image.js +2 -21
  249. package/dist/commands/node-daemon-install-helpers.js +10 -8
  250. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  251. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  252. package/dist/commands/onboard-auth.credentials.js +90 -13
  253. package/dist/commands/onboard-auth.js +1 -1
  254. package/dist/commands/onboard-auth.models.js +6 -5
  255. package/dist/commands/onboard-hooks.js +1 -1
  256. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  257. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  258. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  259. package/dist/commands/onboard-remote.js +14 -7
  260. package/dist/commands/onboard.js +11 -13
  261. package/dist/commands/sandbox-display.js +6 -5
  262. package/dist/commands/status-all/diagnosis.js +14 -10
  263. package/dist/commands/status-all/format.js +1 -0
  264. package/dist/commands/status.gateway-probe.js +1 -16
  265. package/dist/commands/systemd-linger.js +12 -6
  266. package/dist/config/agent-limits.js +2 -0
  267. package/dist/config/commands.js +30 -16
  268. package/dist/config/config-paths.js +9 -11
  269. package/dist/config/defaults.js +22 -2
  270. package/dist/config/discord-preview-streaming.js +104 -0
  271. package/dist/config/env-vars.js +37 -8
  272. package/dist/config/includes.js +4 -0
  273. package/dist/config/io.js +97 -12
  274. package/dist/config/legacy.migrations.part-1.js +189 -78
  275. package/dist/config/legacy.shared.js +3 -1
  276. package/dist/config/merge-patch.js +4 -0
  277. package/dist/config/prototype-keys.js +4 -0
  278. package/dist/config/schema.help.js +44 -7
  279. package/dist/config/schema.labels.js +38 -6
  280. package/dist/config/sessions/delivery-info.js +10 -3
  281. package/dist/config/sessions/main-session.js +10 -5
  282. package/dist/config/sessions/session-file.js +33 -0
  283. package/dist/config/sessions/session-key.js +10 -5
  284. package/dist/config/sessions/store.js +1 -1
  285. package/dist/config/sessions.js +1 -0
  286. package/dist/config/zod-schema.agent-runtime.js +11 -0
  287. package/dist/config/zod-schema.js +148 -13
  288. package/dist/config/zod-schema.providers-core.js +78 -4
  289. package/dist/config/zod-schema.providers.js +6 -1
  290. package/dist/config/zod-schema.session.js +41 -2
  291. package/dist/cron/run-log.js +3 -0
  292. package/dist/cron/schedule.js +21 -10
  293. package/dist/cron/service/ops.js +35 -21
  294. package/dist/cron/service/timer.js +116 -16
  295. package/dist/cron/stagger.js +3 -1
  296. package/dist/discord/api.js +12 -6
  297. package/dist/discord/draft-chunking.js +22 -0
  298. package/dist/discord/draft-stream.js +124 -0
  299. package/dist/discord/monitor/agent-components.js +1 -1
  300. package/dist/discord/monitor/commands.js +5 -0
  301. package/dist/discord/monitor/gateway-plugin.js +2 -1
  302. package/dist/discord/monitor/listeners.js +37 -27
  303. package/dist/discord/monitor/message-handler.js +4 -1
  304. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  305. package/dist/discord/monitor/message-handler.process.js +246 -217
  306. package/dist/discord/monitor/message-utils.js +143 -6
  307. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  308. package/dist/discord/monitor/model-picker.js +651 -0
  309. package/dist/discord/monitor/native-command.js +573 -16
  310. package/dist/discord/monitor/provider.allowlist.js +223 -0
  311. package/dist/discord/monitor/provider.js +275 -347
  312. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  313. package/dist/discord/monitor/reply-delivery.js +123 -16
  314. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  315. package/dist/discord/monitor/thread-bindings.js +4 -0
  316. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  317. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  318. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  319. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  320. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  321. package/dist/discord/resolve-users.js +33 -21
  322. package/dist/discord/send.channels.js +15 -0
  323. package/dist/discord/send.js +3 -2
  324. package/dist/discord/send.outbound.js +82 -26
  325. package/dist/discord/send.permissions.js +83 -30
  326. package/dist/discord/send.reactions.js +8 -4
  327. package/dist/discord/token.js +10 -5
  328. package/dist/discord/voice/command.js +263 -0
  329. package/dist/discord/voice/manager.js +531 -0
  330. package/dist/gateway/auth.js +34 -10
  331. package/dist/gateway/call.js +4 -16
  332. package/dist/gateway/client.js +28 -4
  333. package/dist/gateway/config-reload.js +3 -4
  334. package/dist/gateway/control-ui.js +219 -96
  335. package/dist/gateway/hooks-mapping.js +88 -38
  336. package/dist/gateway/http-auth-helpers.js +3 -2
  337. package/dist/gateway/http-endpoint-helpers.js +1 -0
  338. package/dist/gateway/net.js +54 -12
  339. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  340. package/dist/gateway/node-registry.js +10 -5
  341. package/dist/gateway/openai-http.js +1 -0
  342. package/dist/gateway/openresponses-http.js +1 -0
  343. package/dist/gateway/origin-check.js +1 -18
  344. package/dist/gateway/protocol/index.js +4 -3
  345. package/dist/gateway/protocol/schema/cron.js +1 -0
  346. package/dist/gateway/protocol/schema/devices.js +1 -0
  347. package/dist/gateway/protocol/schema/protocol-schemas.js +2 -1
  348. package/dist/gateway/protocol/schema/sessions.js +6 -0
  349. package/dist/gateway/role-policy.js +17 -0
  350. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  351. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  352. package/dist/gateway/server-chat.js +83 -25
  353. package/dist/gateway/server-constants.js +10 -9
  354. package/dist/gateway/server-cron.js +1 -0
  355. package/dist/gateway/server-http.js +16 -7
  356. package/dist/gateway/server-maintenance.js +20 -5
  357. package/dist/gateway/server-methods/chat.js +10 -6
  358. package/dist/gateway/server-methods/config.js +12 -14
  359. package/dist/gateway/server-methods/devices.js +17 -3
  360. package/dist/gateway/server-methods/models.js +11 -1
  361. package/dist/gateway/server-methods/sessions.js +64 -8
  362. package/dist/gateway/server-methods/usage.js +162 -75
  363. package/dist/gateway/server-node-events.js +29 -0
  364. package/dist/gateway/server-runtime-config.js +34 -13
  365. package/dist/gateway/server-startup-memory.js +17 -11
  366. package/dist/gateway/session-utils.fs.js +32 -34
  367. package/dist/gateway/sessions-resolve.js +17 -5
  368. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  369. package/dist/gateway/tools-invoke-http.js +21 -10
  370. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  371. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  372. package/dist/hooks/bundled/session-memory/handler.js +6 -5
  373. package/dist/hooks/frontmatter.js +6 -6
  374. package/dist/hooks/gmail-watcher.js +11 -6
  375. package/dist/hooks/internal-hooks.js +11 -1
  376. package/dist/hooks/llm-slug-generator.js +4 -1
  377. package/dist/hooks/workspace.js +47 -17
  378. package/dist/imessage/accounts.js +9 -20
  379. package/dist/imessage/monitor/inbound-processing.js +2 -1
  380. package/dist/infra/archive.js +174 -73
  381. package/dist/infra/control-ui-assets.js +14 -6
  382. package/dist/infra/device-pairing.js +108 -29
  383. package/dist/infra/env.js +10 -5
  384. package/dist/infra/exec-approvals-allowlist.js +122 -0
  385. package/dist/infra/exec-approvals-analysis.js +34 -3
  386. package/dist/infra/exec-approvals.js +5 -17
  387. package/dist/infra/exec-safe-bin-policy.js +53 -45
  388. package/dist/infra/fs-safe.js +71 -39
  389. package/dist/infra/gateway-lock.js +6 -2
  390. package/dist/infra/heartbeat-wake.js +6 -12
  391. package/dist/infra/host-env-security-policy.json +19 -0
  392. package/dist/infra/host-env-security.js +66 -0
  393. package/dist/infra/net/ssrf.js +131 -38
  394. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  395. package/dist/infra/outbound/channel-selection.js +12 -6
  396. package/dist/infra/outbound/envelope.js +1 -1
  397. package/dist/infra/outbound/format.js +12 -6
  398. package/dist/infra/outbound/payloads.js +14 -7
  399. package/dist/infra/outbound/session-binding-service.js +123 -0
  400. package/dist/infra/path-guards.js +25 -0
  401. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  402. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  403. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  404. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  405. package/dist/infra/retry-policy.js +4 -2
  406. package/dist/infra/retry.js +9 -5
  407. package/dist/infra/session-cost-usage.js +107 -59
  408. package/dist/infra/session-maintenance-warning.js +3 -1
  409. package/dist/infra/shell-env.js +98 -34
  410. package/dist/infra/ssh-config.js +12 -6
  411. package/dist/infra/system-run-command.js +49 -4
  412. package/dist/infra/update-channels.js +10 -5
  413. package/dist/line/accounts.js +5 -7
  414. package/dist/line/bot-access.js +8 -20
  415. package/dist/line/bot-handlers.js +3 -1
  416. package/dist/link-understanding/detect.js +15 -7
  417. package/dist/media/constants.js +15 -6
  418. package/dist/media/image-ops.js +7 -0
  419. package/dist/media/local-roots.js +3 -2
  420. package/dist/media-understanding/apply.js +4 -1
  421. package/dist/media-understanding/concurrency.js +8 -20
  422. package/dist/memory/backend-config.js +45 -6
  423. package/dist/memory/embeddings.js +10 -4
  424. package/dist/memory/fs-utils.js +23 -0
  425. package/dist/memory/manager-search.js +12 -6
  426. package/dist/memory/manager-sync-ops.js +12 -2
  427. package/dist/memory/qmd-manager.js +466 -53
  428. package/dist/memory/query-expansion.js +167 -3
  429. package/dist/memory/status-format.js +10 -5
  430. package/dist/memory/sync-memory-files.js +1 -1
  431. package/dist/node-host/invoke-system-run.js +281 -0
  432. package/dist/node-host/invoke.js +55 -337
  433. package/dist/pairing/pairing-store.js +22 -0
  434. package/dist/plugin-sdk/allow-from.js +1 -1
  435. package/dist/plugin-sdk/command-auth.js +3 -1
  436. package/dist/plugin-sdk/index.js +6 -3
  437. package/dist/plugin-sdk/webhook-targets.js +32 -0
  438. package/dist/plugins/bundled-dir.js +9 -6
  439. package/dist/plugins/hooks.js +50 -0
  440. package/dist/plugins/install.js +28 -16
  441. package/dist/plugins/runtime.js +3 -17
  442. package/dist/plugins/update.js +78 -12
  443. package/dist/process/spawn-utils.js +14 -7
  444. package/dist/providers/github-copilot-token.js +11 -6
  445. package/dist/providers/qwen-portal-oauth.js +14 -6
  446. package/dist/routing/account-id.js +30 -0
  447. package/dist/routing/resolve-route.js +3 -7
  448. package/dist/routing/session-key.js +2 -16
  449. package/dist/security/audit-channel.js +93 -2
  450. package/dist/security/audit-extra.async.js +159 -5
  451. package/dist/security/audit-extra.js +1 -1
  452. package/dist/security/audit-extra.sync.js +85 -6
  453. package/dist/security/audit.js +40 -4
  454. package/dist/security/dm-policy-shared.js +44 -0
  455. package/dist/security/external-content.js +26 -6
  456. package/dist/shared/entry-status.js +6 -0
  457. package/dist/shared/frontmatter.js +5 -5
  458. package/dist/shared/node-match.js +11 -4
  459. package/dist/shared/operator-scope-compat.js +8 -3
  460. package/dist/signal/accounts.js +7 -20
  461. package/dist/signal/monitor/event-handler.js +3 -1
  462. package/dist/slack/accounts.js +6 -19
  463. package/dist/slack/actions.js +11 -3
  464. package/dist/slack/monitor/auth.js +1 -1
  465. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  466. package/dist/slack/monitor/replies.js +15 -7
  467. package/dist/slack/monitor/slash.js +22 -13
  468. package/dist/slack/resolve-channels.js +10 -5
  469. package/dist/slack/send.js +102 -12
  470. package/dist/slack/stream-mode.js +10 -0
  471. package/dist/slack/streaming.js +4 -2
  472. package/dist/telegram/accounts.js +19 -14
  473. package/dist/telegram/bot/helpers.js +3 -5
  474. package/dist/telegram/bot-access.js +35 -36
  475. package/dist/telegram/bot-handlers.js +120 -148
  476. package/dist/telegram/bot-message-context.js +68 -9
  477. package/dist/telegram/bot-message-dispatch.js +155 -90
  478. package/dist/telegram/bot-native-commands.js +16 -0
  479. package/dist/telegram/draft-stream.js +14 -1
  480. package/dist/telegram/inline-buttons.js +5 -15
  481. package/dist/telegram/monitor.js +11 -7
  482. package/dist/telegram/network-config.js +19 -7
  483. package/dist/telegram/send.js +3 -2
  484. package/dist/telegram/sent-message-cache.js +5 -6
  485. package/dist/telegram/status-reaction-variants.js +208 -0
  486. package/dist/telegram/sticker-cache.js +11 -9
  487. package/dist/terminal/theme.js +12 -12
  488. package/dist/tts/tts.js +80 -567
  489. package/dist/tui/components/chat-log.js +41 -8
  490. package/dist/tui/theme/theme.js +10 -12
  491. package/dist/tui/tui-local-shell.js +16 -6
  492. package/dist/tui/tui.js +58 -6
  493. package/dist/utils/account-id.js +2 -4
  494. package/dist/utils/boolean.js +10 -5
  495. package/dist/utils/directive-tags.js +11 -0
  496. package/dist/utils/queue-helpers.js +67 -12
  497. package/dist/web/auto-reply/deliver-reply.js +8 -4
  498. package/dist/web/auto-reply/mentions.js +10 -5
  499. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  500. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  501. package/dist/web/inbound/access-control.js +5 -2
  502. package/dist/web/login-qr.js +12 -6
  503. package/dist/web/media.js +123 -16
  504. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  505. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  506. package/package.json +1 -1
@@ -4,20 +4,51 @@ import { AssistantMessageComponent } from "./assistant-message.js";
4
4
  import { ToolExecutionComponent } from "./tool-execution.js";
5
5
  import { UserMessageComponent } from "./user-message.js";
6
6
  export class ChatLog extends Container {
7
+ maxComponents;
7
8
  toolById = new Map();
8
9
  streamingRuns = new Map();
9
10
  toolsExpanded = false;
11
+ constructor(maxComponents = 180) {
12
+ super();
13
+ this.maxComponents = Math.max(20, Math.floor(maxComponents));
14
+ }
15
+ dropComponentReferences(component) {
16
+ for (const [toolId, tool] of this.toolById.entries()) {
17
+ if (tool === component) {
18
+ this.toolById.delete(toolId);
19
+ }
20
+ }
21
+ for (const [runId, message] of this.streamingRuns.entries()) {
22
+ if (message === component) {
23
+ this.streamingRuns.delete(runId);
24
+ }
25
+ }
26
+ }
27
+ pruneOverflow() {
28
+ while (this.children.length > this.maxComponents) {
29
+ const oldest = this.children[0];
30
+ if (!oldest) {
31
+ return;
32
+ }
33
+ this.removeChild(oldest);
34
+ this.dropComponentReferences(oldest);
35
+ }
36
+ }
37
+ append(component) {
38
+ this.addChild(component);
39
+ this.pruneOverflow();
40
+ }
10
41
  clearAll() {
11
42
  this.clear();
12
43
  this.toolById.clear();
13
44
  this.streamingRuns.clear();
14
45
  }
15
46
  addSystem(text) {
16
- this.addChild(new Spacer(1));
17
- this.addChild(new Text(theme.system(text), 1, 0));
47
+ this.append(new Spacer(1));
48
+ this.append(new Text(theme.system(text), 1, 0));
18
49
  }
19
50
  addUser(text) {
20
- this.addChild(new UserMessageComponent(text));
51
+ this.append(new UserMessageComponent(text));
21
52
  }
22
53
  resolveRunId(runId) {
23
54
  return runId ?? "default";
@@ -25,7 +56,7 @@ export class ChatLog extends Container {
25
56
  startAssistant(text, runId) {
26
57
  const component = new AssistantMessageComponent(text);
27
58
  this.streamingRuns.set(this.resolveRunId(runId), component);
28
- this.addChild(component);
59
+ this.append(component);
29
60
  return component;
30
61
  }
31
62
  updateAssistant(text, runId) {
@@ -45,7 +76,7 @@ export class ChatLog extends Container {
45
76
  this.streamingRuns.delete(effectiveRunId);
46
77
  return;
47
78
  }
48
- this.addChild(new AssistantMessageComponent(text));
79
+ this.append(new AssistantMessageComponent(text));
49
80
  }
50
81
  dropAssistant(runId) {
51
82
  const effectiveRunId = this.resolveRunId(runId);
@@ -65,19 +96,21 @@ export class ChatLog extends Container {
65
96
  const component = new ToolExecutionComponent(toolName, args);
66
97
  component.setExpanded(this.toolsExpanded);
67
98
  this.toolById.set(toolCallId, component);
68
- this.addChild(component);
99
+ this.append(component);
69
100
  return component;
70
101
  }
71
102
  updateToolArgs(toolCallId, args) {
72
103
  const existing = this.toolById.get(toolCallId);
73
- if (!existing)
104
+ if (!existing) {
74
105
  return;
106
+ }
75
107
  existing.setArgs(args);
76
108
  }
77
109
  updateToolResult(toolCallId, result, opts) {
78
110
  const existing = this.toolById.get(toolCallId);
79
- if (!existing)
111
+ if (!existing) {
80
112
  return;
113
+ }
81
114
  if (opts?.partial) {
82
115
  existing.setPartialResult(result);
83
116
  return;
@@ -4,20 +4,20 @@ import { createSyntaxTheme } from "./syntax-theme.js";
4
4
  const palette = {
5
5
  text: "#E8E3D5",
6
6
  dim: "#7B7F87",
7
- accent: "#A855F7", // vivid purple (was gold #F6C453)
8
- accentSoft: "#C084FC", // soft purple (was orange #F2A65A)
7
+ accent: "#F6C453",
8
+ accentSoft: "#F2A65A",
9
9
  border: "#3C414B",
10
10
  userBg: "#2B2F36",
11
11
  userText: "#F3EEE0",
12
12
  systemText: "#9BA3B2",
13
- toolPendingBg: "#1F1F2F", // slight purple tint (was teal #1F2A2F)
13
+ toolPendingBg: "#1F2A2F",
14
14
  toolSuccessBg: "#1E2D23",
15
15
  toolErrorBg: "#2F1F1F",
16
- toolTitle: "#A855F7", // vivid purple (was gold #F6C453)
16
+ toolTitle: "#F6C453",
17
17
  toolOutput: "#E1DACB",
18
18
  quote: "#8CC8FF",
19
19
  quoteBorder: "#3B4D6B",
20
- code: "#D4BBFF", // light lavender (was gold #F0C987)
20
+ code: "#F0C987",
21
21
  codeBlock: "#1E232A",
22
22
  codeBorder: "#343A45",
23
23
  link: "#7DD3A5",
@@ -50,6 +50,7 @@ function highlightCode(code, lang) {
50
50
  }
51
51
  export const theme = {
52
52
  fg: fg(palette.text),
53
+ assistantText: (text) => text,
53
54
  dim: fg(palette.dim),
54
55
  accent: fg(palette.accent),
55
56
  accentSoft: fg(palette.accentSoft),
@@ -85,15 +86,16 @@ export const markdownTheme = {
85
86
  underline: (text) => chalk.underline(text),
86
87
  highlightCode,
87
88
  };
88
- export const selectListTheme = {
89
+ const baseSelectListTheme = {
89
90
  selectedPrefix: (text) => fg(palette.accent)(text),
90
91
  selectedText: (text) => chalk.bold(fg(palette.accent)(text)),
91
92
  description: (text) => fg(palette.dim)(text),
92
93
  scrollInfo: (text) => fg(palette.dim)(text),
93
94
  noMatch: (text) => fg(palette.dim)(text),
94
95
  };
96
+ export const selectListTheme = baseSelectListTheme;
95
97
  export const filterableSelectListTheme = {
96
- ...selectListTheme,
98
+ ...baseSelectListTheme,
97
99
  filterLabel: (text) => fg(palette.dim)(text),
98
100
  };
99
101
  export const settingsListTheme = {
@@ -108,11 +110,7 @@ export const editorTheme = {
108
110
  selectList: selectListTheme,
109
111
  };
110
112
  export const searchableSelectListTheme = {
111
- selectedPrefix: (text) => fg(palette.accent)(text),
112
- selectedText: (text) => chalk.bold(fg(palette.accent)(text)),
113
- description: (text) => fg(palette.dim)(text),
114
- scrollInfo: (text) => fg(palette.dim)(text),
115
- noMatch: (text) => fg(palette.dim)(text),
113
+ ...baseSelectListTheme,
116
114
  searchPrompt: (text) => fg(palette.accentSoft)(text),
117
115
  searchInput: (text) => fg(palette.text)(text),
118
116
  matchHighlight: (text) => chalk.bold(fg(palette.accent)(text)),
@@ -9,10 +9,12 @@ export function createLocalShellRunner(deps) {
9
9
  const env = deps.env ?? process.env;
10
10
  const maxChars = deps.maxOutputChars ?? 40_000;
11
11
  const ensureLocalExecAllowed = async () => {
12
- if (localExecAllowed)
12
+ if (localExecAllowed) {
13
13
  return true;
14
- if (localExecAsked)
14
+ }
15
+ if (localExecAsked) {
15
16
  return false;
17
+ }
16
18
  localExecAsked = true;
17
19
  return await new Promise((resolve) => {
18
20
  deps.chatLog.addSystem("Allow local shell commands for this session?");
@@ -49,20 +51,28 @@ export function createLocalShellRunner(deps) {
49
51
  const cmd = line.slice(1);
50
52
  // NOTE: A lone '!' is handled by the submit handler as a normal message.
51
53
  // Keep this guard anyway in case this is called directly.
52
- if (cmd === "")
54
+ if (cmd === "") {
53
55
  return;
56
+ }
54
57
  if (localExecAsked && !localExecAllowed) {
55
58
  deps.chatLog.addSystem("local shell: not enabled for this session");
56
59
  deps.tui.requestRender();
57
60
  return;
58
61
  }
59
62
  const allowed = await ensureLocalExecAllowed();
60
- if (!allowed)
63
+ if (!allowed) {
61
64
  return;
65
+ }
62
66
  deps.chatLog.addSystem(`[local] $ ${cmd}`);
63
67
  deps.tui.requestRender();
68
+ const appendWithCap = (text, chunk) => {
69
+ const combined = text + chunk;
70
+ return combined.length > maxChars ? combined.slice(-maxChars) : combined;
71
+ };
64
72
  await new Promise((resolve) => {
65
73
  const child = spawnCommand(cmd, {
74
+ // Intentionally a shell: this is an operator-only local TUI feature (prefixed with `!`)
75
+ // and is gated behind an explicit in-session approval prompt.
66
76
  shell: true,
67
77
  cwd: getCwd(),
68
78
  env,
@@ -70,10 +80,10 @@ export function createLocalShellRunner(deps) {
70
80
  let stdout = "";
71
81
  let stderr = "";
72
82
  child.stdout.on("data", (buf) => {
73
- stdout += buf.toString("utf8");
83
+ stdout = appendWithCap(stdout, buf.toString("utf8"));
74
84
  });
75
85
  child.stderr.on("data", (buf) => {
76
- stderr += buf.toString("utf8");
86
+ stderr = appendWithCap(stderr, buf.toString("utf8"));
77
87
  });
78
88
  child.on("close", (code, signal) => {
79
89
  const combined = (stdout + (stderr ? (stdout ? "\n" : "") + stderr : ""))
package/dist/tui/tui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CombinedAutocompleteProvider, Container, Loader, ProcessTerminal, Text, TUI, } from "@mariozechner/pi-tui";
1
+ import { CombinedAutocompleteProvider, Container, Key, Loader, matchesKey, ProcessTerminal, Text, TUI, } from "@mariozechner/pi-tui";
2
2
  import { resolveDefaultAgentId } from "../agents/agent-scope.js";
3
3
  import { loadConfig } from "../config/config.js";
4
4
  import { buildAgentMainSessionKey, normalizeAgentId, normalizeMainKey, parseAgentSessionKey, } from "../routing/session-key.js";
@@ -43,13 +43,21 @@ export function createEditorSubmitHandler(params) {
43
43
  }
44
44
  export function shouldEnableWindowsGitBashPasteFallback(params) {
45
45
  const platform = params?.platform ?? process.platform;
46
+ const env = params?.env ?? process.env;
47
+ const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase();
48
+ // Some macOS terminals emit multiline paste as rapid single-line submits.
49
+ // Enable burst coalescing so pasted blocks stay as one user message.
50
+ if (platform === "darwin") {
51
+ if (termProgram.includes("iterm") || termProgram.includes("apple_terminal")) {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
46
56
  if (platform !== "win32") {
47
57
  return false;
48
58
  }
49
- const env = params?.env ?? process.env;
50
59
  const msystem = (env.MSYSTEM ?? "").toUpperCase();
51
60
  const shell = env.SHELL ?? "";
52
- const termProgram = (env.TERM_PROGRAM ?? "").toLowerCase();
53
61
  if (msystem.startsWith("MINGW") || msystem.startsWith("MSYS")) {
54
62
  return true;
55
63
  }
@@ -137,6 +145,36 @@ export function resolveTuiSessionKey(params) {
137
145
  }
138
146
  return `agent:${params.currentAgentId}:${trimmed}`;
139
147
  }
148
+ export function resolveGatewayDisconnectState(reason) {
149
+ const reasonLabel = reason?.trim() ? reason.trim() : "closed";
150
+ if (/pairing required/i.test(reasonLabel)) {
151
+ return {
152
+ connectionStatus: `gateway disconnected: ${reasonLabel}`,
153
+ activityStatus: "pairing required: run poolbot devices list",
154
+ pairingHint: "Pairing required. Run `poolbot devices list`, approve your request ID, then reconnect.",
155
+ };
156
+ }
157
+ return {
158
+ connectionStatus: `gateway disconnected: ${reasonLabel}`,
159
+ activityStatus: "idle",
160
+ };
161
+ }
162
+ export function createBackspaceDeduper(params) {
163
+ const dedupeWindowMs = Math.max(0, Math.floor(params?.dedupeWindowMs ?? 8));
164
+ const now = params?.now ?? (() => Date.now());
165
+ let lastBackspaceAt = -1;
166
+ return (data) => {
167
+ if (!matchesKey(data, Key.backspace)) {
168
+ return data;
169
+ }
170
+ const ts = now();
171
+ if (lastBackspaceAt >= 0 && ts - lastBackspaceAt <= dedupeWindowMs) {
172
+ return "";
173
+ }
174
+ lastBackspaceAt = ts;
175
+ return data;
176
+ };
177
+ }
140
178
  export async function runTui(opts) {
141
179
  const config = loadConfig();
142
180
  const initialSessionInput = (opts.session ?? "").trim();
@@ -155,6 +193,7 @@ export async function runTui(opts) {
155
193
  let wasDisconnected = false;
156
194
  let toolsExpanded = false;
157
195
  let showThinking = false;
196
+ let pairingHintShown = false;
158
197
  const localRunIds = new Set();
159
198
  const deliverDefault = opts.deliver ?? false;
160
199
  const autoMessage = opts.message?.trim();
@@ -308,6 +347,14 @@ export async function runTui(opts) {
308
347
  password: opts.password,
309
348
  });
310
349
  const tui = new TUI(new ProcessTerminal());
350
+ const dedupeBackspace = createBackspaceDeduper();
351
+ tui.addInputListener((data) => {
352
+ const next = dedupeBackspace(data);
353
+ if (next.length === 0) {
354
+ return { consume: true };
355
+ }
356
+ return { data: next };
357
+ });
311
358
  const header = new Text("", 1, 0);
312
359
  const statusContainer = new Container();
313
360
  const footer = new Text("", 1, 0);
@@ -648,6 +695,7 @@ export async function runTui(opts) {
648
695
  };
649
696
  client.onConnected = () => {
650
697
  isConnected = true;
698
+ pairingHintShown = false;
651
699
  const reconnected = wasDisconnected;
652
700
  wasDisconnected = false;
653
701
  setConnectionStatus("connected");
@@ -669,9 +717,13 @@ export async function runTui(opts) {
669
717
  isConnected = false;
670
718
  wasDisconnected = true;
671
719
  historyLoaded = false;
672
- const reasonLabel = reason?.trim() ? reason.trim() : "closed";
673
- setConnectionStatus(`gateway disconnected: ${reasonLabel}`, 5000);
674
- setActivityStatus("idle");
720
+ const disconnectState = resolveGatewayDisconnectState(reason);
721
+ setConnectionStatus(disconnectState.connectionStatus, 5000);
722
+ setActivityStatus(disconnectState.activityStatus);
723
+ if (disconnectState.pairingHint && !pairingHintShown) {
724
+ pairingHintShown = true;
725
+ chatLog.addSystem(disconnectState.pairingHint);
726
+ }
675
727
  updateFooter();
676
728
  tui.requestRender();
677
729
  };
@@ -1,6 +1,4 @@
1
+ import { normalizeOptionalAccountId } from "../routing/account-id.js";
1
2
  export function normalizeAccountId(value) {
2
- if (typeof value !== "string")
3
- return undefined;
4
- const trimmed = value.trim();
5
- return trimmed || undefined;
3
+ return normalizeOptionalAccountId(value);
6
4
  }
@@ -3,20 +3,25 @@ const DEFAULT_FALSY = ["false", "0", "no", "off"];
3
3
  const DEFAULT_TRUTHY_SET = new Set(DEFAULT_TRUTHY);
4
4
  const DEFAULT_FALSY_SET = new Set(DEFAULT_FALSY);
5
5
  export function parseBooleanValue(value, options = {}) {
6
- if (typeof value === "boolean")
6
+ if (typeof value === "boolean") {
7
7
  return value;
8
- if (typeof value !== "string")
8
+ }
9
+ if (typeof value !== "string") {
9
10
  return undefined;
11
+ }
10
12
  const normalized = value.trim().toLowerCase();
11
- if (!normalized)
13
+ if (!normalized) {
12
14
  return undefined;
15
+ }
13
16
  const truthy = options.truthy ?? DEFAULT_TRUTHY;
14
17
  const falsy = options.falsy ?? DEFAULT_FALSY;
15
18
  const truthySet = truthy === DEFAULT_TRUTHY ? DEFAULT_TRUTHY_SET : new Set(truthy);
16
19
  const falsySet = falsy === DEFAULT_FALSY ? DEFAULT_FALSY_SET : new Set(falsy);
17
- if (truthySet.has(normalized))
20
+ if (truthySet.has(normalized)) {
18
21
  return true;
19
- if (falsySet.has(normalized))
22
+ }
23
+ if (falsySet.has(normalized)) {
20
24
  return false;
25
+ }
21
26
  return undefined;
22
27
  }
@@ -6,6 +6,17 @@ function normalizeDirectiveWhitespace(text) {
6
6
  .replace(/[ \t]*\n[ \t]*/g, "\n")
7
7
  .trim();
8
8
  }
9
+ export function stripInlineDirectiveTagsForDisplay(text) {
10
+ if (!text) {
11
+ return { text, changed: false };
12
+ }
13
+ const withoutAudio = text.replace(AUDIO_TAG_RE, "");
14
+ const stripped = withoutAudio.replace(REPLY_TAG_RE, "");
15
+ return {
16
+ text: stripped,
17
+ changed: stripped !== text,
18
+ };
19
+ }
9
20
  export function parseInlineDirectives(text, options = {}) {
10
21
  const { currentMessageId, stripAudioTag = true, stripReplyTags = true } = options;
11
22
  if (!text) {
@@ -1,6 +1,34 @@
1
+ export function clearQueueSummaryState(state) {
2
+ state.droppedCount = 0;
3
+ state.summaryLines = [];
4
+ }
5
+ export function previewQueueSummaryPrompt(params) {
6
+ return buildQueueSummaryPrompt({
7
+ state: {
8
+ dropPolicy: params.state.dropPolicy,
9
+ droppedCount: params.state.droppedCount,
10
+ summaryLines: [...params.state.summaryLines],
11
+ },
12
+ noun: params.noun,
13
+ title: params.title,
14
+ });
15
+ }
16
+ export function applyQueueRuntimeSettings(params) {
17
+ params.target.mode = params.settings.mode;
18
+ params.target.debounceMs =
19
+ typeof params.settings.debounceMs === "number"
20
+ ? Math.max(0, params.settings.debounceMs)
21
+ : params.target.debounceMs;
22
+ params.target.cap =
23
+ typeof params.settings.cap === "number" && params.settings.cap > 0
24
+ ? Math.floor(params.settings.cap)
25
+ : params.target.cap;
26
+ params.target.dropPolicy = params.settings.dropPolicy ?? params.target.dropPolicy;
27
+ }
1
28
  export function elideQueueText(text, limit = 140) {
2
- if (text.length <= limit)
29
+ if (text.length <= limit) {
3
30
  return text;
31
+ }
4
32
  return `${text.slice(0, Math.max(0, limit - 1)).trimEnd()}…`;
5
33
  }
6
34
  export function buildQueueSummaryLine(text, limit = 160) {
@@ -8,16 +36,19 @@ export function buildQueueSummaryLine(text, limit = 160) {
8
36
  return elideQueueText(cleaned, limit);
9
37
  }
10
38
  export function shouldSkipQueueItem(params) {
11
- if (!params.dedupe)
39
+ if (!params.dedupe) {
12
40
  return false;
41
+ }
13
42
  return params.dedupe(params.item, params.items);
14
43
  }
15
44
  export function applyQueueDropPolicy(params) {
16
45
  const cap = params.queue.cap;
17
- if (cap <= 0 || params.queue.items.length < cap)
46
+ if (cap <= 0 || params.queue.items.length < cap) {
18
47
  return true;
19
- if (params.queue.dropPolicy === "new")
48
+ }
49
+ if (params.queue.dropPolicy === "new") {
20
50
  return false;
51
+ }
21
52
  const dropCount = params.queue.items.length - cap + 1;
22
53
  const dropped = params.queue.items.splice(0, dropCount);
23
54
  if (params.queue.dropPolicy === "summarize") {
@@ -26,15 +57,17 @@ export function applyQueueDropPolicy(params) {
26
57
  params.queue.summaryLines.push(buildQueueSummaryLine(params.summarize(item)));
27
58
  }
28
59
  const limit = Math.max(0, params.summaryLimit ?? cap);
29
- while (params.queue.summaryLines.length > limit)
60
+ while (params.queue.summaryLines.length > limit) {
30
61
  params.queue.summaryLines.shift();
62
+ }
31
63
  }
32
64
  return true;
33
65
  }
34
66
  export function waitForQueueDebounce(queue) {
35
67
  const debounceMs = Math.max(0, queue.debounceMs);
36
- if (debounceMs <= 0)
68
+ if (debounceMs <= 0) {
37
69
  return Promise.resolve();
70
+ }
38
71
  return new Promise((resolve) => {
39
72
  const check = () => {
40
73
  const since = Date.now() - queue.lastEnqueuedAt;
@@ -47,6 +80,25 @@ export function waitForQueueDebounce(queue) {
47
80
  check();
48
81
  });
49
82
  }
83
+ export async function drainNextQueueItem(items, run) {
84
+ const next = items[0];
85
+ if (!next) {
86
+ return false;
87
+ }
88
+ await run(next);
89
+ items.shift();
90
+ return true;
91
+ }
92
+ export async function drainCollectItemIfNeeded(params) {
93
+ if (!params.forceIndividualCollect && !params.isCrossChannel) {
94
+ return "skipped";
95
+ }
96
+ if (params.isCrossChannel) {
97
+ params.setForceIndividualCollect?.(true);
98
+ }
99
+ const drained = await drainNextQueueItem(params.items, params.run);
100
+ return drained ? "drained" : "empty";
101
+ }
50
102
  export function buildQueueSummaryPrompt(params) {
51
103
  if (params.state.dropPolicy !== "summarize" || params.state.droppedCount <= 0) {
52
104
  return undefined;
@@ -61,14 +113,14 @@ export function buildQueueSummaryPrompt(params) {
61
113
  lines.push(`- ${line}`);
62
114
  }
63
115
  }
64
- params.state.droppedCount = 0;
65
- params.state.summaryLines = [];
116
+ clearQueueSummaryState(params.state);
66
117
  return lines.join("\n");
67
118
  }
68
119
  export function buildCollectPrompt(params) {
69
120
  const blocks = [params.title];
70
- if (params.summary)
121
+ if (params.summary) {
71
122
  blocks.push(params.summary);
123
+ }
72
124
  params.items.forEach((item, idx) => {
73
125
  blocks.push(params.renderItem(item, idx));
74
126
  });
@@ -79,17 +131,20 @@ export function hasCrossChannelItems(items, resolveKey) {
79
131
  let hasUnkeyed = false;
80
132
  for (const item of items) {
81
133
  const resolved = resolveKey(item);
82
- if (resolved.cross)
134
+ if (resolved.cross) {
83
135
  return true;
136
+ }
84
137
  if (!resolved.key) {
85
138
  hasUnkeyed = true;
86
139
  continue;
87
140
  }
88
141
  keys.add(resolved.key);
89
142
  }
90
- if (keys.size === 0)
143
+ if (keys.size === 0) {
91
144
  return false;
92
- if (hasUnkeyed)
145
+ }
146
+ if (hasUnkeyed) {
93
147
  return true;
148
+ }
94
149
  return keys.size > 1;
95
150
  }
@@ -1,6 +1,8 @@
1
1
  import { chunkMarkdownTextWithMode } from "../../auto-reply/chunk.js";
2
- import { convertMarkdownTables } from "../../markdown/tables.js";
3
2
  import { logVerbose, shouldLogVerbose } from "../../globals.js";
3
+ import { convertMarkdownTables } from "../../markdown/tables.js";
4
+ import { markdownToWhatsApp } from "../../markdown/whatsapp.js";
5
+ import { sleep } from "../../utils.js";
4
6
  import { loadWebMedia } from "../media.js";
5
7
  import { newConnectionId } from "../reconnect.js";
6
8
  import { formatError } from "../session.js";
@@ -11,14 +13,13 @@ export async function deliverWebReply(params) {
11
13
  const replyStarted = Date.now();
12
14
  const tableMode = params.tableMode ?? "code";
13
15
  const chunkMode = params.chunkMode ?? "length";
14
- const convertedText = convertMarkdownTables(replyResult.text || "", tableMode);
16
+ const convertedText = markdownToWhatsApp(convertMarkdownTables(replyResult.text || "", tableMode));
15
17
  const textChunks = chunkMarkdownTextWithMode(convertedText, textLimit, chunkMode);
16
18
  const mediaList = replyResult.mediaUrls?.length
17
19
  ? replyResult.mediaUrls
18
20
  : replyResult.mediaUrl
19
21
  ? [replyResult.mediaUrl]
20
22
  : [];
21
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
22
23
  const sendWithRetry = async (fn, label, maxAttempts = 3) => {
23
24
  let lastErr;
24
25
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -69,7 +70,10 @@ export async function deliverWebReply(params) {
69
70
  for (const [index, mediaUrl] of mediaList.entries()) {
70
71
  const caption = index === 0 ? remainingText.shift() || undefined : undefined;
71
72
  try {
72
- const media = await loadWebMedia(mediaUrl, maxMediaBytes);
73
+ const media = await loadWebMedia(mediaUrl, {
74
+ maxBytes: maxMediaBytes,
75
+ localRoots: params.mediaLocalRoots,
76
+ });
73
77
  if (shouldLogVerbose()) {
74
78
  logVerbose(`Web auto-reply media size: ${(media.buffer.length / (1024 * 1024)).toFixed(2)}MB`);
75
79
  logVerbose(`Web auto-reply media source: ${mediaUrl} (kind ${media.kind})`);
@@ -20,12 +20,14 @@ export function isBotMentionedFromTargets(msg, mentionCfg, targets) {
20
20
  const isSelfChat = isSelfChatMode(targets.selfE164, mentionCfg.allowFrom);
21
21
  const hasMentions = (msg.mentionedJids?.length ?? 0) > 0;
22
22
  if (hasMentions && !isSelfChat) {
23
- if (targets.selfE164 && targets.normalizedMentions.includes(targets.selfE164))
23
+ if (targets.selfE164 && targets.normalizedMentions.includes(targets.selfE164)) {
24
24
  return true;
25
+ }
25
26
  if (targets.selfJid) {
26
27
  // Some mentions use the bare JID; match on E.164 to be safe.
27
- if (targets.normalizedMentions.includes(targets.selfJid))
28
+ if (targets.normalizedMentions.includes(targets.selfJid)) {
28
29
  return true;
30
+ }
29
31
  }
30
32
  // If the message explicitly mentions someone else, do not fall back to regex matches.
31
33
  return false;
@@ -34,19 +36,22 @@ export function isBotMentionedFromTargets(msg, mentionCfg, targets) {
34
36
  // Self-chat mode: ignore WhatsApp @mention JIDs, otherwise @mentioning the owner in group chats triggers the bot.
35
37
  }
36
38
  const bodyClean = clean(msg.body);
37
- if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean)))
39
+ if (mentionCfg.mentionRegexes.some((re) => re.test(bodyClean))) {
38
40
  return true;
41
+ }
39
42
  // Fallback: detect body containing our own number (with or without +, spacing)
40
43
  if (targets.selfE164) {
41
44
  const selfDigits = targets.selfE164.replace(/\D/g, "");
42
45
  if (selfDigits) {
43
46
  const bodyDigits = bodyClean.replace(/[^\d]/g, "");
44
- if (bodyDigits.includes(selfDigits))
47
+ if (bodyDigits.includes(selfDigits)) {
45
48
  return true;
49
+ }
46
50
  const bodyNoSpace = msg.body.replace(/[\s-]/g, "");
47
51
  const pattern = new RegExp(`\\+?${selfDigits}`, "i");
48
- if (pattern.test(bodyNoSpace))
52
+ if (pattern.test(bodyNoSpace)) {
49
53
  return true;
54
+ }
50
55
  }
51
56
  }
52
57
  return false;
@@ -1,11 +1,13 @@
1
1
  import { normalizeE164 } from "../../../utils.js";
2
2
  export function noteGroupMember(groupMemberNames, conversationId, e164, name) {
3
- if (!e164 || !name)
3
+ if (!e164 || !name) {
4
4
  return;
5
+ }
5
6
  const normalized = normalizeE164(e164);
6
7
  const key = normalized ?? e164;
7
- if (!key)
8
+ if (!key) {
8
9
  return;
10
+ }
9
11
  let roster = groupMemberNames.get(conversationId);
10
12
  if (!roster) {
11
13
  roster = new Map();
@@ -19,11 +21,13 @@ export function formatGroupMembers(params) {
19
21
  const ordered = [];
20
22
  if (participants?.length) {
21
23
  for (const entry of participants) {
22
- if (!entry)
24
+ if (!entry) {
23
25
  continue;
26
+ }
24
27
  const normalized = normalizeE164(entry) ?? entry;
25
- if (!normalized || seen.has(normalized))
28
+ if (!normalized || seen.has(normalized)) {
26
29
  continue;
30
+ }
27
31
  seen.add(normalized);
28
32
  ordered.push(normalized);
29
33
  }
@@ -31,19 +35,22 @@ export function formatGroupMembers(params) {
31
35
  if (roster) {
32
36
  for (const entry of roster.keys()) {
33
37
  const normalized = normalizeE164(entry) ?? entry;
34
- if (!normalized || seen.has(normalized))
38
+ if (!normalized || seen.has(normalized)) {
35
39
  continue;
40
+ }
36
41
  seen.add(normalized);
37
42
  ordered.push(normalized);
38
43
  }
39
44
  }
40
45
  if (ordered.length === 0 && fallbackE164) {
41
46
  const normalized = normalizeE164(fallbackE164) ?? fallbackE164;
42
- if (normalized)
47
+ if (normalized) {
43
48
  ordered.push(normalized);
49
+ }
44
50
  }
45
- if (ordered.length === 0)
51
+ if (ordered.length === 0) {
46
52
  return undefined;
53
+ }
47
54
  return ordered
48
55
  .map((entry) => {
49
56
  const name = roster?.get(entry);